1 2 Previous Next 18 Replies Latest reply on Aug 12, 2009 10:44 AM by kapitanpetko

    New Seam example featuring distributed transactions

    asookazian

      I'm considering writing a new Seam 2.2.x app that runs on JBoss 5.1.x featuring one or two use cases of how to design/implement distributed tx's using XA resources with MySQL, EJB 3.0 and JTA.


      1) Tx manager manages 2PC for one resource manager (MySQL db1) and another resource manager (MySQL db2)


      2) Tx manager manages 2PC for one resource manager (MySQL db1) and another resource manager (JMS message)


      I have not seen any examples in the Seam distro thus far showcasing XA resources with distributed tx's so if there's enough demand, I'll give it a shot.

        • 1. Re: New Seam example featuring distributed transactions
          mdesignz

          That would be great to see.

          • 2. Re: New Seam example featuring distributed transactions
            asookazian

            I've made some significant progress.  The distributed tx works for MySQL db1 and MySQL db2.  I am now trying to add in a third resource to the distrubted tx, which is publishing a JMS topic and subsequent MDB onMessage() execution.


            Basically I have modded the booking example (for now) and added in some code (specifically the LoggerBean MDB and configs) from the remoting\chatroom distro project.


            The problem I am having is quite strange.


            Caused by: javax.jms.MessageFormatException: ClassNotFoundException: No ClassLoaders found for: org.jboss.seam.example.booking.ChatroomEvent
                 at org.jboss.mq.SpyObjectMessage.getObject(SpyObjectMessage.java:154)
                 at org.jboss.seam.example.remoting.chatroom.LoggerBean.onMessage(LoggerBean.java:28)
                 ... 41 more



            which is triggered by the ChatroomEvent reference in this MDB:


            @MessageDriven(activationConfig={
                  @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Topic"),
                  @ActivationConfigProperty(propertyName="destination", propertyValue="topic/chatroomTopic")
               })
            @Name("logger")
            public class LoggerBean implements MessageListener
            {
               
               @Logger Log log;
            
               public void onMessage(Message msg)
               {
                  try
                  {
                     ChatroomEvent event = (ChatroomEvent) ( (ObjectMessage) msg ).getObject();
                     log.info( "#0: #1", event.getUser(), event.getData()==null ? event.getAction() : event.getData() );
                  }
                  catch (JMSException jmse)
                  {
                     throw new RuntimeException(jmse);
                  }
               }
            
            }



            The class is in the exploded JAR that is deployed to JBoss AS 4.2.3 here:


            server\default\deploy\jboss-seam-booking.ear\jboss-seam-booking.jar\org\jboss\seam\example\booking


            There is a jboss-seam-chatroom-service.xml in the server\default\deploy directory which seems to be a MBean config for the chatroom project.  I'm not even sure if it's required or not.  The chatroom project also has a treecache.xml file which I'm not sure exactly what it's being used for in that project.


            btw, I am using AS 4.2.3 and Seam 2.1.2 for now as AS 5.1 is not supported by JBoss Tools in JBDS 2.0.0.GA AFAIK in the JBoss server creation and that makes debugging impossible via the IDE, I tried using AS 5.0 setup for AS 5.1 and it doesn't like that (incompatible)...

            • 3. Re: New Seam example featuring distributed transactions
              kapitanpetko

              Arbi Sookazian wrote on Aug 07, 2009 01:33:


              Caused by: javax.jms.MessageFormatException: ClassNotFoundException: No ClassLoaders found for: org.jboss.seam.example.booking.ChatroomEvent
                   at org.jboss.mq.SpyObjectMessage.getObject(SpyObjectMessage.java:154)
                   at org.jboss.seam.example.remoting.chatroom.LoggerBean.onMessage(LoggerBean.java:28)
                   ... 41 more





              Not sure what causes this, but maybe it has something to do with the ChatroomEvent having a @Name annotation. Try something simpler for starters, like a TextMessage.



              There is a jboss-seam-chatroom-service.xml in the server\default\deploy directory which seems to be a MBean config for the chatroom project.  I'm not even sure if it's required or not.


              It defines the JMS topic, so it is required.



              ... JBoss server creation and that makes debugging impossible via the IDE,...


              You can always attach remotely and debug in Eclipse. There should be something like this in your JBoss startup script, uncomment and
              attach from Eclipse once the server is running (that's for Windows):


              rem set JAVA_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y %JAVA_OPTS%
              



              HTH


              • 4. Re: New Seam example featuring distributed transactions
                asookazian

                Thanks for the helpful tips.


                The ClassNotFoundException has mysteriously disappeared and it apparently has nothing to do with the @Name annotation on ChatroomEvent class.  I'm not sure exactly what I changed in the code, if anything at all, but I do recall that I restarted JBoss and did 'ant clean unexplode explode' and reproduced the exception.  Very strange.


                Anyways, I just tried using the <local-tx-datasource> in *-ds.xml with this code in the backing bean (SFSB with conversation-scope, remember that default tx attribute type is REQUIRED):


                @Begin(join=true, flushMode=FlushModeType.MANUAL)
                     public void startup(){
                          log.info("in startup()");
                          List<Hotel> list = em.createQuery("from Hotel").getResultList();
                          log.info("list.size() = "+list.size());
                          
                          Hotel hotel = null;
                          
                          if (list != null && list.size() > 0) {
                               hotel = list.get(0);
                               hotel.setAddress("arbi's house");
                          }
                          
                          em.flush();
                          
                          connect();
                          
                     }
                
                        public void connect() {
                            publish( new ChatroomEvent("connect", "arbime") );
                        }
                
                      private void publish(ChatroomEvent message) {
                      try {
                         topicPublisher.publish( topicSession.createObjectMessage(message) );
                      } 
                      catch (Exception ex) {
                         throw new RuntimeException(ex);
                      } 
                   }
                     



                And it works fine.


                09:25:39,341 INFO  [TestStartConversation] in startup()
                09:25:39,356 INFO  [STDOUT] Hibernate: 
                    select
                        hotel0_.id as id61_,
                        hotel0_.address as address61_,
                        hotel0_.name as name61_,
                        hotel0_.state as state61_,
                        hotel0_.country as country61_,
                        hotel0_.price as price61_,
                        hotel0_.city as city61_,
                        hotel0_.zip as zip61_ 
                    from
                        Hotel hotel0_
                09:25:39,387 INFO  [TestStartConversation] list.size() = 20
                09:25:41,731 INFO  [LoggerBean] arbime: connect



                I was actually expecting this to fail like it failed when I used <local-tx-datasource> for both datasources and this code:


                @Begin(join=true, flushMode=FlushModeType.MANUAL)
                     public void startup(){
                          log.info("in startup()");
                          List<Hotel> list = em.createQuery("from Hotel").getResultList();
                          log.info("list.size() = "+list.size());
                          
                          Hotel hotel = null;
                          
                          if (list != null && list.size() > 0) {
                               hotel = list.get(0);
                               hotel.setAddress("arbi's house");
                          }
                          
                          em.flush();
                          
                          List<User> list2 = em2.createQuery("from User").getResultList();
                          log.info("list2.size() = "+list2.size());
                          
                          User user = null;
                          
                          if (list2 != null && list2.size() > 0) {
                               user = list2.get(0);               
                               user.setPassword("arbi1");
                          }
                          
                          em2.flush();
                     }



                Stack trace:


                This is the partial stack trace you'll see if you use local-tx-datasource instead of xa-datasource in *-ds.xml:
                               
                               Caused by: org.jboss.util.NestedSQLException: Could not enlist in transaction on entering meta-aware object!; - nested throwable: (javax.transaction.SystemException: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: a2e0519:e8a:4a7b4398:b6 status: ActionStatus.ABORT_ONLY >); - nested throwable: (org.jboss.resource.JBossResourceException: Could not enlist in transaction on entering meta-aware object!; - nested throwable: (javax.transaction.SystemException: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: a2e0519:e8a:4a7b4398:b6 status: ActionStatus.ABORT_ONLY >))
                               at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:95)
                               at org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider.getConnection(InjectedDataSourceConnectionProvider.java:47)
                               at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:423)
                               ... 141 more
                          Caused by: org.jboss.resource.JBossResourceException: Could not enlist in transaction on entering meta-aware object!; - nested throwable: (javax.transaction.SystemException: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: a2e0519:e8a:4a7b4398:b6 status: ActionStatus.ABORT_ONLY >)
                               at org.jboss.resource.connectionmanager.TxConnectionManager.managedConnectionReconnected(TxConnectionManager.java:358)
                               at org.jboss.resource.connectionmanager.BaseConnectionManager2.reconnectManagedConnection(BaseConnectionManager2.java:524)
                               at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:405)
                               at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:849)
                               at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89)
                               ... 143 more
                          Caused by: javax.transaction.SystemException: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: a2e0519:e8a:4a7b4398:b6 status: ActionStatus.ABORT_ONLY >
                               at org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener$TransactionSynchronization.checkEnlisted(TxConnectionManager.java:759)
                               at org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener.enlist(TxConnectionManager.java:592)
                               at org.jboss.resource.connectionmanager.TxConnectionManager.managedConnectionReconnected(TxConnectionManager.java:352)
                               ... 147 more



                So what I'm trying to understand now is the 2nd scenario described in my original post: 1 - db and 1 - JMS session.  Does that not qualify as two resource managers in a distributed tx thus requiring XA/2PC?  According to my test, no...


                This is legal as well with local-tx-datasource:


                @Begin(join=true, flushMode=FlushModeType.MANUAL)
                     public void startup(){
                          log.info("in startup()");
                          List<Hotel> list = em.createQuery("from Hotel").getResultList();
                          log.info("list.size() = "+list.size());
                          
                          Hotel hotel = null;
                          
                          if (list != null && list.size() > 0) {
                               hotel = list.get(0);
                               hotel.setAddress("arbi's house");
                          }
                          
                          em.flush();
                                              
                          try {
                               topicPublisher.publish( topicSession.createObjectMessage(new ChatroomEvent("connect", "arbime")) );
                          }
                          
                          catch (Exception ex) {
                              throw new RuntimeException(ex);
                         } 
                     }



                I'm also wondering how distributed tx's are handled or supported by @Transactional with Seam JavaBean components...  If the underlying tx mgr is JTA, then it seems like it should work.  Perhaps I should do an example of that scenario as well...

                • 5. Re: New Seam example featuring distributed transactions
                  asookazian

                  I created an alternative JavaBean backing component with @Transactional on the startup() method and it does not work with <local-tx-datasource> and does work with <xa-datasource> in *-ds.xml.  So that's good (works as expected with operations on both EntityManager instances).

                  • 6. Re: New Seam example featuring distributed transactions
                    kapitanpetko

                    Arbi Sookazian wrote on Aug 07, 2009 18:36:


                    So what I'm trying to understand now is the 2nd scenario described in my original post: 1 - db and 1 - JMS session.  Does that not qualify as two resource managers in a distributed tx thus requiring XA/2PC?  According to my test, no...



                    I don't have time to look into this right now, but here is guess: since the Seam-managed JMS Session is created before the transaction
                    starts (because injection happens before the actual method call), it is not joining the transaction. Try it without using the Seam JMS components (create your Session manually), you should get a different result.


                    HTH

                    • 7. Re: New Seam example featuring distributed transactions
                      asookazian

                      That makes sense.  I'll try that out Nikolay.  thx.

                      • 8. Re: New Seam example featuring distributed transactions
                        asookazian

                        So here is the refactored version w/o the JMS interface injections (excuse the poor error handling for now):


                        @Name("startConversation")
                        @AutoCreate
                        @Install(true)
                        @Stateful
                        public class TestStartConversation implements TestStartConversationLocal{
                             
                             @Logger 
                             private Log log;
                             
                             @In
                             private EntityManager em;
                             
                             @In
                             private EntityManager em2;
                             
                             //@In(create=true)
                             private transient TopicPublisher topicPublisher;   
                             
                             //@In(create=true)
                             private transient TopicSession topicSession;
                             
                             private transient TopicConnection conn;
                             
                             private transient Topic topic;
                                  
                             @Begin(join=true, flushMode=FlushModeType.MANUAL)
                             public void startup(){
                                  log.info("in startup()");
                                  List<Hotel> list = em.createQuery("from Hotel").getResultList();
                                  log.info("list.size() = "+list.size());
                                  
                                  Hotel hotel = null;
                                  
                                  if (list != null && list.size() > 0) {
                                       hotel = list.get(0);
                                       hotel.setAddress("arbi's house");
                                  }
                                  
                                  em.flush();
                                  
                                  /*List<User> list2 = em2.createQuery("from User").getResultList();
                                  log.info("list2.size() = "+list2.size());
                                  
                                  User user = null;
                                  
                                  if (list2 != null && list2.size() > 0) {
                                       user = list2.get(0);
                                       //user.setName("arbiname");
                                       user.setPassword("arbi1");
                                  }
                                  
                                  em2.flush();*/
                                  
                                  //connect();
                                  
                                  try{
                                      InitialContext iniCtx = new InitialContext();
                                      Object tmp = iniCtx.lookup("ConnectionFactory");
                                      TopicConnectionFactory tcf = (TopicConnectionFactory) tmp;
                                      conn = tcf.createTopicConnection();
                                      topic = (Topic) iniCtx.lookup("topic/chatroomTopic");
                                      topicSession = conn.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
                                      topicPublisher = topicSession.createPublisher(topic);
                                      topicPublisher.publish( topicSession.createObjectMessage(new ChatroomEvent("connect", "arbime")) );
                                  }
                                  catch(Exception e){
                                       //noop
                                  }
                                  
                             }
                             
                             private void connect(){           
                                  publish( new ChatroomEvent("connect", "arbime") );
                             }
                             
                             private void publish(ChatroomEvent message) {
                                  try {
                                       topicPublisher.publish( topicSession.createObjectMessage(message) );
                                  } 
                                  catch (Exception ex) {
                                       throw new RuntimeException(ex);
                                  } 
                            }
                             
                             @Destroy
                             @Remove
                             public void destroy(){
                                  log.info("in destroy()");
                             }
                             
                             
                        }



                        LoggerBean MDB component (unchanged):


                        @MessageDriven(activationConfig={
                              @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Topic"),
                              @ActivationConfigProperty(propertyName="destination", propertyValue="topic/chatroomTopic")
                           })
                        @Name("logger")
                        public class LoggerBean implements MessageListener
                        {
                           
                           @Logger Log log;
                        
                           public void onMessage(Message msg)
                           {
                              try
                              {         
                                  ChatroomEvent event = (ChatroomEvent) ( (ObjectMessage) msg ).getObject();
                                 log.info( "#0: #1", event.getUser(), event.getData()==null ? event.getAction() : event.getData() );
                              }
                              catch (JMSException jmse)
                              {
                                 throw new RuntimeException(jmse);
                              }
                           }
                        
                        }



                        When I used local-tx-datasources, it works fine.  This is unexpected.  So in terms of distributed tx mgmt, there is no change/effect (i.e. the tx mgr is not seeing two resource managers in this method apparently).


                        output:


                        13:53:27,899 INFO  [TestStartConversation] in startup()
                        13:53:27,899 INFO  [STDOUT] Hibernate: 
                            select
                                hotel0_.id as id85_,
                                hotel0_.address as address85_,
                                hotel0_.name as name85_,
                                hotel0_.state as state85_,
                                hotel0_.country as country85_,
                                hotel0_.price as price85_,
                                hotel0_.city as city85_,
                                hotel0_.zip as zip85_ 
                            from
                                Hotel hotel0_
                        13:53:27,915 INFO  [TestStartConversation] list.size() = 20
                        13:53:34,915 INFO  [LoggerBean] arbime: connect



                        There was no update in this test run b/c the value did not change (it's hard-coded to arbi's house), but that is irrelevant to the distributed tx semantics/problem.  Even if there are no updates or inserts, for example, reading from two different db's in a REQUIRED tx type/method - the invisible default - is still a distributed tx...


                        So anybody know what's going on here and why this is apparently still not a distributed tx according to JBoss/JTA (tx mgr) even without the injections???  Perhaps I should post this now on the JBoss transaction/EJB3 forum.  thx.

                        • 9. Re: New Seam example featuring distributed transactions
                          asookazian
                          • 10. Re: New Seam example featuring distributed transactions
                            kapitanpetko

                            Oh, I see now. In order to enlist in a distributed transaction, you have to use the XA-aware interfaces, specifically ConnectionFactory.
                            So if you change to something like this, it should work (the JNDI path may be different, check your JMX console to be sure). As far as the Seam JMS components are concerned, if you configure them to use the XAConnectionFactory should work as well.


                            Object tmp = iniCtx.lookup("java:/XAConnectionFactory");
                            TopicConnectionFactory tcf = (TopicConnectionFactory) tmp;
                            
                            

                            • 11. Re: New Seam example featuring distributed transactions
                              asookazian

                              Ok, that's good to know but still does not explain why it's working with local-tx-datasource.  I was expecting a tx enlistment exception if it's really distributed tx.


                              How would I know that the transaction manager has detected (enlisted?) a 2nd resource manager?  Perhaps I need to use BMT or similar so I can access this information dynamically in the method at runtime...


                              If the tx mgr enlists a 2nd resource mgr and you're not using xa-datasource, then there should be an exception thrown I'd imagine.


                              This is not the case, it works fine with db and jms and local-tx-datasource.  Seems strange to me....

                              • 12. Re: New Seam example featuring distributed transactions
                                kapitanpetko

                                Arbi Sookazian wrote on Aug 11, 2009 06:50:


                                Ok, that's good to know but still does not explain why it's working with local-tx-datasource.  I was expecting a tx enlistment exception if it's really distributed tx.


                                You are probably getting two separate transactions, not a distributed one.



                                How would I know that the transaction manager has detected (enlisted?) a 2nd resource manager?  Perhaps I need to use BMT or similar so I can access this information dynamically in the method at runtime...


                                You can turn on JBoss transaction logging and I imagine there would be some info about this in the logs. (com.arjuna IIRC)
                                Or you can throw an exception and see if that rollbacks both the JMS message and your DB update.



                                If the tx mgr enlists a 2nd resource mgr and you're not using xa-datasource, then there should be an exception thrown I'd imagine.

                                This is not the case, it works fine with db and jms and local-tx-datasource.  Seems strange to me....


                                You might get better answers at the AS forum (do post back here, if you do), but, as I said it is probably treating them as separate transactions. Or the message send is not enlisted in a transaction at all (so you get just one regular DB transaction).


                                • 13. Re: New Seam example featuring distributed transactions
                                  asookazian

                                  Ok, I setup a new logger for org.jboss.seam.transaction package and here are the results after executing my test case:


                                  -- one db and one jms session and local-tx-datasource


                                  2009-08-11 09:55:17,681 DEBUG [org.jboss.seam.transaction.UTTransaction] beginning JTA transaction
                                  2009-08-11 09:55:17,775 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:55:17,947 DEBUG [org.jboss.seam.transaction.UTTransaction] committing JTA transaction
                                  2009-08-11 09:55:17,947 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:55:17,947 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:55:17,947 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:55:17,947 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:55:17,947 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:55:18,041 DEBUG [org.jboss.seam.transaction.UTTransaction] beginning JTA transaction
                                  2009-08-11 09:55:18,041 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:55:20,619 DEBUG [org.jboss.seam.transaction.UTTransaction] committing JTA transaction
                                  2009-08-11 09:55:20,619 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:55:20,619 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:55:20,619 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:55:20,619 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:55:20,619 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion



                                  -- two db and local-tx-datasource


                                  2009-08-11 09:57:30,183 DEBUG [org.jboss.seam.transaction.UTTransaction] beginning JTA transaction
                                  2009-08-11 09:57:30,198 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:30,323 DEBUG [org.jboss.seam.transaction.UTTransaction] committing JTA transaction
                                  2009-08-11 09:57:30,323 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:30,323 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:57:30,323 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:57:30,323 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:30,323 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:30,386 DEBUG [org.jboss.seam.transaction.UTTransaction] beginning JTA transaction
                                  2009-08-11 09:57:30,386 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:32,574 DEBUG [org.jboss.seam.transaction.UTTransaction] committing JTA transaction
                                  2009-08-11 09:57:32,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:32,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:57:32,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:57:32,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:32,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:33,870 DEBUG [org.jboss.seam.transaction.UTTransaction] beginning JTA transaction
                                  2009-08-11 09:57:33,870 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:34,199 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:34,199 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:35,402 DEBUG [org.jboss.seam.transaction.UTTransaction] rolling back JTA transaction
                                  2009-08-11 09:57:35,433 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:35,433 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:35,433 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:35,574 DEBUG [org.jboss.seam.transaction.UTTransaction] beginning JTA transaction
                                  2009-08-11 09:57:35,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:35,574 DEBUG [org.jboss.seam.transaction.UTTransaction] committing JTA transaction
                                  2009-08-11 09:57:35,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:35,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:57:35,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:57:35,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:35,574 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:37,089 DEBUG [org.jboss.seam.transaction.UTTransaction] beginning JTA transaction
                                  2009-08-11 09:57:37,089 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:37,089 DEBUG [org.jboss.seam.transaction.UTTransaction] committing JTA transaction
                                  2009-08-11 09:57:37,089 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 09:57:37,089 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:57:37,089 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] beforeCompletion
                                  2009-08-11 09:57:37,089 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 09:57:37,089 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion



                                  Note that the rollback only occurs in the 2nd case for two db's.  But in both cases there are two commits which may have to do with the global tx's that are part of Seam's transactional architecture.


                                  To prove this, for the 2nd case above, I added transaction-management-enabled="false" to the components.xml to turn off global tx's:


                                  <core:init jndi-pattern="@jndiPattern@" debug="true" distributable="@distributable@" transaction-management-enabled="false"/>



                                  and here is the result with 2 db's and local-tx-datasource:


                                  2009-08-11 10:18:31,543 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 10:18:31,543 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterBegin
                                  2009-08-11 10:18:32,184 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  2009-08-11 10:18:32,184 DEBUG [org.jboss.seam.transaction.EjbSynchronizations] afterCompletion
                                  



                                  So Seam has the facility to inject the UserTransaction interface using @In.  The org.jboss.seam.transaction.Transaction class uses the manager component pattern via @Unwrap to return the UserTransaction instance.


                                  So I started messing around with a new method in my Seam component and it looks like the API for the UserTransaction interface only provides one enlist() method which requires an ENtityManager as a param.  In the case of enlisting a JMS session for a sub/pub scenario like I'm doing, I'm not sure how to enlist that resource or even if it's possible to do so via the API.


                                  So now I'm wondering how this whole experiment would work/behave if I bypassed Seam completely (i.e. remove the @Name so it will no longer be managed by the Seam container as a Seam component) and how the JTA/arjuna tx mgr would handle this.


                                  I would have to have a backing bean do a JNDI lookup (or use @EJB to inject the local interface into the backing bean) to see what will happen with the startup() method in a non-Seam component SLSB, for example.


                                  This is getting more complicated and time-consuming than I originally estimated...

                                  • 14. Re: New Seam example featuring distributed transactions
                                    asookazian

                                    I tried the above idea by writing a SLSB that is injected into the SFSB (backing bean for the JSF page) via @EJB.  I got the exact same results as before.  Only difference is I did not use a @Name annotation for the SLSB and I used @PersistenceContext to inject the EntityManager interfaces.


                                    So I referred to JSR220-core and there is some very good info there in Chapter 13 - Support for Transactions.


                                    There are some complicated scenarios discussed in that chapter regarding distributed tx's.


                                    Specifically, section 13.2.2 states the following:



                                    In the following figure, a client invokes the enterprise bean X. Bean X sends a message to a JMS queue
                                    A and updates data in a database B using connections that the Deployer configured to connect with a
                                    JMS provider and a database. Then X calls another enterprise bean, Y. Bean Y updates data in database
                                    C. The EJB server ensures that the operations on A, B, and C are either all committed, or all rolled
                                    back.

                                    and then:



                                    The application programmer does not have to do anything to ensure transactional semantics. The enterprise
                                    beans X and Y perform the message send and database updates using the standard JMS and
                                    JDBC™ APIs. Behind the scenes, the EJB server enlists the session on the connection to the JMS provider
                                    and the database connections as part of the transaction.
                                    When the transaction commits, the EJB
                                    server and the messaging and database systems perform a two-phase commit protocol to ensure atomic
                                    updates across all the three resources.

                                    The ridiculously absurd thing is that xa-datasource is not mentioned in the entire spec.  And of course, there are no code examples.  I thought Sun owned MySQL (or is it Oracle now)?  How lame...

                                    1 2 Previous Next