如果 web 应用程序包含 @Stateless ejb,我无法启动在 websphere 自由配置文件 8.5.5 上嵌入 CODI 的 web 应用程序。
我得到这个例外:
[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"
我已经声明只有当项目中存在 ejb 时才会出现问题(在我的情况下是 @Stateless ejb)。
在这种情况下,应用程序上下文在服务器启动和 webapp 安装/部署时被初始化。这里没问题。
当 webapp 处理第一个 HTTP 请求时,它FacesServlet
被初始化并被CodiNavigationHandler
实例化。
该方法CodiNavigationHandler.isAddViewConfigsAsNavigationCaseActivated()
在构造函数中被调用并尝试获取对 CODI 的引用JsfModuleConfig
。这JsfModuleConfig
有一个 @ApplicationScoped 注释,并且 beanManager 尝试获取应用程序上下文。
此应用程序上下文已创建(当部署 webapp 时)但LibertyContextsService.initApplicationContext(String)
尚未调用。因此 ThreadLocal 变量上的应用程序上下文为 nullLibertyContextsService.applicationContexts
并发生错误:
WebBeans context with scope type annotation @ApplicationScoped does not exist within current thread
重现:
- 创建动态 Web 项目
- 在 WEB-INF 下添加一个几乎空的 beans.xml(只是一个
beans
元素) - 在 WEB-INF 下添加一个几乎空的 faces-config.xml(只是一个
faces-config
元素) - 添加带有 faces/index.xhtml 的 web.xml
- 复制 WEB-INF/lib 中的 codi jars ( http://www.apache.org/dyn/closer.cgi/myfaces/binaries/myfaces-extcdi-assembly-jsf20-1.0.5-bin.zip )
添加一个无状态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"; } }
添加一个jsf bean:
import javax.inject.Inject; import javax.inject.Named; @Named public class MyController { @Inject private MyBean myBean; public String getTitle() { return myBean.getTitle(); } }
添加一个简单的 jsf 网页:
<h:body> <h:outputText>${myController.title}</h:outputText> </h:body>
注意:如果您删除 ejb 上的 @stateless,应用程序将正常工作。