A SFSB as part of transaction
bemtaill Nov 15, 2011 9:06 AMHi All,
I observe an interesting behavior. I hava a SFSB with CMT which implements SessionSynchronization:
{code}
@Stateful(name = "AImpl")
@TransactionManagement(TransactionManagementType.CONTAINER)
public class AImpl implements A, SessionSynchronization {
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void foo1() {
System.out.println("from foo1");
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void foo2() {
System.out.println("from foo2");
}
@Override
public void afterBegin() throws EJBException, RemoteException {
System.out.println("afterBegin() invoked");
}
@Override
public void afterCompletion(boolean arg0) throws EJBException, RemoteException {
System.out.println("afterCompletion("+arg0+") invoked");
}
@Override
public void beforeCompletion() throws EJBException, RemoteException {
System.out.println("beforeCompletion() invoked");
}
}
{code}
I also have a servlet which does exectly this:
{code}
try {
Context ic = new InitialContext();
UserTransaction userTransaction = (UserTransaction) ic.lookup("java:comp/UserTransaction");
userTransaction.begin();
A a = (A)ic.lookup("java:global/holiday-ear/holiday-ejb/AImpl!com.holiday.test.A");
a.foo1();
a.foo2();
userTransaction.commit();
} catch (Exception e) {
e.printStackTrace();
}
{code}
Now, when I call a.foo1() the bean becomes a part of the transaction and calling a.foo2() should throw an exception because of the new transaction being started by REQUIRES_NEW annotation. In other words I'm expecting to see this behaivior
Enterprise JavaBeans 3.1
{quote}
Once a stateful session bean is a part of a transaction—whether it implements Session
Synchronization or not—it cannot be accessed by any other transactional context. This
is true regardless of whether the client tries to access the EJB with a different context
or the EJB’s own method creates a new context. If, for example, a method with a transaction
attribute of RequiresNew is invoked, the new transactional context causes an error
to be thrown. Since the NotSupported and Never attributes specify a different transactional
context (no context), invoking a method with these attributes also causes an
error.
{quote}
But instead I see that when the a.foo2() is invoked the client transaction (the one started in the servlet) gets susspended and no exception is thrown!
From the logs I can see that the bean "joins" transaction right before a.foo1() and "leaves" it when client transaction in commited (userTransaction.commit() in the servlet):
{quote}
14:20:42,656 INFO [] afterBegin() invoked
14:20:45,368 INFO [] from foo1
14:20:46,106 INFO [] from foo2
14:20:46,713 INFO [] from foo2
14:20:46,714 INFO [] beforeCompletion() invoked
14:20:46,714 INFO [] afterCompletion(true) invoked
{quote}
Could anyone clerify why the exception is not thrown?
Thanks,
Valery
PS: and it seems that I can actually remove the bean (calling @Remove method) while the bean is still in the transaction!
PSS: in fact I can't remove it. The container doesn't throw the exception on the @Remove method invocation (and the method gets executed without problems), but the bean is there till the end of transaction.