Reputation: 4868
My question is about the need to define a UserTransaction in a JSF Bean if multiple EJB methods are called. This is my general scenario:
//jsf bean...
@EJB ejb1;
...
public String process(businessobject) {
ejb1.op1(businessobject);
ejb1.op2(businessobject);
....
}
both ejbs methods manipulate the same complex jpa entity bean object (including flush and detachment). I recognized in the database that some of the @oneToMany relations form my entity bean where duplicated when ejb1.op1() is called before ejb1.op2(). I understand that both ejbs start a new transaction. And to me anything looks ok so far. But the JSF code only works correctly if I add a UserTransaction to my jsf method like this:
//jsf bean...
@Resource UserTransaction tx;
@EJB ejb1;
...
public String process(businessobject) {
try {
tx.begin();
ejb1.op1(businessobject);
ejb1.op2(businessobject);
finaly {
tx.commit();
}....
}
I did not expect that it is necessary to encapsulate both ejb calls into one usertransaction. Why is this necessary?
Upvotes: 1
Views: 1178
Reputation: 1108567
Each @Stateless
EJB method call from a client (in your case, the JSF managed bean), counts by default indeed as one full transaction. This lasts as long as until the EJB method call returns, including nested EJB method calls.
Just merge them both into a single EJB method call if it must represent a single transaction.
public String process(Entity entity) {
ejb1.op1op2(entity);
// ...
}
with
public void op1op2(Entity entity) {
op1(entity);
op2(entity);
}
No need to fiddle with UserTransaction
in the client. In a well designed JSF based client application you should never have the need for it, either.
As to the why of transactions, it locks the DB in case you're performing a business action on the entity. Your mistake was that you performed two apparently dependent business actions completely separately. This may in a high concurrent system indeed cause a corrupted DB state as you encountered yourself.
As to the why of transactions, this may be a good read: When is it necessary or convenient to use Spring or EJB3 or all of them together?
Upvotes: 2
Reputation: 134
Is a user transaction needed for you? Generally, container managed transactions are good enough and serve the purpose.
Even if you need to have user managed transactions, it is not a good to have transaction management logic mingled with JSF logic.
For using container managed transactions, you should look at using the @TransactionAttribute on the EJBs.
If all the methods in your ejb need to have the same level of transaction support, you could have the annotation at the class level. Else you could also use the @TransactionAttribute annotation against each individual ejb method.
Upvotes: 1