[weld-dev] @Resource annotation handling by Weld vs Servlet container
Jan Bartel
janb at intalio.com
Tue Apr 14 01:17:55 EDT 2015
Hi Jozef,
>>> 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.
>
> Ok, great, I'll give this a go and report back.
I've implemented the service for the ResourceInjectionServices (for
now each method simply does a println), and it looks like weld is
seeing it:
Apr 14, 2015 11:40:34 AM org.jboss.weld.bootstrap.AdditionalServiceLoader put
DEBUG: Installing additional service
org.jboss.weld.injection.spi.ResourceInjectionServices (class
org.eclipse.jetty.cdi.servlet.ResourceInjectionServices)
Weld ResourceInjectionServices jetty constructor called
However, it does not appear to be being used, as I see no output from
my service, but still get the following error:
java.lang.RuntimeException: Error looking up maxAmount in JNDI
at org.jboss.weld.injection.spi.helpers.AbstractResourceServices.resolveResource(AbstractResourceServices.java:50)
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)
Any hints?
thanks,
Jan
>
>
>>> 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
>
> So if jetty is handling @Resource (handling making the jndi entries
> and injecting the fields/methods) for servlets/filters/listeners, what
> will happen if someone declares this in eg a servlet:
>
> public class MyServlet extends HttpServlet
> {
>
> @Producer @Resource (name="foo")
> @MyDb
> private DataSource db;
> }
>
> Will weld still inspect this class and find the producer and make it
> available for injection in other code?
>
> cheers
> Jan
>
>>
>>>
>>> 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
>>>>
>>>>
>>>
>>>
>>
>
>
>
> --
> Jan Bartel <janb at intalio.com>
> www.webtide.com
> 'Expert Jetty/CometD developer,production,operations advice'
--
Jan Bartel <janb at intalio.com>
www.webtide.com
'Expert Jetty/CometD developer,production,operations advice'
More information about the weld-dev
mailing list