Purpose of having custom annotations - java

Some projects using of custom annotations as below. For example as below. Please explain me
when should I take decision to have custom annotations.
Role of #Target & #Retention annotation attributes
is it better to use import java.lang.annotation.Target and import java.lang.annotation.Retention or hibernate specific annotations as below
#Entity
#Table(name = "creditCard")
#CreditCardEntity
public class CreditCard implements java.io.Serializable {}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.hibernate.validator.ValidatorClass;
#Target( { ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
public #interface CreditCardEntity {}
}

If you plan to use the same annotations together on more than one place in your code, it's a good idea to use custom annotations. For example, in your case, if you will use #Entity #Table(name = "creditCard") together in another place, it's a good idea to unite them under one annotation like the CreditCardEntity annotation, but if that's the only place you will use those two annotations together (which is more likely in this case), it's unnecessary to make a custom annotation for it.

Related

How to use the value of custom annotation parameter inside the annotation

Want to create annotation which will contain multiple annotations but want to make it more configurable so that it can be more feasible to use in all scenarios
#SpringBootApplication
#ServletComponentScan(basepackages="com.example.commons.traceability")
#ComponentScan(basePackages={
"com.example.commons.security",
"com.example.commons.restTemplate",
"com.example.commons.logging",
})
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Microservice{
String[] scanBasePackages() default {};
}
I want to use this application in Spring Application file but also want to make the componentScan more configurable so that apart from the default packages other package can also me included in the component scan
#Microservice(scanBasePackages={"com.example.myproject"})
public class MySpringApplciation{
public static void main (final String[] args){
// some code
}
}
so as in the above code if I pass value of scanBasePackages so those packages should also be included in the component scan.
Is there any way to include values of scanBasePackages inside componentScan in custom annotation ?
Annotations on (custom) annotations are called meta-annotations.
In short: you're lucky. While Java does not allow this out of the box, Spring has a special annotation for this sort of thing: #AliasFor.
I had a similar question, and I found the answer here.
And here is a good source.
Specifically in your case, try this:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AliasFor;
#SpringBootApplication
#ServletComponentScan(basePackages="com.example.commons.traceability")
#ComponentScan(basePackages={
"com.example.commons.security",
"com.example.commons.restTemplate",
"com.example.commons.logging",
})
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Microservice{
// >>> TRY THIS <<<
#AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
}
(I myself am less lucky, since I need this sort of thing for reducing my JUnit5 boilerplate annotations, and #AliasFor is only meaningful in Spring.)

How to get java type annotation of functional by reflection

According to JSR 308 (Java Type Annotations) it is possible to annotate any type using ElementType.TYPE_USE:
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Target({ TYPE_USE })
#Retention(RUNTIME)
public #interface MyAnnotation {
String value();
}
How to get the annotated value from a function at runtime?
import java.util.function.Consumer;
import org.junit.Assert;
import org.junit.Test;
public class TestFunctionAnnotation {
#Test
public void test() {
Consumer<TestFunctionAnnotation> fun = #MyAnnotation("NoJoke") TestFunctionAnnotation::test;
Assert.assertEquals("NoJoke", fun.getClass().getAnnotatedSuperclass().getAnnotation(MyAnnotation.class));
// expected:<NoJoke> but was:<null>
}
}
Your #MyAnnotation doesn't appear on the class, or the method, but on the use of the type - something that you can't reflect on. Instead, you'd need a hypothetical "reflection" which could examine the code itself, not just the structure of the types.
Instead, you want to either build a compiler plugin which can read that, or add a task listener inside an annotation processor - see https://stackoverflow.com/a/55288602/860630 for some discussion on this. Once you've done that and can read the annotation, you can generate new code which you could then access at runtime, and do whatever it is you are after here.

Custom Class Level Validation - Creating the Annotation

I want to implement a custom validator in a Spring Boot v1.5.14.RELEASE app. First I create a custom constraint annotation:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public interface CreateBook {
}
However, I receive this compilation error:
#Retention not applicable to type
The problem is with how you define a new annotation. It should be like this:
#Retention(RetentionPolicy.RUNTIME)
public #interface CreateBook {
}
Note the # character in #interface

Can't implement generics with java.lang.annotation.Annotation: incompatible types

I am wanting to generically retrieve annotations based on where a provided is retrieving values. Either from a field or getters/setters. So, a provider needs to return information in a Field annotation. There are other annotations planned, so the implementations needs to be generic.
The method is exactly what is in the java.lang.Class class.
import java.lang.annotation.Annotation;
public interface Setter<Instance, Type>
{
<A extends Annotation> A getAnnotation(Class<A> annotationClass);
}
But, when I use the method..
final Field annotation = setter.getAnnotation(Field.class);
I get a complication error..
incompatible types
found : java.lang.annotation.Annotation
required: Field
This makes nearly no sense because Field is an Annotation!
Are there special considerations to give to annotations while implementing generics?
Why isn't this working?? It is exactly like the Java API.
Just for more information, here is the Field annotation.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.METHOD})
public #interface Field
{
/**
* The effective path of the local or result set value to load into the field.
*/
String value() default "";
}

Are annotation class files needed in the runtime class path?

If a class is annotated with an annotation, does the definition of that annotation have to be in the runtime classpath in order to use the class? For example, given the annotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Retention;
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface Component {}
can I execute the program
#Component
public class Test {
public static void main(String[] args) {
System.out.println("It worked!");
}
}
without having Component.class in the classpath? (In my test I could, but is this behavior defined by the spec?)
I ask because there are conflicting claims whether using an annotation from a library creates a dependency on that library.
Runtime annotations are meta information to be processed by annotation processor at the runtime. If there is an access to annotation at runtime, you definitely add annotations in the classpath. For example junit definitely need the annotations in the class path determine test methods.
If there is no processing of annotation is done, there is no need to have it the classpath.
Yes you can execute program without having Component.class in the classpath. More details here: Why doesn't a missing annotation cause a ClassNotFoundException at runtime?

Categories