Transaction rollback error & transaction best practice
paulsmith001 Sep 7, 2004 5:09 AMHello,
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