Hibernate version:3.0
Mysql 4.1.13
Hi,
I'm having problem with my timestamp optimistic-lock automatic versioning.
My problem is that (for some weird reason) I don't always get a StaleObjectStateException when concurrent modifications are made. Here is a simple test case that illustrates this:
Code:
protected void setUp() throws Exception {
super.setUp();
referenceProduct = ProductTestCase.createMinimalProduct();
String referenceId = referenceProduct.getId();
System.err.println("RP: " + referenceProduct.getTimeStamp());
//Fetch 2 instances of a product
p1 = ProductPersistenceFacade.getInstance().fetchProduct(referenceId, localizationContext);
p2 = ProductPersistenceFacade.getInstance().fetchProduct(referenceId, localizationContext);
//Populate 2 different items
i1 = ItemTestCase.populateMinimalItem();
i1.setItemName("FIRST TRANSACTION");
i2 = ItemTestCase.populateMinimalItem();
i2.setItemName("SECOND TRANSACTION");
}
protected void tearDown() throws Exception {
super.tearDown();
Product deletedProduct = ProductPersistenceFacade.getInstance().fetchProduct(referenceProduct.getId(), localizationContext);
ProductPersistenceFacade.getInstance().deleteProduct(deletedProduct);
}
public void testConcurrentModifications() throws NoLocalizablePropertyException, InstanceNotLocalizedException, SystemException, ConcurrencyException {
p1.addItems(i1);
p1 = ProductPersistenceFacade.getInstance().saveProduct(p1);
assertEquals(1, p1.getItems().size());
System.err.println("P1: " + p1.getTimeStamp());
p2.addItems(i2);
boolean exception = false;
try {
System.err.println("P2 before: " + p2.getTimeStamp());
p2 = ProductPersistenceFacade.getInstance().saveProduct(p2);
System.err.println("P2 after: " + p2.getTimeStamp());
} catch(ConcurrencyException ce) {
//OK
exception = true;
}
assertTrue(exception);
}
The saveProduct method looks like this:
Code:
/**
* This method saves a Product in the datasource.
*
* @ejb.interface-method view-type="remote"
* @ejb.transaction type="NotSupported"
*/
public Product saveProduct(Product instance)
throws org.mdarad.framework.exception.ConcurrencyException, org.mdarad.framework.exception.SystemException {
if ("".equals(instance.getId())) instance.setId(null);
try {
// Initialize the hibernate session
Session session = currentSession();
// Start an hibernate transaction
Transaction tx = session.beginTransaction();
try {
// Schedule the value object for persistence
session.saveOrUpdate(instance);
// Commit hibernate transaction
tx.commit();
} catch (StaleObjectStateException sose) {
tx.rollback();
throw new org.mdarad.framework.exception.ConcurrencyException("The object has been modified by another user between the time the fetch and the save were completed");
} catch (HibernateException he) {
tx.rollback();
throw new org.mdarad.framework.exception.SystemException(he);
} finally {
// Close the hibernate session
closeSession();
}
} catch (HibernateException he) {
throw new org.mdarad.framework.exception.SystemException(he);
}
return instance;
}
Now when I launch this test normally, test test fails on the last
assertTrue and I get the following output:
Quote:
RP: 2005-10-09 13:44:23.728
P1: 2005-10-09 13:44:23.999
P2 before: 2005-10-09 13:44:23.0
P2 after: 2005-10-09 13:44:24.099
The test should pass for there should be a ConcurrencyException thrown.
Now this is where it becomes weird...if I do the same test but insert a Thread.sleep(1000) before the
p1 = ProductPersistenceFacade.getInstance().saveProduct(p1);, the test will pass. It is as though if there needed to be at least a certain amount of time between the 2 saves before it is considered a concurrent exception.
Is this a known bug or a workaround of some sort?
Thanks,
François[/code]