NPE из workmanager при попытке получить класс, уже загруженный в приложение

Я работаю с WebSphere 8.5 и JSF2.0, и у меня возникла проблема с использованием WorkManager (из websphere - асинхронный компонент). У меня есть класс workManagerExample, который реализует рабочий интерфейс. Когда я вызываю workManagerExample из моего приложения, я больше не могу получить методы класса, уже загруженные в мое приложение. Ситуация: у меня в приложении есть класс Utility (который работает нормально), но когда я пытаюсь использовать его (например, Utility.someMethod) из workManagerExample, я получаю NPE. Я проверил класс Utility перед вызовом 'startWork(WorkManagerExample)' и он не нулевой, я могу использовать его как обычно. Кстати, workManager работает нормально, без вызова каких-либо уже загруженных классов из моего приложения. Я не могу передать класс Utility в качестве параметра конструктора workManagerExample (это ограничение от клиента / клиента). Мой вопрос: почему я больше не использую функции класса Utility из этого 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>

Это мой справочник http://www.bencode.net/blog/2014/07/26/was-async-beans/

Некоторый код Java: Class1.java

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

В GetInfoWork.java, когда я пытаюсь 'FacesContext.getCurrentInstance();' Я всегда получаю NULL, но если я попробую из Class1.java, он будет работать как положено. Структура папок, как обычно, веб-приложение JSF2, это уже существующее приложение, и теперь я хочу добавить эту функциональность Async Bean через workManager (из com.ibm.ws.runtime.jar).

1 ответ

Решение

FacesContext.getCurrentInstance() это не ваш служебный класс, а внутренняя часть инфраструктуры JSF. Если вы посмотрите на документацию по Java:

public static FacesContext getCurrentInstance()

Вернуть экземпляр FacesContext для запроса, который обрабатывается текущим потоком.

FacesContext для правильной работы нужен поток, обрабатывающий веб-запрос, и асинхронный компонент вызывается в отдельном потоке, который вообще не знает о контексте JSF, и именно поэтому вы получаете нулевое значение. Ваш Class1 вызывается потоком, обрабатывающим веб-запрос.

Однако вы ошибаетесь в своем утверждении:
Я не могу передать класс Utility в качестве параметра конструктора workManagerExample (это ограничение).

Я не знаю, где вы нашли это ограничение, но это не так. См. Инфоцентр - Разработка рабочих объектов для параллельного выполнения кода

Итак, ваш код должен быть примерно таким:

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

ОБНОВИТЬ
Если не через конструктор, вы можете передать его через метод setter. Но не пройти FacesContext, но то, что вам действительно нужно, так как некоторые данные из этого контекста будут недействительными после завершения веб-запроса. например:

GetInfoWork currentOfferWork = new GetInfoWork(); //GetInfoWork implements Work
currentOfferWork.setMyParam1(param1);
currentOfferWork.setMyParam2(param2);
workManager.startWork(currentOfferWork);
Другие вопросы по тегам