ActiveMQ Artemis JMS XA Send Example

# JMS XA Send Example

This example shows you how message sending behaves in an XA transaction in ActiveMQ Artemis. When a message is sent within the scope of an XA transaction, it will only reach the queue once the transaction is committed. If the transaction is rolled back the sent messages will be discarded by the server.

ActiveMQ Artemis is JTA aware, meaning you can use ActiveMQ Artemis in a XA transactional environment and participate in XA transactions. It provides the javax.transaction.xa.XAResource interface for that purpose. Users can get a XAConnectionFactory to create XAConnections and XASessions.

In this example we simulate a transaction manager to control the transactions. First we create an XASession and enlist it in a transaction through its XAResource. We then send two words, 'hello' and 'world', with the session, let the transaction roll back. The messages are discarded and never be received. Next we start a new transaction with the same XAResource, but this time we commit the transaction. Both messages are received.

## Example step-by-step

To run the example, simply type `mvn verify -Pexample` from this directory

1. First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the `client-jndi.properties` file in the directory `../common/config`

               InitialContext initialContext = getContext(0);

2. We look-up the JMS queue object from JNDI

               Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");

3. We perform a lookup on the XA Connection Factory

               XAConnectionFactory cf = (XAConnectionFactory) initialContext.lookup("/XAConnectionFactory");

4. We create a JMS XAConnection

               connection = cf.createXAConnection();

5. We Start the connection

               connection.start();

6. We create a JMS XASession

              XASession xaSession = connection.createXASession();

7. We create a normal session

              Session normalSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

8. We create a normal Message Consumer

               MessageConsumer normalConsumer = normalSession.createConsumer(queue);
               normalConsumer.setMessageListener(new SimpleMessageListener());

9. We get the JMS Session

              Session session = xaSession.getSession();

10. We create a message producer

              MessageProducer producer = session.createProducer(queue);

11. We create two Text Messages

              TextMessage helloMessage = session.createTextMessage("hello");
              TextMessage worldMessage = session.createTextMessage("world");

12. We create a transaction

              Xid xid1 = new XidImpl("xa-example1".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());

13. We get the JMS XAResource

              XAResource xaRes = xaSession.getXAResource();

14. We begin the Transaction work

              xaRes.start(xid1, XAResource.TMNOFLAGS);

15. We do work, sending two messages.

              producer.send(helloMessage);
              producer.send(worldMessage);

16. We check the result, it should receive none!

              checkNoMessageReceived();

17. We stop the work

              xaRes.end(xid1, XAResource.TMSUCCESS);

18. We prepare

              xaRes.prepare(xid1);

19. We roll back the transaction

              xaRes.rollback(xid1);

20. We check no messages should be received!

              checkNoMessageReceived();

21. We create another transaction

              Xid xid2 = new XidImpl("xa-example2".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());

22. We start the transaction

              xaRes.start(xid2, XAResource.TMNOFLAGS);

23. We re-send those messages

               producer.send(helloMessage);
               producer.send(worldMessage);

24. We stop the work

              xaRes.end(xid2, XAResource.TMSUCCESS);

25. We prepare

              xaRes.prepare(xid2);

26. We check that no messages should be received at this moment

              checkNoMessageReceived();

27. We commit!

              xaRes.commit(xid2, false);

28. We check that all messages are received.

              checkAllMessageReceived();

29. And finally, always remember to close your JMS connections and resources after use, in a `finally` block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects

               finally
               {
                  if (initialContext != null)
                  {
                    initialContext.close();
                  }
                  if (connection != null)
                  {
                     connection.close();
                  }
               }