Reputation: 210
I have two stateless SessionBeans. My client (JSF2 application) is calling a method (saveOrderCompletion) on the first EJB (CompletionFacade), which calls another method (processRequest) on the second EJB (ContactFacade) to send a message to a queue via JMS.
At the end of the first called method I am throwing a RuntimException to see how JBoss behaves. This should all run in one transaction, thus the transaction should do a rollback, so that no message should be sent to the queue.
I double checked this this on weblogic server, which shows exactly the expeced behaviour. My question is why JBoss does not rollback the entire transaction? Did I miss something...
The entity is not being persisted, but the message is sent to the queue anyway.
I am using jboss 7.1.1, app is deployed as EAR
Here are my session beans...
/**
* Session Bean implementation class CompletionFacade
*/
@Stateless
public class CompletionFacade implements CompletionFacadeRemote, CompletionFacadeLocal {
@PersistenceContext(unitName="my_test")
private EntityManager entityManager;
@EJB
ContactFacadeLocal contactFacade;
.....
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public OrderCompletion saveOrderCompletion(OrderCompletion orderCompletion) throws TestBusinessException {
try {
...do some stuff on entity
//persist to get id
entityManager.persist(orderCompletion);
//finally send email
contactFacade.processRequest(orderCompletion,partner);
if (0 == 0)
throw new RuntimeException("Test RuntimeException ");
} catch (TestGenericException re) {
throw new TestBusinessException("Could not print orderCompletion: " ,re);
} catch (DocumentException e) {
throw new TestBusinessException("Could not print orderCompletion: " ,e);
}
return orderCompletion;
}
}
and the second facade:
@Stateless
public class ContactFacade implements ContactFacadeRemote, ContactFacadeLocal {
....
/*
* actually create message
*/
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void processRequest(Object request, SmtpPartner partner) throws TestGenericException {
if (logger.isDebugEnabled()) {
logger.debug("Starting to process request!");
}
QueueConnection connection = null;
QueueSession session = null;
try {
...lookup queue etc...
sender.send(QUEUE, objectMessage);
} catch (JMSException e) {
logger.error("MS Exception:", e);
} catch (NamingException e) {
logger.error("Naming exception:", e);
} ...
} finally {
try {
session.close();
connection.close();
} catch (JMSException e) {
logger.error("Error closing connection:", e);
}
}
}
...
}
Any help is highly appreciated.
Upvotes: 4
Views: 855
Reputation: 3769
You've left the most important part out; the JMS connection factory where you obtain the connection from and the way how you got hold of this factory.
Make sure you inject this factory, and that you use a transactional one. In JBoss AS 6, java:/JmsXA was the transactional one, and java:/ConnectionFactory the unmanaged/not-transactional alternative. Check that for AS 7 you are using the right one.
Upvotes: 3