CODI with ejb stateless on Websphere liberty profi

2019-09-14 19:27发布

问题:

I cannot launch a webapp that embedd CODI on websphere liberty profile 8.5.5 if the webapp contains a @Stateless ejb.

I get this exception:

[ERROR   ] null
java.lang.reflect.InvocationTargetException
[ERROR   ] An error occured while initializing MyFaces: java.lang.reflect.InvocationTargetException
java.lang.reflect.InvocationTargetException
[ERROR   ] Uncaught.init.exception.thrown.by.servlet 
    Faces Servlet
    codiTest
    javax.enterprise.context.ContextNotActiveException: WebBeans context with scope type annotation @ApplicationScoped does not exist within current thread
    at org.apache.webbeans.container.BeanManagerImpl.getContext(BeanManagerImpl.java:342)
    at [internal classes]
    at org.apache.myfaces.extensions.cdi.core.api.config.CodiCoreConfig_$$_javassist_78.isAdvancedQualifierRequiredForDependencyInjection(CodiCoreConfig_$$_javassist_78.java)
    at org.apache.myfaces.extensions.cdi.jsf.impl.listener.phase.PhaseListenerExtension.consumePhaseListeners(PhaseListenerExtension.java:110)
    at org.apache.myfaces.extensions.cdi.jsf2.impl.listener.phase.CodiLifecycleFactoryWrapper.getLifecycle(CodiLifecycleFactoryWrapper.java:67)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:119)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:322)
    at [internal classes]

[ERROR   ] SRVE0266E: Error occured while initializing servlets: javax.servlet.ServletException: SRVE0207E: Uncaught initialization exception created by servlet
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:385)
    at [internal classes]
Caused by: javax.enterprise.context.ContextNotActiveException: WebBeans context with scope type annotation @ApplicationScoped does not exist within current thread
    at org.apache.webbeans.container.BeanManagerImpl.getContext(BeanManagerImpl.java:342)
    at [internal classes]
    at org.apache.myfaces.extensions.cdi.core.api.config.CodiCoreConfig_$$_javassist_78.isAdvancedQualifierRequiredForDependencyInjection(CodiCoreConfig_$$_javassist_78.java)
    at org.apache.myfaces.extensions.cdi.jsf.impl.listener.phase.PhaseListenerExtension.consumePhaseListeners(PhaseListenerExtension.java:110)
    at org.apache.myfaces.extensions.cdi.jsf2.impl.listener.phase.CodiLifecycleFactoryWrapper.getLifecycle(CodiLifecycleFactoryWrapper.java:67)
    at javax.faces.webapp.FacesServlet.init(FacesServlet.java:119)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:322)
    ... 1 more

[WARNING ] Unknown RenderKit 'HTML_BASIC'.
[WARNING ] Unknown RenderKit 'HTML_BASIC'.
[ERROR   ] An exception occurred
java.lang.IllegalArgumentException: Could not find a RenderKit for "HTML_BASIC"

I've constated that the problem occurs only if an ejb is present in the project (in my case a @Stateless ejb).

In this case, the application context is initialized when the server is started and the webapp installed/deployed. No problem here.

When the first HTTP request is handled by the webapp, the FacesServlet is initialized and CodiNavigationHandler is instanciated.

The method CodiNavigationHandler.isAddViewConfigsAsNavigationCaseActivated() is called in the constructor and tries to get a reference on CODI JsfModuleConfig. This JsfModuleConfig has an @ApplicationScoped annotation and the the beanManager tries to get the application context.

This application context has already been created (when the webapp is deployed) but the LibertyContextsService.initApplicationContext(String)has not been called yet. So the application context is null on the LibertyContextsService.applicationContexts ThreadLocal variable and the error occurs:

WebBeans context with scope type annotation @ApplicationScoped does not exist within current thread

To reproduce:

  • create a Dynamic Web Project
  • add an almost empty beans.xml under WEB-INF (just a beans element)
  • add an almost empty faces-config.xml under WEB-INF (just a faces-config element)
  • add a web.xml with a faces/index.xhtml
  • copy codi jars in WEB-INF/lib (http://www.apache.org/dyn/closer.cgi/myfaces/binaries/myfaces-extcdi-assembly-jsf20-1.0.5-bin.zip)
  • add a stateless bean:

    import javax.annotation.PostConstruct;
    import javax.ejb.Stateless;
    
    @Stateless
    public class MyBean {
    
        @PostConstruct
        public void postConstruct() {
            System.out.println("post construct: " + this);
        }
    
        public String getTitle() {
            return "test";
        }
    }
    
  • add a jsf bean:

    import javax.inject.Inject;
    import javax.inject.Named;
    
    @Named
    public class MyController {
    
        @Inject
        private MyBean myBean;
    
        public String getTitle() {
            return myBean.getTitle();
        }
    }
    
  • add a simple jsf web page with:

    <h:body>
        <h:outputText>${myController.title}</h:outputText>
    </h:body>
    

nota: if you remove the @stateless on the ejb, the application works.

回答1:

Effectively it seems to be a bug (I also post the question on IBM forums: https://www.ibm.com/developerworks/community/forums/html/topic?id=f372bbc5-5ba4-4c2a-9ef0-0bdcd76766da#09228314-2baf-4892-899e-5a8cc52daa19).

I'm going to try to find a way to create a PMR (I'm in a big company, difficult to find the right person that will grant me access to that).

So for now, I've switched to jboss.