hello,
I have encountered the following distributed transaction problem using the
following configuration (jonas 2.3):
I am using an entity bean that represents a user (bean-managed persistence,
container-managed transactions), with the following deployment descriptor:
<enterprise-bean>
<entity>
<ejb-name>User</ejb-name>
<persistence-type>Bean</persistence-type>
...
</entity>
</enterprise-bean>
...
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>User</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
There is also a UserManager stateless session bean (bean-managed
transactions) that provides a facade to the User bean:
<enterprise-bean>
<session>
<ejb-name>UserManager</ejb-name>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
...
</session>
</enterprise-bean>
The User Bean and the UserManager Bean operate in two separate jonas servers
on two separate machines, with separate JEREMIE registries and local
Transaction Managers (jonas.tm.remote = false). The User Bean is running in
the "Jonas-User" server and the UserManager Bean is running in the
"Jonas-UserManager" server.
The User Bean's ejbStore() method modifies the database programmatically.
There is also a method, changeUser(..), that allows a client of the User
Bean to change the internal values of the Bean. The UserManager Bean calls
User.changeUser() within a bean-managed transaction:
UserManagerBean.java:
public void changeUser(..)
...
try {
javax.transaction.UserTransaction trans =
this.sessionContext.getUserTransaction();
User user = userHome.findByPrimaryKey(userId);
trans.begin();
...
user.changeUser(..);
...
trans.commit;
System.out.println("Transaction commmited");
return;
} catch (Exception e) {
try {
trans.rollback;
} catch (Exception e2) { }
}
}
(Once again, the User is running in the jonas named "JonasUser" and the
UserManager is in the jonas container "JonasUserManager")
Since the <trans-attribute> on the method User.changeUser(..) is "Required",
I expect the User.changeUser() method to use the existing transaction
("trans") explicity declared in the code above. In other words, the call to
trans.commit() should cause the "JonasUser" container to call
User.ejbStore() after User.changeUser() has modified the entity bean's
state. However, I've found that when an exception is thrown in
User.ejbStore() -- say an SQLException due to an errant database
operation -- the demarcated transaction in the UserManager Bean code above
commits without throwing an exception, and at some point after the calling
method UserManagerBean.changeUser() returns, I get the following exception:
JContextEntity.storeIfModified raised EJBException
Rollback during beforeCompletion in SubCoordinator.prepare
Resource replied rollback to prepare
JTM: Cannot rollback resource:
java.rmi.MarshalException: error during marshalling/unmarshalling by stub;
nested exception is:
org.omg.CORBA.OBJECT_NOT_EXIST: minor code: 0 completed: No
org.omg.CORBA.OBJECT_NOT_EXIST: minor code: 0 completed: No
at java.lang.Class.newInstance0(Native Method)
at java.lang.Class.newInstance(Class.java:237)
at
org.objectweb.david.libs.protocols.giop.GIOPProtocol$ReplyHolder.listen(GIOP
Protocol.java:933)
at
org.objectweb.jonas_tm.SubCoordinator_Stub.rollback(SubCoordinator_Stub.java
:176)
at
org.objectweb.jonas_tm.ControlImpl.do_rollback(ControlImpl.java:911)
at org.objectweb.jonas_tm.ControlImpl.commit(ControlImpl.java:425)
at
org.objectweb.jonas_tm.ControlImpl_Skel.send(ControlImpl_Skel.java:51)
at
org.objectweb.david.libs.protocols.giop.GIOPProtocol$ServerSession_Low.send(
GIOPProtocol.java:621)
at
org.objectweb.jonathan.libs.protocols.tcpip.TcpIpProtocol$Session.run(TcpIpP
rotocol.java:396)
at
org.objectweb.jonathan.libs.resources.JScheduler$JJob.run(JScheduler.java:26
5)
It appears that by the time the container calls User.ejbStore(), the
original transaction has been committed and cleaned up. However, if i
modify the UserManager Bean deployment descriptor to use Container-managed
transactions:
<enterprise-bean>
<session>
<ejb-name>UserManager</ejb-name>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
...
</session>
</enterprise-bean>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>UserManager</ejb-name>
<method-name>changeUser</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
and i remove the demarcated transations from UserManagerBean.changeUser(),
things seem to work correctly. That is, if User.ejbStore() throws an
exception, i get the following output:
JContextEntity.storeIfModified raised EJBException
Rollback during beforeCompletion in SubCoordinator.commit_one_phase
Commit local transaction -> rolled back!
Is this difference in bean-managed and container-managed transactions
expected?
Thanks for your help,
Eric
----
To unsubscribe, send email to [EMAIL PROTECTED] and
include in the body of the message "unsubscribe jonas-users".
For general help, send email to [EMAIL PROTECTED] and
include in the body of the message "help".