简体   繁体   中英

OmniFaces CDI @ViewScoped bean deployed on WebSphere 7 (Java EE 5) nulls all EJBs injected with @EJB: NPE/NullPointerException

I have a simple OmniFaces 1.8.3 view-scoped bean successfully deployed on WebSphere 7 (7.0.50) along with OpenWebBeans 1.2.8 (and Mojarra 2.1.27 BTW):

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;
    }
}

When opening the view of the bean however, the bean gets initialized running the @PostConstruct method to load all entities (just a handful), but this fails with a NullPointerException in loadViewData(). The returned service is null... this basically gets confirmed by the log in which I also find the line

this.cashValueCalculationService = null

The CashValueCalculationService interface is annotated with @Local and the implementation CashValueCalculationServiceBean is annotated with @Stateless :

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

Bean:

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

I had this successfully being injected into JSF managed beans before trying the OmniFaces/CDI/OpenWebBeans on WebSphere 7 craze.

When app gets deployed on the server the following log entries appear:

.
.
.
[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.
.
.
.

The entries

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 

appear to the most interesting ones.

But what do they actually mean?

Of course, it's somewhat clear, the servlet.api classes are missing.

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

(Sorry this is Ant/Ivy syntax)

However adding javax-servlet-api-2.5.jar to the deployment totally breaks the app when logging in, saying "FacesServlet is not a Servlet class":

In 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)

I had to translate the error message as best as I could. WebSphere 7 BTW is a Servlet 2.5 container, so the problem might be classloader-related... ?

BIG QUESTION(s):

Why is this setup failing to inject EJBs via @EJB on the basically usable scenario (without the javax.servlet dependency)? The bean and bean manager seem to be present, so why isn't it able to inject via @EJB ?

How do you possibly cure this? Can it be done at all?

Are you embedding your own JSF (Myfaces) and CDI (OpenWebBeans) implementation with your application? If you do so, please read the doc on how to configure WAS to use your own JSF implementation. You can not override/use the CDI implementation in WAS Also you could inject the EJB in the CDI way ( @Inject ) instead of the EJB way.. ( @EJB )?

WAS-7 implements the JavaEE 5 standard. This did not include CDI yet. That means that there is also no integration between EJB and CDI.

What you can do is to write a CDI Extension which uses ProcessAnnotatedType and for all CDI classes you create a custom programmatic Bean per found @EJB. This custom Bean simply looks up the EJB via JNDI and that's it.

If you only need this a few times then you could also use a @PostConstruct method and fetch the EJB from the JNDI context directly in the class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM