Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EJB3 Transaction Propagation

People also ask

What is transactional propagation?

Transaction Propagation indicates if any component or service will or will not participate in transaction and how will it behave if the calling calling component/service already has or does not have a transaction created already.

What is @transactional propagation propagation Requires_new?

When the propagation is REQUIRES_NEW, Spring suspends the current transaction if it exists, and then creates a new one: @Transactional(propagation = Propagation.

What is the default transaction propagation in Spring?

REQUIRED is Default Transaction Propagation. It may or may not run in a transaction. If current transaction exists then it is supported. If none exists then gets executed with out transaction.

What is javax EJB TransactionAttribute?

javax.ejb The TransactionAttribute annotation specifies whether the container is to invoke a business method within a transaction context. The TransactionAttribute annotation can be used for session beans and message driven beans. It can only be specified if container managed transaction demarcation is used.


Another way to do it is actually having both methods on the same bean - and having an @EJB reference to itself! Something like that:

// supposing processObjects defined on MyStatelessRemote1 and process defined on MyStatelessLocal1
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {
    @EJB
    private MyStatelessLocal1 myBean2;

    public void processObjects(List<Object> objs) {
        // this method just processes the data; no need for a transaction
        for(Object obj : objs) {
            this.myBean2.process(obj);
        }
    }


    @TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void process(Object obj) {
        // do some work with obj that must be in the scope of a transaction

        this.mgr.merge(obj);
        // ...
        this.mgr.merge(obj);
        // ...
        this.mgr.flush();
    }
}

This way you actually 'force' the process() method to be accessed via the ejb stack of proxies, therefore taking the @TransactionAttribute in effect - and still keeping only one class. Phew!


Matt, the question you ask is a pretty classic one, I think the self-reference solution by Herval/Pascal is neat. There is a more general solution not mentioned here.

This is a case for EJB "user" transactions. Since you are in a session bean you can get the user transaction from the session context. Here's how your code will look with user transactions:

// supposing processObjects defined on MyStatelessRemote1 and process defined on MyStatelessLocal1
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {

    @Resource
    private SessionContext ctx;

    @EJB
    private MyStatelessLocal1 myBean2;

    public void processObjects(List<Object> objs) {
        // this method just processes the data; no need for a transaction
        for(Object obj : objs) {
            this.myBean2.process(obj);
        }
    }


    public void process(Object obj) {

        UserTransaction tx = ctx.getUserTransaction();

        tx.begin();

        // do some work with obj that must be in the scope of a transaction

        this.mgr.merge(obj);
        // ...
        this.mgr.merge(obj);
        // ...
        this.mgr.flush();

        tx.commit();
    }
}

I think the thing is each bean is wrapped in a proxy that controls the transactional behaviour. When you call from one bean to another, you're going via that bean's proxy and the transaction behaviour can be changed by the proxy.

But when a bean calls a method on itself with a different transaction attribute, the call doesn't go via the proxy, so the behaviour doesn't change.


Matt, for what it's worth I've come to exactly the same conclusion as you.

TransactionAttributeTypes are only taken into consideration when crossing Bean boundaries. When calling methods within the same bean TransactionAttributeTypes have no effect, no matter what Types are put on the methods.

As far as I can see there is nothing in the EJB Persistence Spec that specifies what the behaviour should be under these circumstances.

I've also experienced this in Jboss. I'll also give it a try in Glassfish and let you know the results.