users@jersey.java.net

[Jersey] Re: Erratic missing "CdiInjecteeSkippingClassAnalyzer" Exceptions

From: Joachim Kanbach <jo.ka_at_gmx.de>
Date: Tue, 22 Sep 2015 13:13:17 +0200
Hi Jakub,
 
all the log entries involving a CdiComponentProvider look exactly the same in the erroneous and the working deployments. There are several lines like this:
 
[2015-09-17T20:38:11.620+0200] [glassfish 4.1] [WARN] [] [org.jboss.weld.Event] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1442515091620] [levelValue: 900] [[
  WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.]]
 
[2015-09-17T20:38:11.639+0200] [glassfish 4.1] [WARN] [] [org.jboss.weld.Event] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1442515091639] [levelValue: 900] [[
  WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.]]
 
etc.
 
Regarding your suggestion to implement a Jersey component provider, wouldn't this disable CDI injection in my whole web module if I don't specify classes in the bind() method that should be exempt (like in the example in the Jersey documentation)? I don't use CDI injection only in those few EJBs that are involved in this initialization code, but I do use it in many other EJBs and Jersey resource classes.
 
Seeing that the error occurs so relatively rarely and apparently despite the server environment not changing, wouldn't that point to some concurrency/timing issue? Particularly since there are also different threads involved?
 
 
Regards,
Joachim
 
Gesendet: Dienstag, 22. September 2015 um 11:55 Uhr
Von: "Jakub Podlesak" <jakub.podlesak@oracle.com>
An: users@jersey.java.net
Betreff: [Jersey] Re: Erratic missing "CdiInjecteeSkippingClassAnalyzer" Exceptions
Hi Joachim,
 
Please see inline…
 
On 22 Sep 2015, at 11:11, Joachim Kanbach <jo.ka@gmx.de> wrote:
 
Hi Jakub,
 
thank your for your reply.
 
I have enabled CDI support in this module, in fact my beans.xml even declares a CDI interceptor. In those cases when the deployment and server startup code triggered by that singleton EJB run fine, CDI injection (in other beans) works without any problems thereafter.
 
I can confirm that the exception only occurs quite rarely; unfortunately the consequences when it does occur are quite bad because the singleton EJB is not available anymore then. I was thinking to catch the EJBException explicitly around this call so at least the bean will still be available. I could also add some logging in the catch clause to analyze the current server state wrt. CDI initialization etc. What would be useful information for you and how could I get hold of it? I'm still trying hard to reproduce it on my development system without success.
 
Well, you can try to search your server log for something like:
WARNING: Could not load service class org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider
 
If you see such a log message before you get a failure, that would confirm how it happens.
 
 
Since there's no immediate explanation, here are some more details of my design: that startup/singleton EJB actually spawns a different thread by registering a java.nio.file.WatchService in an @Asynchronous method, which is then triggered by a file on the file system present at server startup (I know using java.nio.file is not covered by the Java EE specification, but this is required/convenient for our environment and didn't cause any other problems yet). So it's one of the GlassFish EJB thread pool threads where the exception happens:
 
