8 Replies Latest reply on Nov 30, 2004 2:42 AM by Tomer ben david

    how to roll back ejbCreate operations?

    Jason Long Novice

      I am using JBoss 4.0 with MySQL. I have an operation that does the following in a loop over a collection:

      PipeLocal pipe2 = PipeUtil.getLocalHome().create(pv2);
      pipe2.setPipePurchaseOrder(getPipePurchaseOrder());

      If one of the operations fails in the loop I need everything to roll back. All relevant information is rolled back and I am left with Pipe entries that are not attached to a PipePurchaseOrder. I read that the ejbCreate method runs in an undefined transation context. There has to be a simple solution to this problem. Is this behavior configured in JBoss or my code?

        • 1. Re: how to roll back ejbCreate operations?
          Jason Long Novice

          After more research I found that using an XADatasource wrapper would help. Is this the only solutoin to my problem? Does anyone have an example of how to set up this configuration>

          • 2. Re: how to roll back ejbCreate operations?
            Jason Long Novice

            I have been trying all night to configure the XADataSource. Here is a sample of mysql-ds.xml

            <mbean code="org.jboss.jdbc.XADataSourceLoader" name="DefaultDomain:service=XADataSource,name=explorecoDS">
             <attribute name="PoolName">explorecoDS</attribute>
             <attribute name="DataSourceClass">org.jboss.pool.jdbc.xa.wrapper.XADataSourceImpl</attribute>
             <attribute name="URL">jdbc:mysql://localhost:3306/exploreco</attribute>
             <attribute name="JDBCUser">xxx</attribute>
             <attribute name="Password">xxx</attribute>
            </mbean>
            


            I get the following error:
            org.jboss.deployment.DeploymentException: No ClassLoaders found for: org.jboss.jdbc.XADataSourceLoader;

            I searched everywhere in the JBoss 4.0 source for this class. I am going to sleep now. Hopefully someone will post a solution before I wake up. Even a code workaround for my ejbCreate roll back problem would fantastic.

            • 3. Re: how to roll back ejbCreate operations?
              Scott Stark Master

              Last time I checked, the mysql jdbc driver does not have an xa datasource so it cannot be deployed as one.

              An entity bean ejbCreate has a well defined tx as documented in the ejb 2.1 spec:


              An ejbCreate<METHOD> method executes in the transaction context determined by the transaction attribute of the matching create<METHOD> method. The database insert operations are performed by the container within the same transaction context after the Bean Provider?s
              ejbCreate<METHOD> method completes.



              • 4. Re: how to roll back ejbCreate operations?
                Jason Long Novice

                I read somewhere that JBoss can wrap the driver to support XA transactions. Maybe I am going in the wrong direction. I am using a session bean to access all my entity bean methods. I have a single method that has Required as transaction. My coded works fine, but the fact that I am creating entity beans from inside another entity bean keeps this from being rolled back. Basically I take and entity and split it into two with some properties changed. All other records are rolled back, but I am left with orphaned entitys with that have null fk values. I believe that is because everything is being rolled back except the create statement. This seems like a common problem does anyone have any advice?

                • 5. Re: how to roll back ejbCreate operations?
                  Jason Long Novice

                  I apologize for posting to this multiple times, but I still have not found a relevant answer. I have an action method in ReleaseEJB and a split method in PipeEJB. See code below. I release can contain any number of pipe, but when one fails all should roll back. In fact all changes roll back except those applied when a new pipe is created in split. All other updates are rolled back including the fk attached with:

                  pipe2.setPipePurchaseOrder(getPipePurchaseOrder());
                  


                  I am left with orphanded pipe that is not attached to any PO and is also a new pipe that is invalid because the update to the original unit of pipe were correctly rolled back to there initial state. I have tried changing to transaction Required, Manadatory, ect, but with no success.

                  My real question is why does JBoss see the creation of this entity as being a separate transaction that succeed and how do I fix my code to work and one transactional unit?


                  Method to release multiple pipes:
                  /**
                   * @ejb.interface-method
                   */
                  public void action(ReleaseValue rv, Collection col, int uid) throws EJBException {
                  
                   Iterator it = col.iterator();
                   try {
                   while(it.hasNext()) {
                   PipeValue pv = (PipeValue) it.next();
                   PipeLocal pipe1 = PipeUtil.getLocalHome().findByPrimaryKey(pv.getId());
                   PipeLocal pipe2 = pipe1.split(pv.getNumFeet(), pv.getNumJoints());
                   }
                   } catch(Exception e) {
                   throw new EJBException(e);
                   }
                  
                  }
                  


                  Method to split pipe:
                   /**
                   * @ejb.interface-method
                   * @ejb.transaction
                   * type="Mandatory"
                   */
                   public PipeLocal split(double amount, int numJts) throws CreateException, Exception {
                   if(amount > 0 && numJts > 0) {
                   PipeValue pv = this.getPipeValue();
                   PipeValue pv2 = null;
                   double feetInstock = pv.getNumFeet();
                   int jstInstock = pv.getNumJoints();
                   double roundOff = 0.01;
                   boolean total = ((amount - feetInstock) < roundOff && numJts == jstInstock);
                   boolean partial = (amount < feetInstock && numJts < jstInstock);
                   boolean invalid = (amount > feetInstock || numJts > jstInstock);
                   if(total) {
                   pv.setPipeSource(getId());
                   setPipeValue(pv);
                   return null;
                   } else if(partial) {
                   pv.setDeltaFeet( -amount);
                   pv.setDeltaJoints( -numJts);
                   pv.setNumFeet(feetInstock - amount);
                   pv.setNumJoints(jstInstock - numJts);
                   setPipeValue(pv);
                   pv2 = new PipeValue(pv);
                   pv2.setNumFeet(amount);
                   pv2.setNumJoints(numJts);
                   pv2.setDeltaFeet(amount);
                   pv2.setDeltaJoints(numJts);
                   pv2.setPipeSource(pv.getId());
                   PipeLocal pipe2 = testCreate(pv2);
                   pipe2.setPipePurchaseOrder(getPipePurchaseOrder());
                   return pipe2;
                   } else if(invalid) {
                   throw new EJBException();
                   }
                   }
                   return null;
                   }
                  


                  • 6. Re: how to roll back ejbCreate operations?
                    Jason Long Novice

                    This is the datasource I am using. Should this be set up different to roll back create transactions? This problem is really annoying. Rest assured that if I find the solution before it is posted here I will share it.

                    <datasources>
                     <local-tx-datasource>
                     <jndi-name>xxxDS</jndi-name>
                     <connection-url>jdbc:mysql://localhost:3306/exploreco</connection-url>
                     <driver-class>org.gjt.mm.mysql.Driver</driver-class>
                     <user-name>xxx</user-name>
                     <password>xxx</password>
                     </local-tx-datasource>
                    </datasources>
                    


                    • 7. Re: how to roll back ejbCreate operations?
                      Jason Long Novice

                      I finally found the problem. MySQL tables were by default created as MyISAM. I changed one of them to BerkelyDB and everything now works. Does anyone know where to specify that a table is created by default as BerkelyDB when using JBoss and MySQL?

                      • 8. Re: how to roll back ejbCreate operations?
                        Tomer ben david Novice

                        In jbosscmp-jdbc.xml

                        post-table-create
                        sql-statement
                        ALTER TABLE %%t TYPE=YOUR_DB_TYPE
                        /sql-statement
                        /post-table-create