I wonder how to use JMS transactions correctly inside an EJB container. I found this code, that sends messages using JMS in a stateless bean:
@Stateless
public class SendEventsBean {
private static final Logger log = Logger.getLogger(SendEventsBean.class);
@Resource(mappedName = "jms/MyConnectionFactory")
private ConnectionFactory jmsConnectionFactory;
@Resource(mappedName = "jms/myApp/MyQueue")
private Queue queue;
public void sendEvent() {
Connection jmsConnection = null;
try {
connection = jmsConnectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
MyObj obj = new MyObj(1, "Foo");
ObjectMessage myObjMsg = session.createObjectMessage(obj);
producer.send(myObjMsg);
} catch (JMSException jmxEx) {
log.error("Couldn't send JMS message: ", jmsEx);
}finally{
if (jmsConnection != null) {
try {
jmsConnection.close();
}catch(JMSException ex) {
log.warn("Couldn't close JMSConnection: ", ex);
}
}
}
}
(from When should I close a JMS connection that was created in a stateless session bean? )
At default the transactions are container managed with transaction attribute 'required'. Suppose a client calls sendEvent() directly, so that the transaction starts at the beginning and ends at the end of sendEvent() (-> a commit is executed at the very end of the method). Isn't it wrong to close the connection (jmsConnection.close()) BEFORE the commit occurs at the very end of the method?
Furthermore I'm wondering how setting the transactional attribute and setting true/false at createSession() interacts.
Does it make sense setting createSession(true,...) if there is already a transaction started by the container (using container managed transactions)? Does this create a new transaction just for JMS messages (and not for DB also) inside the JTA transaction?
And with createSession(false, ...) am I right, that messages are nevertheless transactional because of the transaction started by the container?