Reputation: 991
I have following ejb:
for (int i = 1; i <= shopItem.getQuantity(); i++) {
purchase = new Purchase();
purchase.setUser(user);
// a lot of sets
purchase.setPhoneNumber(order.getPhoneNumber());
try {
financeEntityEjb.createPurchase(purchase);
} catch (NotEnoughFundsException e) {
throw new NotEnoughFundsExceptionWithRollback(e); // Making in rollable
}
}
public void createPurchase(Purchase purchase) throws InputValidationException, NotEnoughFundsException {
// a lot of calculations
em.persist(purchase);
em.flush();
/* Closing Order */
purchase.getOrder().setState(Order.State.PURCHASED);
em.merge(purchase.getOrder());
}
My Exception class:
@ApplicationException(rollback = true)
public class NotEnoughFundsExceptionWithRollback extends NotEnoughFundsException {
public NotEnoughFundsExceptionWithRollback() {
}
public NotEnoughFundsExceptionWithRollback(Throwable e) {
super(e);
}
public NotEnoughFundsExceptionWithRollback(String message, Throwable e) {
super(message, e);
}
}
So I have problem that ejb rollbacks all em.persist(purchase); but ignores em.merge(purchase.getOrder());
UPD: Loop is in purchaseEjb. and CreatePurchase method is on financeEjb
Upvotes: 2
Views: 2125
Reputation: 6523
I am assuming the code in the for-loop is not within the, or an, ejb (you are not using this
). In that case most likely the problem is the following
Container managed transaction in EJB last a single method call. Depending on the transactional attributes it ignores, starts or joins a transaction.
The default is required, which means the transaction starts on the call to createPurchase
and ends when the method is finished (tipically a
proxy takes care if this) .
The transaction is rolledback on a RuntimeException
, when an application exception is throws with @ApplicationException(rollback = true)
or when
the set-rollback-only-flag has been set.
In your case most likely none of these happen within the transactional context of createPurchase
. You did not show the code for NotEnoughFundsException
, but
i am assuming it is not annoted with @ApplicationException(rollback = true)
.
Instead you have annotated the NotEnoughFundsExceptionWithRollback
, which is thrown outside of the transactional context by the client calling the EJB.
If you want the whole loop to be an atomic operation, you need to place that in an transactional context (e.g, using an EJB)
Upvotes: 2