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

From: Bill Shannon <bill.shannon_at_oracle.com>
Date: Thu, 05 Mar 2015 14:19:09 -0800

Jason Greene wrote on 03/05/2015 01:35 PM:
>> On Mar 4, 2015, at 6:59 PM, Bill Shannon <bill.shannon_at_oracle.com> wrote:
>> Jason Greene wrote on 03/02/15 15:09:
>>> The only code thats allowed to execute from a CDI perspective, is the
>>> portable extension class, which uses the service loader mechanism. Only
>>> when deployment has completed can code in the CDI component classes
>>> execute.
>> Right, but what is a portable extension allowed to do? Can it call web
>> services? EJBs? In the same app? Can it access the database? Do JNDI
>> lookups? Create threads? What resources are available? All of this really
>> needs to be fully specified.
> Well its loaded via a service loader interface, so it can do anything that
> Java code can do. We donít define a naming context on it, so you couldnít
> rely on a naming context. There is no injection context either, and its not a
> managed bean, so you canít access resources, or CDI beans. I donít think we
> say much in any of our specs about whether or not you can create threads,
> other than point people at the concurrency utils executors. It also is
> defined as running in deployment so its implied you canít rely on anything
> else your deployment might do on setup.

I think we need to move beyond implying what you can and can't do and stating
it more explicitly.

>>>> 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.
>>> I guess I just donít agree that having to scan an annotation means you
>>> have to define a component. To me this seems to be a bit of a false
>>> dichotomy. We can certainly improve things without making every Java
>>> class a component.
>> We're not making every Java class a component. Why do you think we are?
> Well you are talking about enabling resource injection on every class, and
> that effectively makes them some kind of component. I guess the closest would
> be a managed bean, but without the @ManagedBean.

No, I'm talking about allowing every class to declare resource references
and resource definitions.

It's pretty clear why this should work at the class level. Do you need

If a non-managed bean class annotates a field or method with (e.g.)
@Resource, I would still create the resource reference deployment information
corresponding to that annotation, even though that field or method would
never be injected. We could argue about whether that's a good idea or not,
but it seemed simpler to just *always* do it rather than figure out exactly
when injection would work. It's just like annotating a managed bean's fields
or methods for injection and then creating the bean with "new". It may look
like injection is going to occur, but it won't. If the injection request
(which might never occur) can't be satisfied, CDI is still going to complain,
it's not going to try to figure out that the bean will never be used in a way
in which injection should occur.

>>>> 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?
>>> Yes but only for valid injection points, so if its not a Resource
>>> producer then it wouldnít be in that particular callback. That said the
>>> EE container can participate in a number of ways as part of the process.
>>> And the SPI could also be extended further.
>> So CDI managed beans that contain @DataSourceDefinition annotations aren't
>> being reported to the container? How does the container find those
>> annotations if it's limiting itself to only the classes supporting
>> injection?
> Well you just only execute them if they are on a CDI managed bean, but you do
> need CDI logic to tell you that. The logic could either be the CDI RI via a
> lifecycle callback, or it could be a duplicated simulation.

I didn't understand that. What do you mean "execute them"?

If the deployment process is depending on CDI to tell it about the managed
beans so it can scan them for these annotations, and CDI isn't telling it
about these beans because they have no resource references on producer
fields, then we have a bug.

>> And since the spec clearly says that CDI managed beans support resource
>> injection, they need to support all aspects of resource injection defined
>> by the platform spec, not some limited cases related to CDI producers.
> My interpretation is that the CDI spec limits this to producer fields. It was
> also the intention because the value of full resource injection to CDI
> applications is very low and duplicates a subset of functionality provided by
> CDI (Granted it doesnít explicitly say you canít do it, so I certainly
> understand why we have differing interpretations).
> That said, we could certainly *add* support for EE resource injection to the
> CDI RI, and clarify in the CDI spec that all forms of EE injection are
> supported. It has to be implemented by the CDI container though, since the
> CDI container governs CDI managed bean instantiation, and only the CDI
> container (or something implementing the same rules) can define what is and
> is not a CDI managed bean.

I think you need to review the discussion we had for Java EE 7,
and the matrix showing which features were supported where:
As you remember, our goal was to make support of the various features
more uniform across all the component and bean types. CDI managed beans
support Java EE resource injection in the same way that @ManagedBeans do,
and EJB session beans do, and so on. There's never been any intended
limitation on what Java EE resource injection is supported by CDI beans.

>>>> 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.
>>> Glassfish does not appear to be defining bindings on the CDI @Resource
>>> values, unless I am looking at the wrong code, or its duplicated in some
>>> other place (sorry if I am wrong about this, I still havenít had time to
>>> test it) .
>> I tested it and it seems to be working for me.
>> Again, what started us on this path is some bugs in the way GlassFish is
>> handling some of this stuff, so we know it's not perfect. But in this
>> case it seems to be doing what we expect.
> Yes, I just tried it and it appears to be working in some cases. If you
> explicitly do a module or app reference it appears to bind. It seems to
> ignore default names (iím guessing everything in comp?).
> Standard EE resource injection and field injection doesnít work, since the
> CDI RI doesnít do it.

Show me.

I have a CDI bean that's @Injected in to a servlet, and the CDI bean declares
@Resource injected fields. The fields are injected into the bean and the bean
is injected into the servlet. It works fine.