【问题标题】:OmniFaces CDI @ViewScoped bean deployed on WebSphere 7 (Java EE 5) nulls all EJBs injected with @EJB: NPE/NullPointerException部署在 WebSphere 7 (Java EE 5) 上的 OmniFaces CDI @ViewScoped bean 将所有注入 @EJB 的 EJB 清空:NPE/NullPointerException
【发布时间】:2017-12-18 12:03:57
【问题描述】:

我在 WebSphere 7 (7.0.50) 和 OpenWebBeans 1.2.8(和 Mojarra 2.1.27 BTW)上成功部署了一个简单的 OmniFaces 1.8.3 视图范围 bean:

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.inject.Named;

import org.omnifaces.cdi.ViewScoped;

...

@Named
@ViewScoped
public class CashValueCalculationManager implements Serializable {

    private static final long serialVersionUID = 1L;

    @EJB
    private CashValueCalculationService cashValueCalculationService;

    // the list of entities to be shown in a datatable
    private List<CashValueCalculation> entities;

    @PostConstruct
    public void init() {

        // displays "this.cashValueCalculationService = null" in the log
        System.out.println("this.cashValueCalculationService = " + this.cashValueCalculationService);

        // load list of entities on init
        try {
            this.loadViewData();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List<CashValueCalculation> getEntities() {
        return this.entities;
    }

    protected CashValueCalculationService getEntityService() {
        return this.cashValueCalculationService;
    }

    protected void loadViewData() throws Exception {

        // NPE here!
        List<CashValueCalculation> cashValueCalculations = this.getEntityService().findAll();

        this.entities = cashValueCalculations;
    }
}

然而,当打开 bean 的视图时,bean 被初始化,运行 @PostConstruct 方法来加载所有实体(只有少数),但这会失败并在 loadViewData() 中出现 NullPointerException。返回的服务是空的......这基本上得到了日志的确认,我也在其中找到了该行

this.cashValueCalculationService = null

CashValueCalculationService 接口用@Local 注释,实现CashValueCalculationServiceBean@Stateless 注释:

@Local
public interface CashValueCalculationService extends EntityService<Integer, CashValueCalculation> {
    // super interface has findAll()
}

豆子:

@Stateless
public class CashValueCalculationServiceBean extends BaseEntityServiceBean<Integer, CashValueCalculation> implements CashValueCalculationService {
    // super class has findAll() implementation
}

在尝试 WebSphere 7 热潮中的 OmniFaces/CDI/OpenWebBeans 之前,我已成功地将其注入 JSF 托管 bean。

当应用程序部署在服务器上时,会出现以下日志条目:

.
.
.
[13.07.17 16:56:13:889 CEST] 00000013 WebContainerL I   OpenWebBeans Container is starting...
[13.07.17 16:56:13:894 CEST] 00000013 PluginLoader  I   Adding OpenWebBeansPlugin : [OpenWebBeansJsfPlugin]
[13.07.17 16:56:13:899 CEST] 00000013 AbstractMetaD I   added beans.xml marker: wsjar:file:/C:/IBM/WebSphere7.0/AppServer/profiles/CLDSrv7050/installedApps/srv-cld-helNode03Cell/CLD.ear/lib/omnifaces-1.8.3.jar!/META-INF/beans.xml
[13.07.17 16:56:13:901 CEST] 00000013 AbstractMetaD I   added beans.xml marker: file:/C:/IBM/WebSphere7.0/AppServer/profiles/CLDSrv7050/installedApps/srv-cld-helNode03Cell/CLD.ear/cld-web.war/WEB-INF/beans.xml
[13.07.17 16:56:15:051 CEST] 00000013 AbstractMetaD W   Ignoring class [org.omnifaces.facesviews.FacesViewsInitializer] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.ServletContainerInitializer 
[13.07.17 16:56:15:322 CEST] 00000013 AbstractMetaD W   Ignoring class [org.omnifaces.component.output.cache.CacheInitializerListener] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.FilterRegistration 
[13.07.17 16:56:15:328 CEST] 00000013 AbstractMetaD W   Ignoring class [org.omnifaces.util.Platform] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.ServletRegistration 
[13.07.17 16:56:15:581 CEST] 00000013 AbstractMetaD W   Ignoring class [org.omnifaces.facesviews.FacesViewsInitializer] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.ServletContainerInitializer 
[13.07.17 16:56:15:586 CEST] 00000013 AbstractMetaD W   Ignoring class [org.omnifaces.component.output.cache.CacheInitializerListener] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.FilterRegistration 
[13.07.17 16:56:15:588 CEST] 00000013 AbstractMetaD W   Ignoring class [org.omnifaces.util.Platform] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.ServletRegistration 
[13.07.17 16:56:16:438 CEST] 00000013 AbstractMetaD W   Ignoring class [org.omnifaces.facesviews.FacesViewsInitializer] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.ServletContainerInitializer 
[13.07.17 16:56:16:443 CEST] 00000013 AbstractMetaD W   Ignoring class [org.omnifaces.component.output.cache.CacheInitializerListener] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.FilterRegistration 
[13.07.17 16:56:16:446 CEST] 00000013 AbstractMetaD W   Ignoring class [org.omnifaces.util.Platform] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.ServletRegistration 
[13.07.17 16:56:17:199 CEST] 00000013 BeansDeployer I   All injection points were validated successfully.
[13.07.17 16:56:17:236 CEST] 00000013 WebContainerL I   OpenWebBeans Container has started, it took [3345] ms.
[13.07.17 16:56:17:291 CEST] 00000013 config        I   Mojarra 2.1.27 ( 20140108-1632 https://svn.java.net/svn/mojarra~svn/tags/2.1.27@12764) für Kontext '/cld' wird initialisiert.
[13.07.17 16:56:17:739 CEST] 00000013 application   I   JSF1048: PostConstruct/PreDestroy-Annotationen vorhanden.  Verwaltete Bean-Methoden, die mit diesen Annotationen markiert sind, lassen die entsprechenden Annotationen verarbeiten.
[13.07.17 16:56:19:334 CEST] 00000013 config        W   JSF1067: Ressource /WEB-INF/common-ui.taglib.xml, die von der Konfigurationsoption javax.faces.CONFIG_FILES angegeben wird, kann nicht gefunden werden.  Die Ressource wird ignoriert.
[13.07.17 16:56:19:336 CEST] 00000013 config        W   JSF1067: Ressource /WEB-INF/common-functions.taglib.xml, die von der Konfigurationsoption javax.faces.CONFIG_FILES angegeben wird, kann nicht gefunden werden.  Die Ressource wird ignoriert.
[13.07.17 16:56:19:475 CEST] 00000013 PostConstruct I   Running on PrimeFaces 6.0.15
[13.07.17 16:56:19:478 CEST] 00000013 VersionLogger I   Using OmniFaces version 1.8.3
[13.07.17 16:56:19:497 CEST] 00000013 lifecycle     I   JSF1027: [null Die ELResolvers für JSF wurden nicht im JSP-Container registriert.
.
.
.

参赛作品

Ignoring class [org.omnifaces.facesviews.FacesViewsInitializer] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.ServletContainerInitializer 
Ignoring class [org.omnifaces.component.output.cache.CacheInitializerListener] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.FilterRegistration 
Ignoring class [org.omnifaces.util.Platform] because it could not be loaded: java.lang.NoClassDefFoundError: javax.servlet.ServletRegistration 

出现在最有趣的人面前。

但它们的真正含义是什么?

当然,有点清楚,servlet.api 类不见了。

<dependency org="javax.servlet" name="servlet-api" rev="2.5" />

(对不起,这是 Ant/Ivy 语法)

但是,在部署中添加 javax-servlet-api-2.5.jar 会在登录时完全破坏应用程序,并说“FacesServlet 不是 Servlet 类”:

在 HTML 中:

Original Exception:
Error message: javax.servlet.UnavailableException: SRVE0201E: Servlet [javax.faces.webapp.FacesServlet] is not a servlet class.
Error code: 404
Target servlet: Faces Servlet
Stacktrace:
javax.servlet.UnavailableException: SRVE0201E: Servlet [javax.faces.webapp.FacesServlet] is not a servlet class.
     at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:535)
     at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:503)
     at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:181)
     at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3954)
     at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:276)
     at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:942)
     at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1592)
     at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:186)
     at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:453)
     at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:515)
     at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:306)
     at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83)
     at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
     at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
     at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
     at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
     at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
     at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
     at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
     at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1646)

