@PostConstruct вызывал вызов Stateful EJB, но не Stateless Почему?
Этот вопрос является ответом на другой вопрос, который я опубликовал пару недель назад: log4j2 регистрация кода в EJB jar на JBoss EAP 7. В этом посте я изложил проблему и, в конечном итоге, решение для инициализации ведения журнала на EJB, развернутых как EJB jar (не EAR) на сервере JBoss EAP 7 и вызванных из другого сервлета. Эти EJB-компоненты вызываются через локальный интерфейс.
Решение, которое я представил в этой ссылке, прекрасно работало для первого EJB, с которым я его пробовал - Stateful EJB. вызывается аннотированный @PostConstruct метод, который инициализирует контекст ведения журнала, и все отлично работает.
Решение не удалось на втором EJB, с которым я пробовал. Этот EJB был без гражданства. Метод @PostConstruct никогда не вызывается, и первая попытка регистрации взрывает проблему, потому что logger равен null. Единственное различие, которое я мог видеть между двумя бобами, было то, что второй был без состояния, тогда как первый был с состоянием. В качестве эксперимента я сделал второй с состоянием. Как только я это сделал, был вызван @PostConstruct, логирование было инициализировано, и все было в основном нормально.
Согласно учебному руководству по Oracle JavaEE6, метод @PostConstruct должен вызываться при создании экземпляра компонента без сохранения состояния. Итак, почему инстанцирование сессионного компонента с сохранением состояния вызывает @PostConstruct, а инстанцирование сессионного компонента без сохранения состояния - нет, и что я могу с этим сделать?
Благодарю.
Обновление: добавление исходного кода.
EJB-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee"
version="3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd">
<module-name>DealerLocatorBean</module-name>
<enterprise-beans>
<session>
<ejb-name>DealerLocatorBean</ejb-name>
<home>com.whatever.ServiceLogicHome</home>
<remote>com.whatever.ServiceLogic</remote>
<local-home>com.whatever.ServiceLogicLocalHome</local-home>
<local>com.whatever.ServiceLogicLocal</local>
<ejb-class>com.whatever.ejbs.DealerLocatorBean</ejb-class>
<session-type>Stateless</session-type>
<!-- <session-type>Stateful</session-type> No problem if this is made stateful-->
<transaction-type>Bean</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
DealerLocatorBean.java:
public class DealerLocatorBean implements SessionBean
{
private static final String LOGGER_CONFIG = "/path/to/log4j2.xml";
private static final String LOGGER_CONTEXT_NAME = "VTDLLOC-EJB";
private static LoggerContext logctx;
private static Logger logger = null;
public DealerLocatorBean() {
System.out.println("calling DealerLocatorBean() constructor");
}
@PostConstruct
@TransactionAttribute(value=TransactionAttributeType.NOT_SUPPORTED)
private void postConstruct() {
System.out.println("DealerLocatorBean.postConstruct()");
logctx = Configurator.initialize(LOGGER_CONTEXT_NAME, LOGGER_CONFIG);
logger = logctx.getLogger(getClass().getName());
logger.log(Level.INFO, ("postConstruct() in DealerLocatorBean called"));
logger.log(Level.INFO, ("******END OF THE postConstruct() CALL******"));
}
@PreDestroy
@TransactionAttribute(value=TransactionAttributeType.NOT_SUPPORTED)
private void preDestroy() {
logger.log(Level.INFO, ("preDestroy() in DealerLocatorBean called. Shutting down logging."));
Configurator.shutdown(logctx);
}
Если bean-компонент развернут как с состоянием (в ejb-jar.xml), @postConstruct вызывается при первом использовании bean-компонента после развертывания, и все работает. DealerLocatorBean.postConstruct()
видно в выводе и все последующие записи в журнал работает.
Если bean-компонент развернут как без сохранения состояния (в ejb-jar.xml), @postConstruct никогда не вызывается. DealerLocatorBean.postConstruct()
НЕ виден на выходе. Ведение журнала не инициализируется, и исключения NullPointerExceptions возникают, как только код пытается что-то записать в журнал.
1 ответ
Вы видели, как этот компонент сообщается в журналах как развернутый? Также не разрешены финальные статики в SLSB. Я бы предложил изменить приватный статический LoggerContext logctx; в закрытое статическое окончание LoggerContext logctx= Configurator.initialize(LOGGER_CONTEXT_NAME, LOGGER_CONFIG); если возможно и то же самое для logger и удалите соответствующие операторы из @PostConstruct или просто удалите ключевое слово static в объявлениях logctx и logger.