Web アプリケーションに @Stateless ejb が含まれている場合、Websphere Liberty Profile 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 がインストール/デプロイされるときに初期化されます。ここでは問題ありません。
最初の HTTP 要求が webapp によって処理されると、FacesServlet
が初期化され、インスタンス化されCodiNavigationHandler
ます。
メソッドCodiNavigationHandler.isAddViewConfigsAsNavigationCaseActivated()
はコンストラクターで呼び出され、 CODI で参照を取得しようとしますJsfModuleConfig
。これJsfModuleConfig
には @ApplicationScoped アノテーションがあり、beanManager はアプリケーション コンテキストを取得しようとします。
このアプリケーション コンテキストは (webapp のデプロイ時に) 既に作成されていますが、LibertyContextsService.initApplicationContext(String)
まだ呼び出されていません。そのため、アプリケーション コンテキストはLibertyContextsService.applicationContexts
ThreadLocal 変数で null になり、エラーが発生します。
WebBeans context with scope type annotation @ApplicationScoped does not exist within current thread
再現するには:
- 動的 Web プロジェクトを作成する
- WEB-INF (単なる
beans
要素)の下にほとんど空の beans.xml を追加します。 - WEB-INF (単なる
faces-config
要素)の下にほとんど空の faces-config.xml を追加します。 - faces/index.xhtml で web.xml を追加します
- WEB-INF/lib の codi jar をコピーします ( 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 Web ページを追加します。
<h:body> <h:outputText>${myController.title}</h:outputText> </h:body>
注意: ejb の@statelessを削除すると、アプリケーションは動作します。