我必须尽可能地翻译错误信息。 WebSphere 7 BTW 是一个 Servlet 2.5 容器,所以问题可能与类加载器有关...?

大问题:

为什么这个设置在基本可用的场景中无法通过@EJB 注入EJB(没有javax.servlet 依赖项)? bean 和 bean manager 好像都在了,为什么不能通过@EJB注入呢?

你怎么可能治愈这个?能做到吗?

【问题讨论】:

  • 关于“不是 Servlet 类”问题 - 您不能将自己的 Servlet API 带入安装在 WebSphere 上的应用程序中。 Web 容器从它自己的库中加载 API,然后从您的应用程序中加载您的实现类。如果您的实现链接到不同的 API 类,JVM 将不认为它们兼容(因为基类是由不同的类加载器加载的)并抛出异常。
  • 在 WAS 7 中是否有任何地方可以放置 JAR,以便 servlet API 的类加载器和 OpenWebBeans 相同?
  • 只依赖服务器自带的版本即可。有一些 Java 技术,您可以将自己的 API 与您的应用程序一起使用,但 Servlet 不是其中之一,因为它的功能需要您的应用程序代码和服务器运行时之间的交互。
  • 我意识到评论对您最初的问题没有多大帮助,这看起来像是那些 Servlet 类的类加载问题......在这方面,您是否可能在其中包含了一些应用程序 jar服务器 JVM 类路径(而不仅仅是将它们打包在应用程序中)? JVM 类路径中的东西无法访问服务器中的 Java EE API,因为它位于父加载器中。如果这些异常的堆栈记录到某个地方的日志中,那可能会告诉您使用了哪个加载器。

标签: cdi websphere-7 omnifaces view-scope openwebbeans


【解决方案1】:

您是否将自己的 JSF (Myfaces) 和 CDI (OpenWebBeans) 实现嵌入到您的应用程序中? 如果您这样做,请阅读有关如何配置 WAS 以使用您自己的 JSF 实现的文档。您不能在 WAS 中覆盖/使用 CDI 实现 您也可以以 CDI 方式 (@Inject) 而非 EJB 方式注入 EJB .. (@EJB)?

【讨论】:

    【解决方案2】:

    WAS-7 实现了 JavaEE 5 标准。这还不包括 CDI。这意味着 EJB 和 CDI 之间也没有集成。

    您可以做的是编写一个使用 ProcessAnnotatedType 的 CDI 扩展,并为所有 CDI 类创建一个自定义编程 Bean,每个找到的 @EJB。 这个自定义 Bean 只是通过 JNDI 查找 EJB,就是这样。

    如果您只需要几次,那么您也可以使用 @PostConstruct 方法并直接在类中从 JNDI 上下文中获取 EJB。

    【讨论】:

      猜你喜欢
      • 2013-06-30
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 2015-02-12
      • 2012-06-03
      • 1970-01-01
      • 2023-01-26
      • 2014-01-19
      相关资源
      最近更新 更多