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