Is there a way in CDI to call a single method that will acquire the annotations of an annotated type that themselves are annotated with a meta-annotation?
Suppose I have an annotation, @Fred
, that can be applied to annotation types. We'll call this a meta-annotation.
Suppose further I have an annotation, @Barney
, that can be applied to a class. Suppose that @Barney
is annotated with the meta-annotation @Fred
. We'll say that any class annotated with @Barney
is meta-annotated with @Fred
.
Now suppose I'm writing an extension that doesn't know a thing about @Barney
, but does know about @Fred
, and wants to work with things that are meta-annotated with @Fred
.
I'm looking for an easy way to say "Hey, BeanManager
[or some other machinery], get me all Bean
s that are meta-annotated with @Fred
."
I know I can do this manually (walk the graph by hand, get a class' annotations, get their annotations, and so on, until I detect the meta-annotation in question).
I also know, however, that, for example, Weld and other CDI implementations must do something like this already to implement the Interceptors specification, since interceptor bindings are transitive in much the same way. I'm often guilty of overlooking something in the tersely documented CDI universe; I'm hoping that's the case now.
I doubt that there is a function at the CDI-API which does the job. Probably there are some private helper-classes inside CDI-Implementations (like Weld) for these use-cases.
But the following small function should tell you if a “class to test” has an annotation which again is annotation with something:
private static boolean isBuddyOf(
final Class<? extends Annotation> annotation,
final Class<?> classToTest) {
return Stream.of(classToTest.getAnnotations())
.anyMatch(a -> a.annotationType().isAnnotationPresent(annotation));
}
(compare with JAVA - How to get annotations from Annotation?)
If you need to go deeper, be careful with recursive calls because this can easily lead to a stack overflow. Typically an annotation has the Meta-Annotation @Retention which has @Documented which again has @Retention. So I hope recursion is not necessary and the simple check is OK.
If yes, it should be easy to use that function at your extension:
class MyExtension implements Extension {
<T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> pat) {
Class<?> annotatedTypeClass = pat.getAnnotatedType().getJavaClass();
boolean result = isBuddyOf(Fred.class, annotatedTypeClass);
[...]
}
}