@PostConstruct调用有状态EJB调用但不是无状态为什么?

时间:2016-12-01 17:07:31

标签: jboss ejb stateless-session-bean postconstruct stateful-session-bean

这个问题是我几周前发布的另一个问题的分支: 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。

1 个答案:

答案 0 :(得分:0)

您是否看到此bean已部署到日志中? SLSB中也不允许使用最终静态。我建议更改私有静态LoggerContext logctx;私有静态最终LoggerContext logctx = Configurator.initialize(LOGGER_CONTEXT_NAME,LOGGER_CONFIG);如果可能,对于记录器也是一样的,并从@PostConstruct中删除相应的语句,或者只删除logctx和logger声明中的static关键字。