users@javaee-spec.java.net

[javaee-spec users] [jsr342-experts] allowing stereotypes to be used more widely

From: Bill Shannon <bill.shannon_at_oracle.com>
Date: Thu, 30 Aug 2012 13:58:40 -0700

Some time ago David Blevins started a discussion in the EJB expert
group about "meta-annotations". The thread starts here:
http://java.net/projects/ejb-spec/lists/jsr345-experts/archive/2011-12/message/21

Several of us have been discussing this idea privately on and off
for some time, and it's time to bring that discussion to this expert
group. The general idea is to allow developers to create their own
annotations that are combinations of existing annotations. You can
think of this as a limited "macro" facility for annotations.

For example:

@Metatype
@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public @interface NonTransactional { }

@NonTransactional
public class MyStatelessEJB { ... }


This is essentially CDI stereotypes, which leads to a counter-proposal
to simply allow CDI stereotypes to be used more widely.

The issues with using stereotypes more widely are:

- Stereotypes are implemented by CDI, but (typically) the Java EE
  deployment processing has no knowledge of CDI when it's looking
  for Java EE annotations. Integrating with CDI so that stereotypes
  could be considered during this deployment-time annotation processing
  would require a new CDI SPI.

- CDI extensions can change the definition of a stereotype. Because
  most Java EE annotations are processed at deployment time, before
  any application code (including CDI extensions) can run, any dynamic
  changes to stereotypes can't effect the deployment process.

- The additional processing required at deployment time to handle
  stereotypes could have a non-trivial impact on deployment performance.

To address these issues, we could introduce a new @Metatype annotation
with most of the same functionality as stereotypes, but without the
ability to change them dynamically. Of course, introducing a new
annotation has issues of its own:

- Developers will be confused as to when to use @Stereotype and when
  to use @Metatype. In most, but not all, cases they will behave
  similarly.

- Introducing a new annotation, without a common place to handle
  processing of that annotation, will likely lead to inconsistencies
  in its implementation.


Our preliminary analysis suggests that the performance impact of
handling stereotypes when processing deployment time annotations
will not be significant. While there's a very small incremental
cost to be *able* to handle stereotypes, most of the actual cost
is only incurred if applications *use* stereotypes. And in any
event, the cost would be essentially the same as the @Metatype
approach.

Based on our experience so far, very few developers make use of the
dynamic capabilities of stereotypes. That fact, along with the
potential confusion of having two annotations that are almost but
not exactly the same, makes it attractive to consider enhancing
the definition of stereotypes to indicate that when they're used
with Java EE annotations, the definition of the stereotype is static
at deployment time. Of course, this also requires a tighter
integration of CDI with the rest of the Java EE platform, which
seems to be the direction we're moving on several fronts. (More
on that later.)

Using stereotypes for this purpose would only work when CDI is
enabled. Separately, the CDI expert group is considering whether we
should change the default and enable CDI by default. Doing so would
make this approach more attractive, although it may also introduce
additional performance issues that would need to be addressed.

Allowing the use of stereotypes for this purpose requires changing
many existing annotations to include ANNOTATION_TYPE as a @Target.

Many existing implementations would need to be changed to understand
how to expand stereotypes. Requiring every technology to do this
itself will almost certainly lead to inconsistencies. Since stereotypes
are a CDI feature, CDI will provide a simple replacement for the
java.lang.reflect methods such as getAnnotations that takes into
account stereotypes.

Some technologies will not want to have a hard dependency on CDI so
we'll need to provide a simple way for them to conditionally invoke
these new methods only if CDI is present, falling back to java.lang.reflect
if not. This seems straightforward. In this case, the functionality of
@Stereotype would not be available to applications that chose to run
without CDI.

What do you think of the above approach? Is expanding the use of
@Stereotype the best approach? Or are the issues with that approach
significant enough that we should consider introducing a new annotation
for this purpose?