Hello,
I have written a test-method that deals with the behavior of xa
transactions and can be executed within XATest.java (
http://svn.apache.org/repos/asf/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java
) - it is attached below this email. The test-method attempts to
simulate the case that two transactions edit the same property of a node
concurrently. It fails with a RollbackException once the second
transaction commits (at the latest if the test-method is executed more
than once).
The very first question is: Is it a valid approach to simulate two
concurrent transactions like that within XATest? :)
If so, then there are more questions: Does this test-method show the
intended behavior? That would imply some kind of a prevention of lost
updates.
If that is not the intended behavior: What is wrong or what am I doing
wrong?
I'm doubtful that the test-method shows the intended behavior, because:
1) I have already suggested above that the test-method sometimes passes.
2.) If I change the passage of code below the 'prerequisite'-comment
into (so that the 'testNode' is 'fresh' each time)
// prerequisite for test - fresh 'testNode' exists
if (session0.getRootNode().hasNode("testNode")) {
session0.getRootNode().getNode("testNode").remove();
session0.save();
}
session0.getRootNode().addNode("testNode");
session0.save();
then the test-method never fails.
However, I am confused. Especially since the test seems to always fail
if I map it onto a scenario that uses the JCA package and container
managed transactions.
In a nutshell, what I would like to know is: What is the *intended*
behavior?
Many thanks,
Dominik
public void testConcurrentTx() throws Exception {
Session session0 = null;
Session session1 = null;
Session session2 = null;
try {
session0 = getHelper().getSuperuserSession();
session1 = getHelper().getSuperuserSession();
session2 = getHelper().getSuperuserSession();
// prerequisite for test - 'testNode' exists
if (!session0.getRootNode().hasNode("testNode")) {
session0.getRootNode().addNode("testNode");
session0.save();
}
// two concurrent transactions, which both set a property
of the 'testNode' and then commit
UserTransaction utx1 = new UserTransactionImpl(session1);
UserTransaction utx2 = new UserTransactionImpl(session2);
utx1.begin();
utx2.begin();
session1.getRootNode().getNode("testNode").setProperty("test", "session1");
session1.save();
session2.getRootNode().getNode("testNode").setProperty("test", "session2");
session2.save();
utx1.commit();
utx2.commit();
} finally {
if (session0 != null) {
session0.logout();
}
if (session1 != null) {
session1.logout();
}
if (session2 != null) {
session2.logout();
}
}
}