Java: process annotation inherited from .class file - java

I have an annotation that is inherited and has class-retention:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.CLASS)
#Inherited
public #interface MyAnnotation {}
It is used like this:
#MyAnnotation
public class Parent {}
public class Child extends Parent {}
If these classes are within the same project, my annotation processor is executed on both classes because the annotation is inherited correctly.
If Parent is in a separate project the .jar of which is included in the classpath of the project of Child, it doesn't work. The annotation processor is not executed on Child.
Is this by design or is there a way to fix this?

Related

Java annotations logic implementation

I'm creating a java library that can be imported in multiple projects and creates a graphQL schema file with classes and queries annotated with my custom annotations.
I want that when I compile the project, the classes marked by the annotation will be added (with all their fields) into a file that will be the "schema.graphqls" file.
My question is: where I have to insert my logic implementation? Creating a method into the annotation class?
I created two custom annotations, as in the following files:
package annotations;
import java.lang.annotation.*;
#Documented
#Retention(RetentionPolicy.SOURCE)
#Target(ElementType.TYPE) //with TYPE, you can annotate class, interfaces, annotation, types or enum
public #interface GraphQLQuery {
}
GraphQLQuery.java
package annotations;
import java.lang.annotation.*;
#Documented
#Retention(RetentionPolicy.SOURCE)
#Target(ElementType.TYPE) //with TYPE, you can annotate class, interfaces, annotation, types or enum
public #interface GraphQLModel {
}
GraphQLModel.java

Quarkus tests inheritance not allowed?

Moving some common annotations from a test class to a base one just doesn't work in Quarkus, is this intended or I'm missing something?
This works:
#QuarkusTest
#TestProfile(FunctionalTestProfile.class)
class FrontendControllerTest {...}
This doesn't work:
#QuarkusTest
#TestProfile(FunctionalTestProfile.class)
public class BaseFunctionalTest {}
class FrontendControllerTest extends BaseFunctionalTest {...}
Annotations just don't get applied to child classes
The #QuarkusTest and #TestProfile annotations are not declared #Inherited, so this should not be expected to work.

Converting package level Java annotation to Kotlin

Is it possible to convert a package level Java annotation to Kotlin?
Java annotation (MyAnnotation.java):
package com.myexample.annotation;
#Retention(RUNTIME) #Target(PACKAGE)
public #interface MyAnnotation {
}
Application of annotation (package-info.java)
#MyAnnotation
package com.myexample
The following does not seem to work (although it does compile) - my annotation processor does not detected any of the classes in the package com.myexample:
MyAnnotation.kt
package com.myexample.annotation
#Target(allowedTargets = [AnnotationTarget.CLASS, AnnotationTarget.FILE])
#Retention(AnnotationRetention.SOURCE)
annotation class MyAnnotation
package-info.kt
#file:MyAnnotation
package com.myexample
import com.myexample.annotation.MyAnnotation
No, it's not currently possible. You can simply leave package-info.java as a Java file.

How annotation internally works in java

I know how to create custom annotation. But i am unable to understand how does it work internally. If i take example of spring annontation.
#PropertySource(value = { "classpath:database.properties" }).
if we see internal details of #PropertySource annotation
#Target({ java.lang.annotation.ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Repeatable(PropertySources.class)
public #interface PropertySource {
public abstract String name();
public abstract String[] value();
public abstract boolean ignoreResourceNotFound();
}
We do not have provided any implementation here for loading property file.
Then How is it loading property file from classpath. Who is working behind the scene ?
Really simple: framework. That is. All 'custom' annotations processed by frameworks using reflection. Only small scope of annotations are processed by compiler, such as #Override, #SuppressWarnings, #Retention and so on

Can't get #Component to be inherited in Spring?

In my project there's a common base class that all client classes extend. This has an #Autowired field that needs to be injected by Hibernate. These are all grouped together in another class that has an #Autowired collection of the base class.
In order to reduce boilerplate for client code I'm trying to get #Component inherited. With #Component not doing this by default (apparently it used to though), I created this workaround annotation
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Component
#Inherited
public #interface InheritedComponent {
}
... and annotated the base class with it. Its not pretty but I hoped it would work. Unfortunately it didn't, which really confuses me as #Inherited should make it work
Is there any other way to get #Component inherited? Or do I just have to say that any class that extends the base class needs this boilerplate?
The problem is that the Component annotation type itself needs to be marked with #Inherited.
Your #InheritedComponent annotation type is correctly inherited by any classes that extend a superclass which is marked with #InheritedComponent - but it does not inherit #Component. This is because you have #Component on the annotation, not the parent type.
An example:
public class InheritedAnnotationTest {
#InheritedComponent
public static class BaseComponent {
}
public static class SubClass extends BaseComponent {
}
public static void main(String[] args) {
SubClass s = new SubClass();
for (Annotation a : s.getClass().getAnnotations()) {
System.out.printf("%s has annotation %s\n", s.getClass(), a);
}
}
}
Output:
class brown.annotations.InheritedAnnotationTest$SubClass has annotation #brown.annotations.InheritedComponent()
In other words, when resolving what annotations a class has, the annotations of the annotations are not resolved - they do not apply to the class, only the annotation (if that makes sense).
I've dealt with this issue by creating my own annotation (heritable) and then customizing classpath scanning:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Component
#Inherited
public #interface BusinessService {
}
Spring configuration look likes this:
<context:component-scan base-package="io.bar">
<context:include-filter type="annotation"
expression="io.bar.core.annotations.BusinessService" />
</context:component-scan>
from Spring doc 5.10.3 Using filters to customize scanning

Categories

Resources