views:

330

answers:

1

I'm trying to fully understand the JTA demarcation with CMT. The behavior I am experiencing is that only the first @TransactionAttribute of the method is respected on the EJB and subsequent method invocations of the same bean with different @TransactionAttribute annotations are not.

Example:

@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class Foo implements IFoo {

   @EJB
   private IBar barBean;

   // inherits class transaction annotation of NOT_SUPPORTED
   public void doSomething() {
        barBean.doAction();
   }
}

@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class Bar implements IBar {

    public void doAction() {
        Entity entity = bar.find();
        entity.setName("new name");
        // fails with EJBException with TransactionRequiredException as cause
        save(entity);
    }

    public Entity find() {
        // return some persisted entity.
        return em.findById(1);
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public Entity save(entity) {
        em.persist(em.merge(entity));
        em.flush();
    }
}

The behavior I'm seeing is that Bar.save() throws a TransactionRequiredException. So this tells me that the REQUIRED annotation set on the save() does not create a transaction. REQUIRES_NEW also does not work. If I move the save() to another EJB, it works as expected.

Does this mean that only the first TransactionAttribute annotation is respected regardless of subsequent method invocations on the same with with different annotation values? Is this a bug or the expected behavior? I cannot seem to find any documentation that concretely explains this. I appreciate any insight on this.

My stack: EJB 3.0, Toplink Essentials, GF V2UR2

+1  A: 

My reading of the EJB 3 spec is that a transaction specification on an individual method overrides that of the EJB as a whole. Therefore your expectations that REQUIRED should apply does seem reasonable, but ...

this is only if you are using the bean method as an EJB. When you make a direct call from one business method doAction() to another, save(), you are not using an EJB reference and hence this is just plain old Java - the container is not involved, so no opportunity for the container to intervene.

If you apply the required option to you doAction() method I would expect this to work.

This theory is consistent with your findings of the effect of refactoring to another EJB.

djna
djna - Thank you for your response. Your explanation makes sense. I was able to touch base with another colleague and he also agreed with your statement. I appreciate your time.
Troy