Search code examples
websphereworkmanagers

NPE from workmanager when try to get a class already loaded in the application


I'm working with WebSphere 8.5 and JSF2.0 and I have a problem using WorkManager (from websphere - async bean). I have a workManagerExample class that implements Work interface. When I call the workManagerExample from my application I'm not longer available to get the methods of a class already loaded in my app. Situation: I have an Utility class in my app (which it is working fine) but when a try to use it (like Utility.someMethod) from the workManagerExample I'm getting a NPE. I checked the Utility class before calling the 'startWork(WorkManagerExample)' and is not null, I can use it as usual. BTW the workManager is working fine without calling any already loaded classes from my app. I can't pass the Utility class as a parameter of workManagerExample constructor (this is a restriction from the client/customer guy). My question is why I'm not longer to use the Utility class functions from this Asyn Bean?

web.xml
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
//some extra config not related
    <resource-ref>
        <description>WorkManager</description>
        <res-ref-name>wm/default</res-ref-name>
        <res-type>com.ibm.websphere.asynchbeans.WorkManager</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref> 
</web-app>

ibm-web-bnd.xml
<web-bnd xmlns="http://websphere.ibm.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_0.xsd"
version="1.0">
    <virtual-host name="default_host" />
    <resource-ref name="wm/default" binding-name="wm/default" />
</web-bnd>

This is my reference guide http://www.bencode.net/blog/2014/07/26/was-async-beans/

Some java code: Class1.java

WorkManager workManager = getWorkManager();
if (workManager!=null){   
  GetInfoWork currentOfferWork = new GetInfoWork(); //GetInfoWork implements Work
  workManager.startWork(currentOfferWork);  
}

In GetInfoWork.java, when I try 'FacesContext.getCurrentInstance();' I always get NULL but If I try from Class1.java it works as expected. Folder structure is as usual JSF2 web app, this is an existing application and now I want to add this Async Bean functionality through workManager (from com.ibm.ws.runtime.jar).


Solution

  • FacesContext.getCurrentInstance() is not your utility class, but internal part of the JSF framework. If you take a look at java doc:

    public static FacesContext getCurrentInstance()
    

    Return the FacesContext instance for the request that is being processed by the current thread.

    FacesContext needs a thread handling a web request to work correctly and async bean is called in separate thread, which doesn't know about JSF context at all, and thats the reason why you are getting null. Your Class1 is called by thread handling the web request.

    However you are incorrect in your statement:
    I can't pass the Utility class as a parameter of workManagerExample constructor (this is a restriction).

    I don't know where you found this restriction, but is not true. See the Infocenter - Developing work objects to run code in parallel

    So your code should be something like this:

    WorkManager workManager = getWorkManager();
    if (workManager!=null){ 
      // extract from FacesContext what you need
      ....
      // and pass it to work item  
      GetInfoWork currentOfferWork = new GetInfoWork(pass, whatEver, objectsYouNeed, inWork); //GetInfoWork implements Work
      workManager.startWork(currentOfferWork);  
    }
    

    UPDATE
    If not via constructor you can pass it via setter method. But do not pass FacesContext, but the stuff you really need, as some data from that context will be invalid after end of web request. e.g.:

    GetInfoWork currentOfferWork = new GetInfoWork(); //GetInfoWork implements Work
    currentOfferWork.setMyParam1(param1);
    currentOfferWork.setMyParam2(param2);
    workManager.startWork(currentOfferWork);