JMS inside JTA

Quite often an EJB (whether it is a stateful or stateless) needs to send messages to a JMS queue or a JMS topic. In order for the sending of JMS messages to be part of the JTA transaction, you need to know what to do when constructing the JMS session.

 

The key is that when you create the queue (or topic) session, you need to set the transacted parameter (the first argument) of the createQueueSession (or createTopicSession) method to false. If you set it to true, it means that you are going to control the transaction - not the container.

 

Here is the code fragment that sends a message to a queue and be part of the JTA transaction if it runs within a EJB container.

Context context = new InitialContext();
QueueConnectionFactory qFactory = (QueueConnectionFactory) context.lookup("QueueConnectionFactory");
QueueConnection qConnection = qFactory.createQueueConnection();
Queue queue = (Queue) context.lookup("MyQueue");
QueueSession qSession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender qSender = qSession.createSender(queue);
Message message = qSession.createTextMessage();
message.setText("some text");
qSender.send(message);

 

That means, inside your EJB method, you can do stuff like updating databases and sending JMS messages. If everything goes fine, all operations will be committed at the end of the method. Otherwise, all operations will be rolled back.