【问题标题】:MDB activation for JMS message before the JTA transaction is committed在提交 JTA 事务之前为 JMS 消息激活 MDB
【发布时间】:2011-12-07 13:20:24
【问题描述】:

我需要将 JTA 事务与发送 JMS 消息同步 - MDB 应在客户端 JTA 事务提交后激活。 这在使用 XAConnectionFactory 时应该是可能的,但在我的示例中不起作用。

示例场景:

  • Web 服务客户端发送代码 = 0 的消息
  • mdb 接收消息并打印:START: code (NEW JTA TRANSACTION)
  • mdb 增量代码并打印:SEND: %code + 1%
  • mdb 发送带有新代码值的消息
  • mdb 睡眠
  • mdb 打印:END 代码
  • mdb 完成(事务提交)

场景重复,直到代码

START: 0
SEND: 1
END: 0
START: 1
SEND: 2
END: 1
START: 2
SEND: 3
END: 2
etc..

但目前我得到:

...
START: 4
SEND: 5
END: 3
START: 5
SEND: 6
END: 4
START: 6
SEND: 7
END: 5
END: 6

我的代码:

  • 网络服务客户端

    @WebMethod
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void publish() {
        TestQueueUtil.sendToQueue(0);
    }
    
  • TestQueueUtil(JMS 客户端)

    public static void sendToQueue(Integer code) {
      InitialContext initialContext;
      XAQueueConnection queueConnection = null;
      XAQueueSession queueSession = null;
    
      try {
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
        initialContext = new InitialContext(env);
        XAConnectionFactory queueConnectionFactory = (XAConnectionFactory) initialContext.lookup("jms/dsk/ConnectionFactoryXA");
    
        queueConnection = (XAQueueConnection) queueConnectionFactory.createXAConnection();
        queueConnection.start();
    
        queueSession = queueConnection.createXAQueueSession();
        Queue queue = (Queue) initialContext.lookup("jms/dsk/TestQueue");
    
        //QueueSender sender =
        MessageProducer producer = queueSession.createProducer(queue);
        Message jmsMessage = queueSession.createMessage();
    
        jmsMessage.setIntProperty("code", code);
        producer.send(jmsMessage);
        producer.close();
        queueConnection.stop();
    
    } catch (Exception e) {
        throw new RuntimeException("sendToQueue", e);
    } finally {
        if (queueSession != null) {
            try {
                queueSession.close();
            } catch (Exception e) {
                //ignore
            }
        }
        if (queueConnection != null) {
            try {
                queueConnection.close();
            } catch (Exception e) {
                //ignore
            }
        }
      }
    
    }
    
  • TestQueueMDB

    @MessageDriven(mappedName = "jms/dsk/TestQueue", activationConfig = {
            @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
            @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })
    public class TestQueueMDB implements MessageListener {
    
        @Resource
        protected MessageDrivenContext messageDrivenContext;
    
        @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
        public void onMessage(Message message) {
            Integer code = null;
            try {
    
                code = message.getIntProperty("code");
                System.out.println("START: " + code);
                if (code < 10) {
                    Integer newcode = code + 1;
                    System.out.println("SEND: " + newcode);
                    TestQueueUtil.sendToQueue(newcode);
                    Thread.sleep(2000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                System.out.println("END: " + code);
            }
        }
    }
    

我做错了什么?

【问题讨论】:

    标签: jakarta-ee jms jta


    【解决方案1】:

    我发现我在 MDB 上没有事务上下文!!!

    当我通过调用检查交易 ID 时

    weblogic.transaction.TxHelper.getTransactionId() 
    

    收到null,当调用messageDrivenContext.getRollbackOnly()得到异常

    java.lang.IllegalStateException: [EJB:010156]Illegal attempt to call EJBContext.getRollbackOnly() from an EJB that was not participating in a transaction.
    

    原因是注释

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    

    删除或更改后

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    

    一切正常。

    :)

    【讨论】:

    • 这些都是很奇怪的症状。确实,MDB 只允许 NOT_SUPPORTED 或 REQUIRED 事务注释,但我宁愿期望在部署时抛出异常,而不是默默地忽略 REQUIRES_NEW。即便如此,为有趣的后续行动 +1。
    猜你喜欢
    • 2011-01-25
    • 2013-01-13
    • 1970-01-01
    • 2016-10-23
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 2020-03-26
    • 1970-01-01
    相关资源
    最近更新 更多