I think we need to take a step back and establish a couple of things:
1) are all the annotations we have suitable to be meta-annotations?
2) should it be possible to use meta-annotations anywhere, or just in certain places (on
stereotypes)
3) should these annotations be usable via seam-xml?
IMO the answers are
1) No. Not all annotations are suitable as meta-annotations. This is a principle clearly
established by the CDI spec (which doesn't allow qualifiers etc. as meta-annotations).
We should consider whether each annotation is suitable to be a meta-annotation or not.
2) In general no, only on stereotypes. There are a few reasons. In general, stereotypes
were designed for exactly the purpose of stereotyping an action. The overhead on the user
is minimal (I believe the concern that users will get confused by their annotation not
working can be solved by tooling). Finally, if stereotypes are reused, the CDI container
is capable of caching the recursive scan of the annotation hierarchy (which no extension
can do as it doesn't know the lifecycle of the underlying class), and also applying
any metadata specified through the CDI SPI (e.g. XML config) to the stereotype (something
which is not required in other cases). This means the complexity of the checking the
annotations is reduced to N (rather than the N^N we get with a recursive scan).
IOW, taking the JMS case, it would be necessary to specify:
@Stereotype
@Retention(RUNTIME)
@Target({ PARAMETER, METHOD, FIELD })
@JmsDestination(jndiName = "/jms/my-topic")
public @interface MyTopic {}
3) Yes. This reduces the potential for user confusion, and makes it much more powerful.
So, I would propose we create a new API in WeldExtensions that looks like:
/**
* Discover if a AnnotatedElement <b>element</b> has been annotated with
<b>annotationType</b>. This
* also discovers annotations defined through a @{@link Stereotype} and the CDI SPI.
*
* @param element The element to inspect.
* @param annotationType
* @param metaAnnotation Whether the annotation may be used as a meta-annotation or
not
*
* @return true if annotation is present either on the method itself. Returns false if
the annotation
* is not present
* @throws IllegalArgumentException if element or annotationType is null
*/
public static boolean isAnnotationPresent(AnnotatedElement element, Class<? extends
Annotation> annotationType, boolean metaAnnotation);
/**
* Inspect AnnoatedElement <b>element</b> for a specific
<b>type</b> of annotation. This
* also discovers annotations defined through a @ {@link Stereotype} and the CDI SPI.
*
* @param element The element to inspect
* @param annotationType The annotation type to check for
* @param metaAnnotation Whether the annotation may be used as a meta-annotation or
not
*
* @return The annotation instance found on this method or null if no matching
annotation was found.
* @throws IllegalArgumentException if element or annotationType is null
*/
public static <A extends Annotation> A getAnnotation(AnnotatedElement element,
final Class<A> annotationType, boolean metaAnnotation)
This is somewhat different to Lincoln's original proposal (adjusted to add the
meta-annotation stuff, aligned with the Java Reflection API naming conventions, removed
the stuff about whether the annotation is on the declaring class as well - if this is
really needed we can add a boolean flag for this I guess).
Adam also raised the need to be able to inspect the annotations on an annotation element,
which indicates we need another utility method:
/**
* Inspect AnnoatedElement <b>element</b> for a specific
<b>type</b> of annotation. This
* also discovers annotations defined through a @ {@link Stereotype} and the CDI SPI.
Having found
* the annotation, it is inspected for a member with name
<b>memberName</b>.
*
* @param element The element to inspect
* @param annotationType The annotation type to check for
* @param memberName The name of the member to look for
* @param expectedMemberType The expectedType of the member
* @param metaAnnotation Whether the annotation may be used as a meta-annotation or
not
*
* @return The annotation member's value or null if no matching annotation was
found
* @throws IllegalArgumentException if element, annotationType, memberName or
expectedMemberType is null
* @throws IllegalArgumentException if the annotationType does not have a member of
memberName
* @throws ClassCastException if the value of memberName cannot be cast to
expectedMemberType
*/
public static <V> V getAnnotationMemberValue(AnnotatedElement element, final
Class<A> annotationType, String memberName, Class<V> expectedMemberType,
boolean metaAnnotation)
WDYT?
On 13 Apr 2010, at 22:00, Lincoln Baxter, III wrote:
As many of you know, when creating API annotations for Seam Modules,
we have an interesting situation:
https://jira.jboss.org/jira/browse/WELDX-95
Due to the fact that annotations can include meta-annotations, we need to recursively
scan the annotation hierarchy in order to obtain the correct annotation instance (or null
if it isn't declared,) then return that annotation in order to access the attributes.
This becomes even more complex when annotations are added via the seam-xml-config module,
but I'll let Dan or Pete explain that one.
It seems likely that we will need a new API/SPI in CDI in order to appropriately address
performance concerns with doing such recursive, synchronized (locking!) lookups.
There are several questions to address:
• Where do we allow nested/meta-annotations?
• How do we address the performance concerns where they are allowed?
--
Lincoln Baxter, III
http://ocpsoft.com
http://scrumshark.com
"Keep it Simple"
_______________________________________________
seam-dev mailing list
seam-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/seam-dev