这个问题是我几周前发布的另一个问题的分支: log4j2 logging of code in EJB jar on JBoss EAP 7。在那篇文章中,我提出了一个问题,并最终解决了将部署为EJB jars(非EAR)的EJB上的初始化记录到JBoss EAP 7 Server上并从另一个servlet调用的问题。这些EJB是通过本地接口调用的。
我在该链接中提供的解决方案非常适用于我尝试使用的第一个EJB,一个有状态的EJB。调用@ PostConstruct-annotated方法并初始化日志记录上下文,一切都很好。
我尝试使用的第二个EJB上的解决方案失败了。这个EJB是无状态的。永远不会调用@PostConstruct方法,并且由于logger为null,因此第一次尝试记录会破坏事物。我可以看到两个豆之间的唯一区别是第二个是无国籍的,而第一个是有状态的。作为一个实验,我使第二个有状态。一旦我这样做,@ PostConstruct被调用,日志记录被初始化,一切都基本上没问题。
根据 Oracle JavaEE6 tutorial,@ PostConstruct方法应该在无状态bean实例化上调用。那么,为什么有状态会话bean实例化调用@PostConstruct而无状态会话bean实例化却没有,我该怎么办呢?
感谢。
更新:添加源代码。
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中),则在部署后第一次使用bean时调用@postConstruct,一切正常。输出中可以看到DealerLocatorBean.postConstruct()
,并且所有子记录都可以正常工作。
如果将bean部署为无状态(在ejb-jar.xml中),则永远不会调用@postConstruct。输出中未显示DealerLocatorBean.postConstruct()
。日志记录未初始化,并且一旦代码尝试通过记录器记录某些内容,就会产生NullPointerExceptions。
答案 0 :(得分:0)
您是否看到此bean已部署到日志中? SLSB中也不允许使用最终静态。我建议更改私有静态LoggerContext logctx;私有静态最终LoggerContext logctx = Configurator.initialize(LOGGER_CONTEXT_NAME,LOGGER_CONFIG);如果可能,对于记录器也是一样的,并从@PostConstruct中删除相应的语句,或者只删除logctx和logger声明中的static关键字。