Активация MDB для сообщения JMS до совершения транзакции JTA - PullRequest
3 голосов
/ 07 декабря 2011

Мне нужно синхронизировать транзакцию JTA с отправкой сообщения JMS - MDB должен быть активирован после фиксации транзакции JTA клиента.Это возможно при использовании XAConnectionFactory, но в моем примере это не работает.

Пример сценария:

  • клиент веб-службы отправляет сообщение с кодом = 0
  • mdb получает сообщение и печатает: START: код (НОВАЯ СДЕЛКА JTA)
  • инкрементный код mdb и печатает: SEND:% code + 1%
  • mdb отправляет сообщение с новым значением кода
  • mdb sleep
  • mdb print: END code
  • mdb finish (TRANSACTION COMMIT)

Сценарий повторяется до тех пор, пока код <10. Я ожидаю результата: </p>

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

Что я делаю не так?

1 Ответ

4 голосов
/ 08 декабря 2011

Я обнаружил, что у меня нет контекста транзакции на MDB !!!

Когда я проверил идентификатор транзакции, позвонив по номеру

weblogic.transaction.TxHelper.getTransactionId() 

получил ноль, а при вызове 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)

все работает нормально.

:)

...