0 Replies Latest reply on Sep 7, 2004 5:09 AM by paulsmith001

    Transaction rollback error & transaction best practice

    paulsmith001

      Hello,

      Let me start off with a bit of a disclaimer - I am pretty new to J2EE and JBoss!

      I have some pseudo code below that shows what is happening in my application. I have two questions based on it:

      (1) Why is my transaction not rolling back?
      (2) I think I know why I am getting a duplicate key exception (see end of this post), but I am not sure of the best way of resolving it. I think this must be a very common scenario and am therefore hoping that someone can guide me as to the best practice in this situation.

      I am using:
      JBoss 3.0.6
      JDK 1.4.1_03
      MySQL 4.0.17-nt

      MessageDrivenBean:
      onMessage()
      {
      try
      {
      UserTransaction transaction = m_context.getUserTransaction();
      transaction.begin();
      pojo = new SomeClass();
      pojo.handleMessage(-);
      transaction.commit();
      }
      catch (Exception e)
      {
      // e is a java.util.ConcurrentModificationException here
      m_context.getUserTransaction().rollback();
      // The rollback above fails with java.lang.IllegalStateException: No transaction
      }
      }

      The pojo creates a new entity. The entity's ejbPostCreate() method calls a static method [setSomething()] on a utility class that creates or updates another entity:
      public static setSomething()
      {
      entity = get An Entity
      if (entity == null)
      create the entity
      else
      set an entity property
      }

      I am getting the following exception when creating the entity:

      [org.jboss.ejb.plugins.cmp.jdbc.JDBCCreateEntityCommand.MyEntityBean] (Thread Pool Worker-1:MyEntityBean) Create: pk=001
      [org.jboss.ejb.plugins.cmp.jdbc.JDBCCreateEntityCommand.MyEntityBean] (Thread Pool Worker-1:MyEntityBean) Executing SQL: SELECT COUNT(*) FROM MyTable WHERE id=?
      [org.jboss.ejb.plugins.cmp.jdbc.JDBCCreateEntityCommand.MyEntityBean] (Thread Pool Worker-1:MyEntityBean) Executing SQL: INSERT INTO MyTable (id, field2, field3, field4) VALUES (?, ?, ?, ?)
      [org.jboss.ejb.plugins.cmp.jdbc.JDBCCreateEntityCommand.MyEntityBean] (Thread Pool Worker-1:MyEntityBean) Could not create entity
      java.sql.SQLException: Invalid argument value: Duplicate entry '001' for key 1


      I think the reason is that Thread1 checks if the entity exists, it doesn;t so it creates it. Thread2 checks if the entity exists, because Thread1 hasn't committed it doesn't, so it creates it. Thread1 commits and succeeds, Thread2 then tries to commit and gets the duplicate problem.

      I have considered many solutions to this. Synchronizing code won't work. Changing isolation level might work but cannot be the right approach? Changing the transaction type on the entity bean from Required to RequiresNew got rid of the problem, but I would rather the whole transaction rolled back if the entity update failed. sync-on-commit and commit-option will have no effect.

      Thanks in advance,
      Paul