[weld-dev] @Resource annotation handling by Weld vs Servlet container

Jozef Hartinger jharting at redhat.com
Mon Apr 13 05:13:15 EDT 2015



On 04/13/2015 02:13 AM, Jan Bartel wrote:
> Hi Jozef,
>
> Thanks for the info, a couple of followup questions inline ...
>
>
>> to briefly explain the current integration: Handling or @Resource injection
>> is not handled by Weld core itself. It is abstracted using the following
>> SPI:
>> http://docs.jboss.org/weld/javadoc/2.2/weld-spi/org/jboss/weld/injection/spi/ResourceInjectionServices.html
>> Weld Servlet provides a default implementation of this SPI. An application,
>> Servlet runtime or a library may provide an alternative implementation of
>> the given service and take over resource lookups.
> Looking at the WeldServletLifecyle class on line 124, it will always
> provide an implementation of the ResourceInjectionServices (an
> instance of ServletResourceInjectionServices). If we were to provide
> our own implementation of ResourceInjectionServices, how would we
> override that one? Is there a way to get a hold of the Deployment and
> thus the BeanDeploymentArchives so we could set our own implementation
> up? Ideally we'd like a pure CDI api way of interacting with weld, but
> maybe that's not possible in this case?
You need to interact with Weld APIs to do this. A service can be 
overridden using ServiceLoader mechanism. See 
http://docs.jboss.org/weld/reference/2.2.10.Final/en-US/html/ri-spi.html#_registering_services 
for details.
>
>
>> As for integration with Jetty, Weld provides a decorator that performs CDI
>> and resource injection for Servlets, Filters and listeners. We can change
>> that for Weld to only provide CDI injection
>> (https://issues.jboss.org/browse/WELD-1919).
> Looks like the decorator will only call inject anyway - in my tests I
> haven't seen it call any PostConstruct or PreDestroy methods (on
> servlet/filter/listeners at least).
OK, it's probably the case then that for these components Weld only 
provides CDI + resource injection and does not call 
@PostConstruct/@PreDestroy
>
> Alternatively, instead of Weld
>> hooking into lifecycle of Jetty-managed components, Jetty could use CDI APIs
>> to perform CDI injection on instances it manages.
>>
> Yes, potentially we could do that, although we'd probably need your
> guidance on the best way to do that. Can  @Resource be  used by pojo
> beans or only by servlet artifacts (servlet/filter/listeners)? If the
> latter, then I'm fine for Jetty to do all the handling of @Resource.
> If not, then it probably makes sense for weld to handle it, and we'd
> need a way to disable Jetty's implementation if weld is present in a
> webapp ...
I think the best approach would be to modify the integrating decorator 
to only provide CDI injection to Jetty-managed instances. I have 
implemented it here: 
https://github.com/weld/core/commit/f7420e34355c5c82ef516713c65fc6cd750fb651
>
> cheers
> Jan
>
>> Additional comments inline:
>>
>>
>> On 04/10/2015 02:00 AM, Jan Bartel wrote:
>>> Hi Weld developers,
>>>
>>> The Jetty project is looking at how we can do a tighter integration
>>> with Weld, also with a view to discussions in the Servlet Spec 4
>>> committee to alleviate the necessity for CDI implementations to
>>> maintain jetty-specific initialisation code.
>>>
>>> During investigations, I noticed that we seem to have a conflict in
>>> the handling of a few annotations for classes that are managed by the
>>> servlet container (ie servlets, filters, listeners etc):
>>>
>>> @Resource
>>> @PostConstruct
>>> @PreDestroy
>>>
>>> As Jetty puts a servlet/filter/listener into service, we introspect
>>> the class and find the above annotations and process them. It seems
>>> that Weld does too, as I see the following failure for this code
>>> snippet:
>>>
>>> public class TestListener implements ServletContextListener
>>> {
>>>       @Resource(mappedName="maxAmount")
>>>        private Double maxAmount;
>>> }
>>>
>>>
>>> javax.naming.NameNotFoundException; remaining name 'maxAmount'
>>>       at
>>> org.eclipse.jetty.jndi.local.localContextRoot.lookup(localContextRoot.java:429)
>>>       at
>>> org.eclipse.jetty.jndi.local.localContextRoot.lookup(localContextRoot.java:533)
>>>       at javax.naming.InitialContext.lookup(InitialContext.java:411)
>>>       at
>>> org.jboss.weld.injection.spi.helpers.AbstractResourceServices.resolveResource(AbstractResourceServices.java:48)
>>>       at
>>> org.jboss.weld.injection.spi.helpers.AbstractResourceServices$1.createResource(AbstractResourceServices.java:121)
>>>       at
>>> org.jboss.weld.injection.AbstractResourceInjection.getResourceReference(AbstractResourceInjection.java:44)
>>>       at
>>> org.jboss.weld.injection.AbstractResourceInjection.injectResourceReference(AbstractResourceInjection.java:53)
>>>       at org.jboss.weld.util.Beans.injectEEFields(Beans.java:344)
>>>       at
>>> org.jboss.weld.injection.producer.ResourceInjector$1.proceed(ResourceInjector.java:69)
>>>       at
>>> org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:48)
>>>       at
>>> org.jboss.weld.injection.producer.ResourceInjector.inject(ResourceInjector.java:72)
>>>       at
>>> org.jboss.weld.injection.producer.BasicInjectionTarget.inject(BasicInjectionTarget.java:121)
>>>       at
>>> org.jboss.weld.environment.servlet.inject.AbstractInjector.inject(AbstractInjector.java:55)
>>>       at
>>> org.jboss.weld.environment.jetty.JettyWeldInjector.inject(JettyWeldInjector.java:15)
>>>       at
>>> org.jboss.weld.environment.jetty.WeldDecorator.decorate(WeldDecorator.java:105)
>>>       at
>>> org.eclipse.jetty.util.DecoratedObjectFactory.decorate(DecoratedObjectFactory.java:77)
>>>       at
>>> org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:335)
>>>       at
>>> org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1349)
>>>       at
>>> org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1342)
>>>       at
>>> org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:743)
>>>       at
>>> org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:257)
>>>       at
>>> org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:505)
>>>
>>>
>>> Googling around, it is not clear to me exactly which of the Common
>>> Annotations (JSR250) that Weld supports and I'd appreciate some input
>>> from the Weld devs in order for Jetty to work out how best to move
>>> forward with Weld integration.
>>>
>>> In particular, I'd appreciate some clear feedback on which of the
>>> following @Resource annotation usages will be handled by Weld:
>>>
>>> @Resource on a class
>>> @Resource on a field
>>> @Resource on a method
>>> @Resource annotations without an accompanying @Producer annotation
>> @Resource on a field (with or without @Producer), @Resource on a method,
>> @PostConstruct and @PreDestroy are handled by Weld on a managed instance
>> (generally).
>>>
>>> Secondly, as can be seen from the stacktrace above, Weld is failing to
>>> find the matching JNDI entry for an @Resource annotation. This is
>>> because Weld appears not to be looking in "java:comp/env" namespace,
>>> although IIRC that is mandated by the JavaEE spec for EE managed
>>> classes (servlets/filters/listeners etc). So if Jetty delegates
>>> handling of some/all processing of @Resource, how do we ensure that
>>> Weld will be able to find the right JNDI entry?
>> This might be a bug in weld-servlet's ResourceInjectionServices
>> implementation. Can you file an issue at
>> https://issues.jboss.org/browse/WELD ?
>>
>>> thanks for your time,
>>> Jan
>>
>
>



More information about the weld-dev mailing list