5 Replies Latest reply on Mar 27, 2012 3:06 PM by falcor1

    Auto commit remains enabled in transaction

    falcor1

      Hello. I have been developing/maintaining an application over the last couple of years that runs in JBoss 5.1.0.GA using JPA 1.0 with Hibernate 3.3.1.GA/Hibernate EM 3.4.0.GA as the persistence provider. Long ago I saw some weird behavior when constraint violations were encountered: some of the entity tables had rows inserted but others did not, even though I was within a transaction that was rolled back when the exception was caught. At the time my fix was to simply correct the constraint violation issues and the problem went away, even though the lack of transactional behavior was a bit disturbing.

       

      Two years later I am revisiting this issue and have come across a troubling observation that explains the symptoms that I observed. It turns out that, even though I am within a transaction, my connection's autocommit flag is still true. I have verified this in several ways:

      1) Step through the code. The moment I step over a call to EntityManager.flush() I can see modified data in a separate DB session (using pgAdmin)

      2) Turn on SQL logging at the database (PostgreSQL 8.3 if it matters), no BEGIN/COMMIT/ROLLBACK ever appears

      3) Add the following code before after my calls to EntityManager.persist/flush:

       

       

      Session s = (Session)entityManager.getDelegate();
      boolean autocommit = s.connection().getAutoCommit(); // always true
      
      


      The way that I understand things, the proper behavior is that whenever I start a transaction autocommit should be disabled. I spent the better part of yesterday stepping through Hibernate/JBoss/Arjuna code and cannot find where this would ever happen. When grepping the Hibernate code, I find very few calls to Connection.setAutoCommit(false) and they appear in classes that wouldn't be used in my situation anyway (certain connection providers and transaction implementations). When grepping through the JBoss/Arjuna code, I don't see anywhere that it would happen either.

       

      Here is the relevant persistence context definition and code that exhibits the autocommit behavior (note that I mentioned an entity that exists across several tables earlier, and this sample shows only 1 entity class, but both DAOs/PUs show the same symptoms):


          <persistence-unit name="georeo">
              <jta-data-source>java:/Georeo_DS</jta-data-source>
              <class>com.orci.websol.georeo.Georeo</class>
              <properties>
                  <property name="hibernate.hbm2ddl.auto" value="validate" />
      
                  <!-- this property wasn't here initially but adding it didn't help -->
                  <property name="org.hibernate.transaction.manager_lookup_class"
                     value="org.hibernate.transaction.JBossTransactionManagerLookup" />
              </properties>
          </persistence-unit>
      
      

       

       

      @PersistenceContext(unitName = "georeo")
      private EntityManager entityManager;
      @Resource
      private UserTransaction utx;
      
      public void updateGeoreos(String eventId, Map<Georeo, PersistableGeometry> georeosToGeoms) throws GeoreoException {
         try {
            utx.begin();
      
      
            for (Entry<Georeo, PersistableGeometry> entry : georeosToGeoms.entrySet()) {
               Georeo georeo = entry.getKey();
               PersistableGeometry geom = entry.getValue();
               entityManager.persist(georeo);
               // result of persist is visible to others immediately after this flush
               entityManager.flush();
      
               // insert the geometry
               String insert = createInsertStmt(georeo, geom);
               Query q = entityManager.createNativeQuery(insert);
               q.executeUpdate();
            }
            utx.commit();
         } catch (Exception e) {
            LOG.error("Could not update georeo for event " + eventId, e);
            try {
               utx.rollback();
            } catch (Exception ee) {
               LOG.warn("Failed to rollback", ee);
            }
            throw new GeoreoException("Could not update georeo for event " + eventId, e);
         }
      }
      
      

       

      From the code you can see that I am using JTA, so I don't/can't try to use EntityTransactions instead, and the code is using bean managed transactions (although it doesn't really need to be), but I have also tried container managed transactions with no luck. So my questions are

      1) Am I correct in assuming that autocommit should be disabled when a transaction is started? (Cause otherwise it's not really a transaction, right?)

      2) Who is responsible for disabling autocommit, the persistence provider (Hibernate) or the transaction manager (JBossTS/Arjuna)?

      3) Why isn't it being disabled? Am I missing a setting?

       

      Thanks

        • 1. Re: Auto commit remains enabled in transaction
          falcor1

          I've also verified the same behavior in JBoss 6.1.0 today

          • 2. Re: Auto commit remains enabled in transaction
            wdfink

            How your datasource definition is?

            Do you use a XA-datasource?

            • 3. Re: Auto commit remains enabled in transaction
              falcor1

              It's not XA, just a simple c3p0 DS, defined in c3p0-service.xml and placed in the deploy directory:

               

               

              <?xml version="1.0" encoding="utf-8"?>
              <!DOCTYPE server []>
              <server>
              
              
                <mbean code="com.mchange.v2.c3p0.jboss.C3P0PooledDataSource" name="jboss.jca:name=Georeo_DS,service=DataSourceBinding">
                  <attribute name="JndiName">java:Georeo_DS</attribute>
                  <attribute name="JdbcUrl">jdbc:postgresql://192.168.115.12/georeo</attribute>
                  <attribute name="DriverClass">org.postgresql.Driver</attribute>
                  <attribute name="User">postgres</attribute>
                  <attribute name="Password">postgres</attribute>
                  <depends>jboss:service=Naming</depends>
                </mbean>
              
              
              </server>
              
              
              • 4. Re: Auto commit remains enabled in transaction
                wdfink

                I never tried this.

                I suppose if you use a transactional XXX-ds.xml definition for Georeo_DS it will work as expected.

                • 5. Re: Auto commit remains enabled in transaction
                  falcor1

                  Wow, that solved the problem, thanks.  I never considered that JBoss would be relying on behavior of its own DataSource implementations and wouldn't be compatible with others.  I guess it would be nice if JBoss would have provided some sort of warning along the lines of 'Custom DS may not behave as expected'.  Oh well, too late now, and JBoss 7 makes it a bit more difficult to use the c3p0 DataSource MBeans anyway (although there probably isn't anything stopping me from manually binding my own DS into JNDI).

                   

                  Thanks again.