Jetty Maven插件(jetty:run goal)+ Weld CDI + JSF 2.2 = ViewScoped bean上的NPE

时间:2015-03-02 12:33:35

标签: maven jsf jetty cdi weld

在Web应用程序中使用以下(相当新闻)组件:

Jetty maven插件9.2.6.v20141205

焊接CDI 2.2.9.Final

Mojarra JSF 2.2.10

该应用程序的web.xml包含以下侦听器:

org.jboss.weld.environment.servlet.BeanManagerResourceBindingListener
com.sun.faces.config.ConfigureListener

第一个侦听器使用JNDI注册BeanManager。 第二个侦听器初始化JSF并在JNDI中查找BeanManager。

当jetty maven插件与" jetty:run-war"运行时,此设置完全正常。目标或当应用程序作为独立的嵌入式jetty运行时。

然而,使用" jetty:run"在第一个监听器中注册的BeanManager在JSF中不可见,导致ViewScoped bean上的NPE。

在我看来,这似乎是一个范围或可见性问题,但我无法弄清楚 - jetty:run和jetty:run-war之间有什么区别。

我尝试添加" resource-env-ref" web.xml中的条目以及在各种Jetty的xml文件(jetty.xml,jetty-env.xml,jetty-context.xml)中创建BeanManager,但它没有改变任何内容。

更新:

NPE在会话失效时发生;由于在JSF中没有注册BeanManager,ViewScoped bean无法销毁。见下面的堆栈跟踪:

  

引起:java.lang.NullPointerException at   com.sun.faces.application.view.ViewScopeContextManager.destroyBeans(ViewScopeContextManager.java:171)     在   com.sun.faces.application.view.ViewScopeContextManager.sessionDestroyed(ViewScopeContextManager.java:339)     在   com.sun.faces.application.view.ViewScopeManager.sessionDestroyed(ViewScopeManager.java:369)     在   com.sun.faces.application.WebappLifecycleListener.sessionDestroyed(WebappLifecycleListener.java:181)     在   com.sun.faces.config.ConfigureListener.sessionDestroyed(ConfigureListener.java:399)     在   org.eclipse.jetty.server.session.AbstractSessionManager.removeSession(AbstractSessionManager.java:772)     在   org.eclipse.jetty.server.session.AbstractSession.invalidate(AbstractSession.java:326)     在   com.sun.faces.context.ExternalContextImpl.invalidateSession(ExternalContextImpl.java:783)

2 个答案:

答案 0 :(得分:0)

Dimitri在码头项目上提出了一个错误:https://bugs.eclipse.org/bugs/show_bug.cgi?id=462179

该错误包含问题原因的完整描述。简而言之,Weld使BeanManager可用于JSF的方式不适用于未组装的webapps(mvn jetty:run就是这种情况),只有war文件(即mvn jetty:run-war才有效)。

答案 1 :(得分:0)

只需在您的 web.xml 中添加此侦听器即可。我使用 openwebbeans 作为 CDI 容器,但似乎它应该与任何其他容器一起使用。

package com.devadmin.computec.config;

import com.sun.faces.RIConstants;

import javax.enterprise.inject.spi.CDI;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class CustomServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        sce.getServletContext().setAttribute(RIConstants.CDI_BEAN_MANAGER, CDI.current().getBeanManager());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}