4
votes

Inside a BMT (using a UserTransaction) I call a method on another stateless EJB. When I rollback this transaction, the entity created in the EJB method is not rolled back. I use EJB 3.1 with JPA 2.0. The transaction begins in method doTheTransaction():

@Stateless
@LocalBean
@TransactionManagement(TransactionManagementType.BEAN)
public class TaskExecutor {

    @Inject private SomeEntityFacade someEntityEJB;
    @Inject private RandomEJB randomEJB;
    @Resource private UserTransaction ut;

    @Asynchronous
    public Future<String> doTheTransaction () { // we start here

        try {
            SomeEntity someEntity = new SomeEntity();
            someEntityEJB.create(someEntity); // this entity is rolled back

            // call another EJB to create a SomeEntity, this entity is not rolled back
            randomEJB.createSomeEntity();

            // cause error for test
            int i = 5 / 0;

            ut.commit();
        } catch (java.lang.ArithmeticException e) {
            ut.rollback();
        }
    }
    // Omitted exceptions thrown by UserTransaction methods because they give no problems
}

The RandomEJB:

@Stateless
@LocalBean
@TransactionManagement(TransactionManagementType.BEAN)
public class RandomEJB {

    @Inject private SomeEntityFacade someEntityEJB;

    public void createSomeEntity () {
        // same code to create entity as in TaskExecutor:
        SomeEntity someEntity = new SomeEntity();
        someEntityEJB.create(someEntity);
    }
}

To be complete, here is the essential part of SomeEntity:

@Stateless
@LocalBean
public class SomeEntityFacade {

    @PersistenceContext(unitName = "com.mysite.PU")
    private EntityManager em;

    public void create (SomeEntity p_someEntity) {
        em.persist(p_someEntity);
    }

If you are interested, this is my persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="com.mysite.PU" transaction-type="JTA">
    <jta-data-source>jdbc/myDatabase</jta-data-source>
    <properties></properties>
    </persistence-unit>
</persistence>

Why is the entity created in RandomEJB not rolled back, while the entity created directly inside the transaction is?

Maybe this post is related, but I really don't understand the answer given.

Edit: found the error: annotating RandomEJB with @TransactionManagement(TransactionManagementType.BEAN). My understanding is that BMT transactions are not propagated through other BMT annotated methods, instead a new transaction is created. That one can succeed while the initial transaction can fail and rollback. I guess you need to be carefull when using BMT/CMT annotated methods. Can someone confirm this?

1
"My understanding is that BMT transactions are not propagated through other BMT annotated methods, instead a new transaction is created." Nope! It will not be created unless you have explicitly created it by yourself, since it's a BMT. It makes more sense to say that it will run without any transaction.Bhesh Gurung

1 Answers

4
votes

It's just like you said - BMT beans are not sharing the transaction with each other.

This means that you cannot reuse transaction you explicitly started in another BMT. BMT is like "I know what the game is about, I'll manage the transactional stuff myself".

So:

  • BMT -> BMT will not share transaction
  • BMT -> CMT will share transaction (CMT will use the actual transaction - it doesn't care if it's container started or user-started - it's just interested in fact that the transaction exist).