I've been trying to do some logic upon class loading of an annotation type. Naturally the static block came to my mind.
But unfortunately this isn't allowed, the compile error in Eclipse is:
Syntax error, insert "enum Identifier" to complete EnumHeader
My Annotation declaration is:
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target(FIELD)
@Validate
public @interface StringSize {
int max();
int min() default 0;
static {
Validator.registerCallback(StringSize.class, (Field f, Object parent) -> {
Object o = f.get(parent);
if(!(o instanceof CharSequence))
throw new IllegalAnnotationException("@StringSize allowed on CharSequence fields only.");
CharSequence str = (CharSequence) o;
StringSize size = f.getAnnotation(StringSize.class);
if(str.length() < size.min())
throw new AssertionError(str + " - length < " + size.min());
if(str.length() > size.max())
throw new AssertionError(str + " - length > " + size.max());
});
}
}
What I'm trying to do is build a validator that goes through field after field and check for any illegal value.
Now, this framework is completely unaware of what is considered an 'illegal value' i.e. it is up to any potential user of this framework to create their own rules thus create any number of custom annotations and map it to a callback method that does know how to validate it.
@Validate
is a custom meta-annotation used in the validation framework to mark an annotation as a validator (similar to CDI's @Qualifier
). All the framework does is, when Validator.validate(obj)
is called to scan for all fields if any of its annotations has the meta-annotation @Validate
, look up its correspoding callback method and invoke it with that field passed as argument. The callback throws an exception on any illegal value found.
I am trying to find a generic way to do the annotation-callback mapping, so the end user shouldn't have to manually do the mapping, but rather the author of the custom annotation. So this is what I ended up trying.
Any idea how to overcome this constraint?