在提交JTA事务之前对JMS消息进行MDB激活

时间:2011-12-07 13:20:25

标签: java-ee jms jta

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

示例场景:

  • Web服务客户端发送代码= 0
  • 的消息
  • mdb接收消息并打印:START:代码(NEW JTA TRANSACTION)
  • mdb增加代码并打印:发送:%code + 1%
  • mdb使用新代码值发送消息
  • mdb sleep
  • mdb print:END code
  • mdb finish(TRANSACTION COMMIT)

场景重复直到代码< 10.我期待结果:

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

我的代码:

  • Webservice客户端

    @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);
            }
        }
    }
    

我做错了什么?

1 个答案:

答案 0 :(得分:4)

我发现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)

一切正常。

:)