users@javaee-spec.java.net

[javaee-spec users] [jsr366-experts] Re: Compatibility Problems with MR Resource Annotation Widening

From: Bill Shannon <bill.shannon_at_oracle.com>
Date: Fri, 27 Feb 2015 15:38:39 -0800

You learn something every day...

Before CDI, all deployment processing could be done without running,
or even loading, any classes in the application.

Apparently I wasn't watching carefully when CDI was being defined,
and in particular when the Weld-specific integration SPI was defined.
It now appears that CDI has to be bootstrapped before you can
determine whether deployment succeeds or fails. This wouldn't be
so bad if CDI was just another "container" that needed to look at
application metadata when the application was deployed, but the
introduction of CDI portable extensions means that code in the
application has to run during the application deployment process.
I'm not sure we've fully defined the environment in which that code
is running - what resources are available, what APIs it's allowed
to use, what happens if it does something it shouldn't do, whether
it's allowed to access the database or create threads, etc. I also
don't understand what's supposed to happen if I deploy my application
without starting it. Does CDI bootstrapping occur so that deployment
can succeed, and then the application is terminated? Maybe I need to
spend more time with that part of the CDI spec...

Jason Greene wrote on 02/26/15 19:02:
>> These annotations need to be processed at deployment time in order to work
>> properly. If you wait until CDI is bootstrapped, it's too late. So you
>> need to process these annotations on all classes, whether CID is using them
>> or not, so that they'll work properly.
>
> Why? I donít see how this is required. The CDI RI bootstrap is broken into
> separate phases, and that allows you to analyze all this stuff, and do it
> cooperatively/in-parallel before user code is ever executed, and certainly at
> deployment time. Now maybe the EE RI needs something else out of the CDI RI
> SPI, but thats really just an implementation issue.
>
> The one exception is portable extensions, as those are a container SPI
> contract, and participate during deployment and undeployment.
>
>>
>> These classes need to be able to contain resource *definitions*, not just
>> references. And as I said above, they need to define resource references
>> that can be overridden in the deployment descriptor.
>>
>> (As far as I know, there's no way for a CDI extension to dynamically add
>> (e.g.) an @Resource annotation to a class. And again, since the
>> information from those annotations needs to be visible at deployment time,
>> that's not going to work.)
>
> A portable extension can emit any injection point, including a resource
> injection point and the generic callback should still work since the
> container wouldnít know the difference (unless it looked at the bytecode
> itself).
>
> This looks like it should work on the EE RI (I havenít tried it though):
>
> https://java.net/projects/glassfish/sources/svn/content/trunk/main/appserver/web/weld-integration/src/main/java/org/glassfish/weld/services/InjectionServicesImpl.java?rev=63779

Ok, so it may actually be *possible* for CDI to collect all the information
about resource annotations on CDI managed beans at deployment time,
communicate that to the container, and allow the container to process
those annotations and configure those resources.

>> Before CDI, the set of classes was quite restricted. These were the
>> "container managed" classes. These were the classes instantiated by the
>> container, not by the application, which gave the container the
>> opportunity to perform injection. Clearly many people would like injection
>> to occur for "new", but that's not going to happen, so we described which
>> classes the container was managing, and thus which classes we could
>> actually make injection work on.
>>
>> After CDI, we expanded the set to include all the container managed
>> classes that CDI managed, which meant almost anything that could be used as
>> a CDI bean. The only way to make injection work in all those cases is to
>> consider every class a potential container managed class and to process
>> these resource reference and definition annotations on all these classes.
>> That's why Chapter 8 says you have to collect this deployment information
>> (and again, resource reference and definition annotations are just another
>> way of specifying deployment information) from all classes at deployment
>> time.
>>
>> I don't know how else to make the requirements of the spec actually work
>> correctly, which is why we viewed this as a clarification, not a change.
>
> If its just a matter of saying all of these types have to be looked at, then
> I think we have already defined that, since all of the relevant specs specify
> which types are eligible. If, however, theres a new set of classes that are
> receiving injection & bindings, then thatís by definition a scope expansion.

No new classes are receiving injection.

The inconsistency we're trying to clarify is between Chapter 5, which says
that resource definition annotations can only appear on container-managed
classes, and Chapter 8, which says that all classes must be scanned for
annotations that specify deployment information.

As I explained, there's some spec requirements, and use cases, that can't
be implemented properly unless all classes are scanned. That's why it
seems to us that this is just a clarification, not a change, and not an
expansion in scope.

If, in fact, the CDI implementation is discovering all the CDI managed beans
at deployment time, and communicating that information to the container so
that it can discover all the resource reference and definition annotations
on those classes, we may be closer than I thought. Is CDI/Weld doing that?

If so, then we know that all the other classes don't support injection, and
thus shouldn't contain any annotations specifying injection. If they did,
and those annotations were ignored, that might be a gap we could live with.

That leaves us with these other classes specifying resource references or
definitions at the class level. Since these classes can use JNDI to look up
these resources at runtime, it seems perfectly reasonable for them to be able
to specify resource references or definitions. You have to scan all the
classes to find all the class level annotations anyway, so discovering
these class level annotations should be essentially no additional cost.
It seems like this is a perfectly reasonable use case that should work,
and as we saw from my earlier poll, many developers expect this to work.
And it works in the RI.