I have an EJB module that has to synchronously exchange messages with a MDB in another module via TemporaryQueue. The EJB container (in my case it's Glassfish 4.0) assumes transactional environment, do I have to use BEAN-managed transaction and denote start and end of transactions using UserTransaction object.
The outline of my code is like this:
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class CommunicationJMSUtils {
@Resource
private UserTransaction ut;
@Inject
private JMSContext context;
@Resource(lookup = "jms/DestinationQueue")
private Queue destination;
private static final long JMS_COMMUNICATION_TIMEOUT = 5000;
public Map<String, String> getClientordersData(String id) throws JMSException {
try {
MapMessage mm = context.createMapMessage();
ut.begin();
TemporaryQueue replyQueue = context.createTemporaryQueue();
mm.setJMSReplyTo(replyQueue);
mm.setStringProperty(<...>);
<...>
mm.setString(<...>);
<...>
context.createProducer().send(destination, mm);
ut.commit();
ut.begin();
ObjectMessage om = (ObjectMessage) context.createConsumer(replyQueue).receive(JMS_COMMUNICATION_TIMEOUT);
ut.commit();
if (om != null) {
return om.getBody(Map.class);
} else {
throw new JMSException("Failed to receive reply within " + JMS_COMMUNICATION_TIMEOUT);
}
} catch (NotSupportedException | RollbackException | HeuristicMixedException | HeuristicRollbackException | SecurityException | IllegalStateException | SystemException ex) {
<...>
}
}
}
The first problem is that from time to time this code (receive part) fails with exception
MQJMSRA_DS4001: _checkDestination:Temporary Destination not owned by parent connectionId=1760697170479431168
although evidently TemporaryQueue is created with same JMSContext.
And the second problem is the "fragility" of this code. If I put context.createMapMessage() inside the first transaction or move TemporaryQueue creation out of the first transaction this snippet will definately fail.
Unfortunately, JMS tutorials/documentation do not really cover that particular use-case. What is the correct way to implement the JMS request/response pattern with JMS 2.0 in Java EE?