4

Please help me understand something about transactions in EJB 3.1. I'm using GlassFish v3 and have the following situation:

@Stateless
@LocalBean
public class BeanA {

    @Inject BeanB bean; /* which has no TransactionAttribute set */
    @Resource SessionContext context;

    public void run() {
        ...
        for (...) {
            process(someValue);
        }
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void process(String someValue) {

        try {

            SomeEntity entity = bean.getEntity(someValue);
            entity.setSomeProperty("anotherValue");

            ...

        } catch(CustomException e)  {
            this.context.setRollbackOnly();
        }
    }

}

BeanA.run is called from a servlet. I want to treat each iteration as a seperate transaction. I thought using TransactionAttributeType.REQUIRES_NEW would realise this, but I'm getting javax.ejb.EJBTransactionRolledbackException on subsequent iterations on beanB after having called setRollbackOnly. The strange thing is though, when I move everything but run() to a new BeanC and call beanC.process instead it does work. What am I missing? Can anybody shed some light on why this works the way it does?

Edit: Come to think of it: is it because the container doesn't intercept calls to methods within the same EJB? (which would seem reasonable)

Edit 2: Yep, found the answer here: EJB Transactions in local method-calls (I had to know the answer to find it though :))

Community
  • 1
  • 1
Daan de Zwart
  • 81
  • 1
  • 6
  • Please provide an answer for your question and mark it as solved so the question can be properly flagged. Additionally the following resources might be useful for you: http://stackoverflow.com/questions/8079142/transactionattribute-requires-new-in-jpa/8079752#8079752 http://piotrnowicki.com/2011/11/am-i-in-the-same-transaction-am-i-using-the-same-persistencecontext/ http://stackoverflow.com/a/7218283/920607 – Piotr Nowicki Feb 15 '12 at 09:50
  • Thanks for the input. I'll have to wait for another 7 hours before I can answer my own question. – Daan de Zwart Feb 15 '12 at 09:55

2 Answers2

4

Found the answer here: EJB Transactions in local method-calls

In short: the container doesn't intercept local method calls so the setRollbackOnly marked the sole transaction for rollback, explaining the exceptions.

Community
  • 1
  • 1
Daan de Zwart
  • 81
  • 1
  • 6
0

Old question, but for the sake of completeness...

Indeed, annotations like @TransactionAttribute are not processed when it's called directly in a class. This happens because, you are calling it directly, like in a procedural function. It doesn't go through EJB lifecycle (including interceptors).

There is a way to do it though. You need to inject the self class and use that reference:

// Bean A

@Resource SessionContext context;

public void run() {
    ...
    for (...) {
       context.getBusinessObject(BeanA.class).process(someValue);
    }
}

With this way it will create process @TransactionAttribute.
Although it work, I'm not sure if this is a good design.

RicardoS
  • 2,088
  • 1
  • 21
  • 22