1 Reply Latest reply on Sep 9, 2008 5:59 AM by alin.heyoulin.qq.com

    UserTransaction in Seam

    ylx.ylx24.yahoo.com

      I resolved a problem which has bothered me for months, thought it might be helpful to share my experience.


      My application is web application basing on Seam/Richfaces. The situation is upon a button on browser is clicked, my application needs to perform the following tasks,


      Step 1: persist entity beans into database
      Step 2: call a webservice which accesses the entity beans just persisted
      Step 3: process the data returned by the web service and persist into database


      I used to put all steps in a same method. Because the scope of the default transaction comes with EntityManager is start and end of the method, the data in step 1 is not commited into database until the end of the whole method. So the web service is never not able to get the latest data.


      To resolve this problem, I've to find a way to force data being committed into database in step 1. I assumed the only solution would be UserTransaction, and googled some useful information.


      http://www.mail-archive.com/jboss-user@lists.jboss.org/msg85473.html
      http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4153206#4153206
      http://umberto.tiani-spirit.com/blog/2007/10/bean-managed-transactions-with-ejb3-and.html


      Follow these links, I tried to configure user-transaction-name in components.xml, but apparently setter/getter of userTransactionName is not there in Seam I tried (2.0x and 2.1 beta) even the user guide still says org.jboss.seam.core.init.userTransactionName is a built-in component. Could anyone correct the documentation?


      Also I tried to inject a UserTransaction using @Resource, it didn't work either.


      None of the posts worked for me though I did learn some ideas. After trying all kind of combinations for a couple of days, I finally got everything work. Here is what my final code looks like,



      import javax.ejb.TransactionManagement;
      import javax.ejb.TransactionManagementType;
      import javax.transaction.UserTransaction;
      import org.jboss.seam.annotations.FlushModeType;
      
      @Stateful
      @Scope(CONVERSATION)
      @Name("myAction")
      @javax.ejb.ApplicationException(rollback = true)
      @TransactionManagement(TransactionManagementType.CONTAINER)
      public class MyAction implements Serializable, MyActionLocal {
          ...
          
          @Begin(join = true, flushMode=FlushModeType.MANUAL)
          public String startMyConversation() {
            ...
          }
          
          public void save() {
              UserTransaction utx = null;
              try {
                  utx = (UserTransaction) org.jboss.seam.transaction.Transaction.instance();
                  entityManager.persist(product);
                  entityManager.flush();
                  utx.commit();
              } catch (Exception ex) {
                  ex.printStackTrace();
                  try {
                      utx.rollback();
                  } catch (Exception exx) {
                      exx.printStackTrace();
                  }
                  return;
              }
          }
          
          public void callWebService() {
            //call web service
            //process data returned by web service
          }
      }
      



      The Button in my web page


      <a4j:commandButton id="save_product_button" action="#{myAction.callWebService}" actionListener="#{myAction.save}"/>
      



      It's too much to explain why the code works in such a way. If you have any questions, I could try to follow it.