Zeus
Zeus

Reputation: 6576

Nested transaction in ejb sessionbean - bean managed transaction

I have the following code which saves the user and sends a JMS message. Currently im wraping the saveUserSendMessage with the UserTransaction. When the transaction is nested I get a exception in the ejb. What do I do below to make the nested transaction possible?

@Resource(mappedName = "java:/JmsXA")
private static QueueConnectionFactory queueConnectionFactory;

@Resource(mappedName = "EjbQueueJndi")
private static Queue queueProp;

@PersistenceContext(unitName = "ejbPersistanceunit")
private EntityManager em;

@Resource
UserTransaction ut;

@Override
public boolean saveUserSendMessage(String name, String email, int age,
        boolean arg3) throws Exception {

    UserTransaction xact = ut;
    xact.begin();

    saveUser(name, email, age);
    sendMessage("Successfully saved the user");
    try {
        if (arg3)
            throw new Exception("Unsuccessfull");
        xact.commit();
    } catch (Exception e) {
        xact.rollback();
        throw e;
    }
    return true;
}

@Override
public boolean saveUser(String name, String email, int age)
        throws Exception {
    try {
        ut.begin();
        UserEntity ue = new UserEntity();
        ue.setAge(age);
        ue.setEmail(email);
        ue.setName(name);
        em.persist(ue);
        ut.commit();
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
    return true;
}

Exception i get:

15:51:04,127 ERROR [STDERR] javax.transaction.NotSupportedException: BaseTransaction.checkTransactionState - [com.arjuna
.ats.internal.jta.transaction.arjunacore.alreadyassociated] [com.arjuna.ats.internal.jta.transaction.arjunacore.alreadya
ssociated] thread is already associated with a transaction!

Upvotes: 1

Views: 2112

Answers (1)

Brett Kail
Brett Kail

Reputation: 33956

Java EE does not support nested transactions. The only thing it supports is suspending a transaction, running an unrelated transaction, and the resuming the first transaction.

To accomplish that, you would need to call another EJB that uses RequiresNew transaction attribute. Note that the inner transaction can complete even if the message receipt rolls back, which means if the messaging engine crashes, the second transaction might be run again. Alternatively, you could change the EJB to use bean-managed transactions, which would have a similar effect.

Are you sure you really want to do that? It's probably best to just execute the logic within the container-managed transaction.

Upvotes: 3

Related Questions