I have defined an annotation for validation like this:
#Documented
#Constraint(validatedBy = MyValidator.class)
#Target({ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
public #interface MyCustomValid {
//required methods
}
Now, I want to decide the "validatedBy" class at runtime. Like I have a field in my class:
public class MyClass {
#MyCustomValid
MyObject myObject;
}
How do I pass the ConstraintValidator class at runtime. I have different implementations for different cases.
Annotations are compiled into the code at compile time and they can't change, so you need a hack.
Create a validation class which delegates to another validator. The delegate needs to be created at runtime, using whatever algorithm you design. Note that the code might be used concurrently, so you need a thread-safe initialization.
Related
Since I'm working with a framework that uses the Serializable interface in like every class, I want to make sure that the annotation interfaces in the project I'm working for are serializable as well. However, I can't neither implement nor extend Serializable in any #interface java file. This is why I'm wondering if these files are serializable by default (like enums for example) and if not, if there is a way to implement it in these files. (Even if it isn't an elegant way to code. Just want to know if it's possible in the first place). It's hard to find out where the NotSerializableExceptions come from, since the project has many fields that are not serializable (Lamdas etc.)
The Annotations are mostly structured like this in my case:
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.ANNOTATION_TYPE)
public #interface RandomAnnotation {
//random code
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface RandomA {
// no value
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface RandomB {
// no value
}
}
I have a class with custom annotation for one of class field:
public class Test {
#CustomAnnotation
private String name;
...
}
I just want to know if it possible to get Class<Test> by this annotation? Can't find any suitable api..
public Class<?> getOuterClass(CustomAnnotation annotation) {
...
}
#CustomAnnotation is declared as #Retention(RetentionPolicy.RUNTIME)
No, annotation does not store any data about where it was declared.
Also annotation can work just like any normal interface, so someone can implement annotation in class an make instances of it that were never used as annotations.
You need either include that information yourself, by adding parameter to annotation and then using it #CustomAnn(Test.class) or when reading annotations just remember and include that information yourself in some other object.
This is the first time I create an Annotation Java and I'd like to create a my own annotation then suppress the execution for a test when necessary.
The problem is that I many of my tests I have to use Facebook api, sometimes they don't work so I want an annotation called #Facebook that when added to a test works as #Suppress annotation, so I wrote the following code...that unfortunally doesn't work. Anyone can help me?
#Retention(RetentionPolicy.RUNTIME)
public #interface Facebook {
Suppress notToBeRun() default #Suppress;
}
Java contains a flexible annotation API with numerous application possibilities. First developed to specify enterprise semantics in the Java EE stack (whether a Java-bean is stateless or statefull, singleton, etc.), the annotation interface has now also found common use for Context Dependent Injection (CDI) in Java. Your question addresses how to use the Java annotation API for CDI.
First, you need to define a qualifier interface-class for each specific user-defined CDI-option you want Java to Inject. You want a Facebook-implementation to be loaded by injection. Your interface (Facebook.java) can look as follows:
#Qualifier
#Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
#Documented
#Retention(RetentionPolicy.RUNTIME)
public #interface Facebook {
}
The first term, #Qualifier indicates that you define a new qualifier, actually a unique name (#Facebook) known by the Java injection mechanism.
The #Target annotation indicates that your annotation can precede a Java type declaration, a Java field (specifically a variable declaration) or a method parameter. You can add a fourth qualifier to allow your annotation also to be used before a method, namely ElementType.METHOD.
#Documented defines an annotation that assures that classes using this annotation show this in their generated JavaDoc. #Retention must be set to RetentionPolicy.RUNTIME in order for the annotation to become active when the Java-application is started (deployed, in web application server context).
You now need to define a general Java interface class (SocialMediaService.java), just a plain Java interface:
public interface SocialMediaService {
boolean login(String userId, String password);
void logout();
String searchForMessages(String[] friends);
}
This interface can be implemented in different ways, by means of the implements Java-construct.
Using the previously defined annotation, you can choose
in the Java-code which of the alternative implementations to use.
Here is the Facebook-example of a Java-class (Facebook.java, in a different package than the interface qualifier class, specified above):
#Facebook
public class Facebook implements SocialMediaService {
#Override
public boolean login(String userId, String password) {
...
your application logic
...
return true;
}
#Override
public void logout() {
...
your application logic
...
}
#Override
public String searchForMessages(String[] friends) {
...
your application logic
...
return searchResult;
}
}
You can choose among numerous different implementations #LinkedIn, etc. each with their specific Java implementation class (alternatives to public class Facebook).
In your Java-class you are now ready to use CDI to inject the Java implementation of choice.
Back-end Java-bean (BackendSocialMediaAnalysis.java) where CDI is being applied:
public class BackendSocialMediaAnalysis {
...
#Inject #Facebook
private SocialMediaService genericMediaService;
...
}
Replacing #Facebook by #LinkedIn results in the alternative (LinkedIn) implementation being loaded into genericMediaService.
Guice provides two variations of so-called binding annotations, which seem to really break down to class- and instance-level annotations:
"Class-level":
bind(Service.class).annotatedWith(Red.class).to(RedServiceImpl.class);
#Red
public class SomeService implements Service { ... }
Service redSvc = injector.getInstance(SomeService.class);
"Instance-level":
bind(Service.class).annotatedWith(Names.named("Blue").to(BlueServiceImpl.class);
#Blue blueSvc = injector.getInstance(Service.class);
When is one method preferential over the other? It seems that class-level annotations are more absolute/inflexible than instance-level. Pros/cons/caveats/pitfalls of either method?
I'm not sure I understand your question. Your use of binding annotations is irregular. You wouldn't typically annotate a local variable or a class, but rather fields and parameters.
Your first code example will cause the injector to return SomeService, but not because of your annotation or your binding, but because SomeService is a concrete implementation. Had you asked for this instead:
Service redSvc = injector.getInstance(Service.class);
You will get an error:
1) No implementation for com.example.Service was bound.
while locating com.example.Service
Your second example is also incorrect. If you use Names to define a binding, you must use #Named to access that binding. Using #Blue would cause a compiler error. The correct usage would be #Named(value="Blue").
The common best practice for a binding annotation is this:
#BindingAnnotation
#Target({ FIELD, PARAMETER, METHOD })
#Retention(RUNTIME)
public #interface MyAnno
In that case, both of these would be compile errors:
#Red // not allowed
public class SomeService implements Service { ... }
#Blue // not allowed
blueSvc = injector.getInstance(Service.class);
The only real difference is that in one case you bind for a whole annotation, and in the other case you bind to an annotation with specific arguments. Not all annotations even take arguments, in which case, binding with the annotation class is perfectly normal.
This is regarding use of annotations in Java. I associated an annotation with a method while declaring it in the interface. While implementing, how can I ensure that the annotation is carried along with #Override annotation and if not, it should throw a compilation error?
Thanks.
You can't enforce this in the compiler, no. It is the job of the tools which use those annotations to check all superclasses and interfaces when looking for annotations on a given class.
For example, Spring's AnnotationsUtils takes a class to examine for annotations, and crawls all over its inheritence tree looking for them, because the compiler and JVM does not do this for you.
You can't.
You need to write some code to do this (either on your applciation load time, or using apt)
I had the same scenario, and created an annotation of my own:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.ANNOTATION_TYPE)
public #interface DependsOn {
Class<? extends Annotation>[] value();
/**
* Specifies whether all dependencies are required (default),
* or any one of them suffices
*/
boolean all() default true;
}
and applied it to other annotations, like:
#Retention(value = RetentionPolicy.RUNTIME)
#Target(value = ElementType.TYPE)
#DependsOn(value={Override.class})
public #interface CustomAnnotation {
}
Imporant: have in mind that #Override has a compile-time (SOURCE) retention policy, i.e. it isn't available at run-time.