jsr342-experts@javaee-spec.java.net

[jsr342-experts] Re: allowing stereotypes to be used more widely

From: Bill Shannon <bill.shannon_at_oracle.com>
Date: Mon, 19 Nov 2012 14:34:20 -0800

We knew about this issue from the beginning.

The proposal to reuse @Stereotype was based on the assertion that 99% of
CDI users never write a portable extension, and of those who do, very
few do anything like this.

Yes, those few would have to understand the limitations, but 99% of the
users would not need to know or care.

The alternative is that 100% of users need to know whether to choose
@Stereotype or @Metatype (or whatever we end up calling it), even though
both will work in many cases.

I'd rather confuse 1% of users in rare cases than 100% of users in common
cases.

Remember that in no case will what you've shown below be made to work,
so someone needs to know about that no matter what we do.

But this is the argument I made before, which apparently isn't compelling...

Pete Muir wrote on 11/19/12 06:34:
> I was on the fence for a long time, however discussing with the CDI EG and colleagues made it clear there was little support once we went through the possible confusion that can arise. The CDI EG also agrees with me here :-)
>
> Here is the point which we think kills the idea. If you define this stereotype in CDI, with the support proposed for all Java EE specs:
>
> @Stereotype
> @RequestScoped
> @Stateless
> public @interface MyStereotype {}
>
> And define this bean:
>
> @MyStereotype
> public class MyBean {}
>
> you end up with a request scoped SLSB.
>
> If you also define this bean:
>
> public class MyOtherBean {}
>
> and write a portable extension:
>
> public <X> void addMyStereotype(@Observes ProcessAnnotatedType<X> pat) {
> if (pat.getAnnotatedType().getJavaClass().getName().equals("MyOtherBean")) {
> Annotation myStereotype = new AnnotationLiteral<MyStereotype>() {};
> AnnotatedType<X> at = new AnnotatedTypeBuilder().read(pat.getAnnotatedType()).addAnnotation(myStereotype).build();
> pat.setAnnotatedType(at);
> }
> }
>
> which looks for MyOtherBean, and then adds the @MyStereotype annotation (using an AnnotatedTypeBuilder provided e.g. by DeltaSpike).
>
> Naively, a user would expect @Stateless to be applied to MyOtherBean, however it will not. We feel this is a much more confusing situation than simply saying the you cannot put any other annotations on a stereotype than certain CDI annotations.
>
> Hope that helps explain the issue
>
> Pete
>
> On 16 Nov 2012, at 23:22, Bill Shannon wrote:
>
>> Very recently.
>>
>> He may have held this position for a long time, but it only became
>> clear to me very recently.
>>
>> Werner Keil wrote on 11/16/12 13:47:
>>> Sorry, this thread mentioned is about a year old.
>>> When did Pete state that, last year or just recently?
>>>
>>> Thanks,
>>> Werner
>>>
>>> I hope you've all had a chance to contribute to the Java EE 7 survey
>>> Linda announced recently. If you've looked at the results, you'll
>>> see that 65% of the people support expanding our use of @Stereotype,
>>> with only 11% thinking it's a bad idea.
>>>
>>> Unfortunately, it turns out that the CDI spec lead doesn't agree
>>> that we should reuse @Stereotype in this way, and would prefer that
>>> we define a new annotation for this purpose. Without support from
>>> CDI, we can't reuse @Stereotype, so we'll need to consider the
>>> alternative. Sadly, at this late date, we don't have time and
>>> resources to define, implement, and test an alternative solution.
>>> I'm afraid this is something we'll need to reconsider for Java EE 8.
>>>
>>> I still think the general idea is a great idea and I look forward to
>>> fleshing it out for EE 8!
>>>
>>> Bill Shannon wrote on 08/30/12 13:58:
>>>> 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?
>>>
>>
>