[2015-09-17T20:38:15.041+0200] [glassfish 4.1] [WARNING] [] [javax.enterprise.ejb.container] [tid: _ThreadID=114 _ThreadName=__ejb-thread-pool1] [timeMillis: 1442515095041] [levelValue: 900] [[
javax.ejb.EJBException: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
 
Another thing that might be of importance is that I use @ExcludeDefaultInterceptors on both the singleton and the called stateless EJB.
 
And finally, what I find confusing is that I don't even use CDI injection in any of those classes involved in the issue. The stateless EJB is injected with @EJB into the singleton, and both the singleton and the stateless EJB only have other @EJB, @PersistenceContext and @Resource (javax.annotation.Resource) annotations.
 
Since you do not use any CDI injection, there should be a workaround for you:
 
 
The only important method that you need to implement is initialize:
 
    @Override
    public void initialize(final ServiceLocator locator) {
 
        final ClassAnalyzer defaultClassAnalyzer =
                locator.getService(ClassAnalyzer.class, ClassAnalyzer.DEFAULT_IMPLEMENTATION_NAME);
 
        final DynamicConfiguration dc = Injections.getConfiguration(locator);
 
        final ScopedBindingBuilder bindingBuilder =
                Injections.newBinder(defaultClassAnalyzer);
 
        bindingBuilder.analyzeWith(ClassAnalyzer.DEFAULT_IMPLEMENTATION_NAME)
                .to(ClassAnalyzer.class)
                .named(“CdiInjecteeSkippingClassAnalyzer");
 
        Injections.addBinding(bindingBuilder, dc);
 
        dc.commit();
    }
 
 your bind method should always return false.
 
You need to register your component provider in a META-INF/services registry and bundle it with your application.
 
I have not tested, but the above workaround should hopefully help.
 
~Jakub
 
 
 
 
Regards,
Joachim
 
Gesendet: Dienstag, 22. September 2015 um 09:58 Uhr
Von: "Jakub Podlesak" <jakub.podlesak@oracle.com>
An: users@jersey.java.net
Betreff: [Jersey] Re: Erratic missing "CdiInjecteeSkippingClassAnalyzer" Exceptions
Hi Joachim,
 
We bumped into a similar issue already in a different container.
 
The problem happens if you disable CDI support. Then EJB integration breaks.
I do not understand why you can see the issue only occasionally. Could you please double check?
 
Then to enable CDI, it should be sufficient to insert an empty beans.xml file into your application: <beans/>
 
Could you please try the above suggested workaround, and eventually file a bug with a simple
reproducer application attached? (https://java.net/jira/browse/JERSEY)
 
Thanks,
 
~Jakub
 
On 22 Sep 2015, at 09:05, Joachim Kanbach <jo.ka@gmx.de> wrote:
 
I hope this is the right mailing list to ask since my problem is apparently in the Jersey-GlassFish integration layer (jersey-gf-cdi.jar/jersey-gf-ejb.jar).
 
I have a setup where a @Singleton @Startup EJB makes calls to another @Stateless EJB. Due to the program layout, it's possible that those calls are triggered right at the server startup through the @PostConstruct method (the whole architecture is a little more complex, I can give the deails if required, but I first need guidance where to look for clues at all).
 
On our build system, the nightly build and deploy occasionally fails with a stack trace like this:
 
javax.ejb.EJBException: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
        at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:435)
        at com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:2579)
        at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1971)
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:210)
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
        at com.sun.proxy.$Proxy224.deleteKeyMetaMappingByDbid(Unknown Source)
        at com.mycompany.cfg.__EJB31_Generated__ConfigurationService__Intf____Bean__.deleteKeyMetaMappingByDbid(Unknown Source)
        [...]
Caused by: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
        [...]
Caused by: javax.ejb.CreateException: Could not create stateless EJB
        [...]
Caused by: A MultiException has 1 exceptions.  They are:
1. java.lang.IllegalStateException: Could not find an implementation of ClassAnalyzer with name CdiInjecteeSkippingClassAnalyzer
        at org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:88)
        at org.jvnet.hk2.internal.Utilities.justInject(Utilities.java:928)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:902)
        at org.glassfish.jersey.gf.ejb.internal.EjbComponentInterceptor.inject(EjbComponentInterceptor.java:71)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        [...]
Caused by: java.lang.IllegalStateException: Could not find an implementation of ClassAnalyzer with name CdiInjecteeSkippingClassAnalyzer
        at org.jvnet.hk2.internal.ServiceLocatorImpl.getAnalyzer(ServiceLocatorImpl.java:2249)
        at org.jvnet.hk2.internal.Utilities.getClassAnalyzer(Utilities.java:172)
        at org.jvnet.hk2.internal.Utilities.justInject(Utilities.java:927)
        ... 102 more
 
"ConfigurationService" is the @Stateless EJB on which deleteKeyMetaMappingByDbid() should be called
 
This happens quite rarely, not more than once a week or so. I didn't manage to recreate the situation outside of the build period. It could be that the system is under very high load during that time. But I couldn't find a pattern that separates the successful deployments, where the exact same sequence of method calls and EJB creations happens, from the ones failing with this stack trace.
 
I've looked at the source code a little and realized that "CdiInjecteeSkippingClassAnalyzer" must be the HK2 internal name used for org.glassfish.jersey.gf.cdi.internal.InjecteeSkippingAnalyzer. But if you search for this on the web, you get only a very few hits, none of which is helpful.
 
So my question is how an error like this could be possible at all? I was wondering if the cause might be that HK2 may not have finished initializing properly before the @Stateless EJB is to be injected and used (cf. my remark regarding system load)?