chrisF
chrisF

Reputation: 210

Jboss 7.1.1 Transaction, cascade EJB methods

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

Answers (1)

Mike Braun
Mike Braun

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

Related Questions