
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
