logging - 使用 EJB 3 发送 JMS 消息时的事务划分

标签 logging ejb jms ejb-3.0 message-driven-bean

在我的 Java EE 应用程序中,我实现了一个异步数据库记录器作为 MDB,它通过 JMS 接收 XML 消息并将它们写入数据库。

在另一个 MDB 中,我创建一条日志消息,并使用以下代码将它们发送到记录器 MDB 的输入队列:

    public static void log(String correlId, String message, String data) throws Exception{

            SysLogEntry sysLogEntry = new SysLogEntry();
            sysLogEntry.setCorrelId(correlId);
            sysLogEntry.setDatetimeCreate(new Date());
            sysLogEntry.setMessage(message);
            sysLogEntry.setData(data);

            ConnectionFactory jmsConnectionFactory = (ConnectionFactory)initialContext.lookup(JMS_CONNECTION_FACTORY_JNDI_NAME);
            Destination logEventDestination = (Destination) initialContext.lookup(LOG_EVENT_DESTINATION_JNDI_NAME);

            JmsUtils.sendMsgToDestination(JaxbUtils.toString(sysLogEntry, jaxbContext), jmsConnectionFactory, logEventDestination, false, Session.AUTO_ACKNOWLEDGE);

        }

public static void sendMsgToDestination(String payload, ConnectionFactory connFactory, Destination destination, boolean sessionTransacted, int acknowledgeMode) throws JMSException{
        if(payload == null)
            throw new IllegalArgumentException("Message payload is null");
        if(connFactory == null)
            throw new IllegalArgumentException("Connection factory is null");
        if(destination == null)
            throw new IllegalArgumentException("Message destination is null");

        Connection connection = null;
        try{
            connection = connFactory.createConnection();
            Session session = connection.createSession(sessionTransacted, acknowledgeMode);
            MessageProducer messageProducer = session.createProducer(destination);
            TextMessage textMessage = session.createTextMessage();
            textMessage.setText(payload);
            messageProducer.send(textMessage);
        } finally {
            if(connection != null){
                try{
                    connection.close();
                } catch (JMSException ignore){

                }
            }
        }
    }

哪里

  • SysLogEntry 是一个带有 JAXB 注释的类,我用它来进行序列化
  • JMS_CONNECTION_FACTORY_JNDI_NAME 是 XA 连接工厂的 JNDI 名称

但是,每次回滚创建日志消息的事务时,日志消息都不会放入记录器输入队列中。

有人可以告诉我我的代码有什么问题吗?我考虑过使用一个单独的无状态 session bean,它将启动一个新事务来生成日志消息,但这种方法有一个缺点:在 EJB 内,我可以轻松地让容器注入(inject)记录器 bean,但我也有非 EJB我想在其中进行异步日志记录的对象。

我的应用程序服务器是Weblogic 10.3.3

最佳答案

如果出现系统异常(或sessionContext.setRollbackOnly),全局事务将由容器回滚(如果您使用容器管理的事务)。 这意味着对全局事务中列出的 XA 感知资源的任何操作都会回滚。

在您的情况下,这包括您想要发送到记录器的待处理消息。这一项被删除,因为事务已回滚。


就您的情况而言,如果您使用非 XA 连接工厂,那么这应该足够了。这样消息应该立即发送(如果有记录器甚至有帮助)。因此,发送在仅跨越 JMS 发送任务的本地事务中运行。

对于非 EJB 对象:您可以使用非 XA 连接工厂将发送功能提取到普通 Java 类(= 不是 EJB)中,并从 EJB 和普通类中使用它。

关于logging - 使用 EJB 3 发送 JMS 消息时的事务划分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18571387/

相关文章:

java - 如何找出阻止 FileAppender 正常滚动的原因

java - 将 EJB 注入(inject) servlet

java - WebSphere javax.naming.NamingException 和连接被拒绝

java - 在 Java 类中注入(inject) EJB 时出现 NullPointerException

java - JMS中上下文的目的是什么?

python 日志记录格式 : how to add bracket

java - 日志记录停止滚动到新文件

java - 使用 Log4j2 2.8.1 在运行时动态添加文件日志记录

java - 如何在 activemq.xml 中创建/预配置持久订阅者,以便这些订阅在 ActiveMQ 启动时准备就绪?

java - JBoss 5.1 - TopicConnection.createTopicSession 有时会挂起