package org.springmodules.prevayler; import org.springframework.test.AbstractDependencyInjectionSpringContextTests; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springmodules.prevayler.test.domain.Employee; import org.springmodules.prevayler.test.domain.EmployeeImpl; /** * @author Sergio Bossa */ public class PrevaylerTemplateWithTxTest extends AbstractDependencyInjectionSpringContextTests { private PrevaylerTransactionManager transactionManager; private PrevaylerTemplate template; public PrevaylerTemplateWithTxTest(String testName) { super(testName); this.setAutowireMode(AUTOWIRE_BY_NAME); } protected void onTearDown() throws Exception { } public void testSaveWithCommit() { EmployeeImpl emp = new EmployeeImpl("a1"); // Get the transaction for the first time: TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); // Id null before adding: assertNull(emp.getId()); // Save: this.template.save(emp); // Id not null after adding: assertNotNull(emp.getId()); // Commit the transaction status: this.transactionManager.commit(status); // Verify that the employee has been actually saved: EmployeeImpl emp2 = (EmployeeImpl) this.template.get(Employee.class, emp.getId()); assertNotNull(emp); assertEquals(emp, emp2); } public void testDoubleCommit() { EmployeeImpl emp = new EmployeeImpl("a1"); // Get the transaction for the first time: TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); // Save: this.template.save(emp); // Commit the transaction status: this.transactionManager.commit(status); // The double commit fails: try { this.transactionManager.commit(status); fail(); } catch(Exception ex) { System.out.println(ex.getMessage()); } } public void testSaveWithTimeout() throws InterruptedException { EmployeeImpl emp = new EmployeeImpl("a1"); // Get the transaction for the first time: TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); // Save this.template.save(emp); // Go to sleep, waiting for timeout: Thread.sleep(2000); // Trying to commit will failbecause the transaction has been aborted due to the timeout: try { this.transactionManager.commit(status); fail(); } catch(Exception ex) { System.out.println(ex.getMessage()); } } public void testSaveWithRollback() { EmployeeImpl emp = new EmployeeImpl("a1"); // Get the transaction for the first time: TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); // Save this.template.save(emp); // Verify that the employee has been saved in the current transaction scope: EmployeeImpl emp2 = (EmployeeImpl) this.template.get(Employee.class, emp.getId()); assertNotNull(emp); assertEquals(emp, emp2); // Manually roll back: this.transactionManager.rollback(status); // Verify that the employee has NOT been actually saved after rolling back: emp = (EmployeeImpl) this.template.get(Employee.class, emp.getId()); assertNull(emp); } public void testCorrectIdSequenceBetweenRollbackAndCommit() { EmployeeImpl emp1 = new EmployeeImpl("a1"); EmployeeImpl emp2 = new EmployeeImpl("a2"); Long id1 = null; Long id2 = null; // Get the transaction for the first time: TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); // Save this.template.save(emp1); // Rollback this.transactionManager.rollback(status); // First id id1 = emp1.getId(); // Now, make a save with commit and verify that the id is the same as before, // because the new transaction must re-assign the id assigned in the previously // rolled back transaction: status = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); this.template.save(emp2); this.transactionManager.commit(status); // Second id id2 = emp2.getId(); assertEquals(id1, id2); } public void testCorrectIdSequenceBetweenCommits() { EmployeeImpl emp1 = new EmployeeImpl("a1"); EmployeeImpl emp2 = new EmployeeImpl("a2"); Long id1 = null; Long id2 = null; // Get the transaction for the first time: TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); // Save this.template.save(emp1); // Rollback this.transactionManager.commit(status); // First id id1 = emp1.getId(); // Now, make a save with commit and verify that the id is equal to the previous id plus one: status = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); this.template.save(emp2); this.transactionManager.commit(status); // Second id id2 = emp2.getId(); assertEquals(id1.longValue() +1, id2.longValue()); } public void testConcurrency() throws InterruptedException { Runnable r1 = new Runnable() { public void run() { EmployeeImpl emp1 = new EmployeeImpl("a1"); TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); template.save(emp1); transactionManager.commit(status); EmployeeImpl emp2 = (EmployeeImpl) template.get(EmployeeImpl.class, emp1.getId()); assertNotNull(emp2); assertEquals("First: " + emp1.getMatriculationCode() + " - Second: "+ emp2.getMatriculationCode(), emp1, emp2); } }; Runnable r2 = new Runnable() { public void run() { EmployeeImpl emp1 = new EmployeeImpl("a2"); TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); template.save(emp1); transactionManager.commit(status); EmployeeImpl emp2 = (EmployeeImpl) template.get(EmployeeImpl.class, emp1.getId()); assertNotNull(emp2); assertEquals("First: " + emp1.getMatriculationCode() + " - Second: "+ emp2.getMatriculationCode(), emp1, emp2); } }; Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); t1.join(); t2.join(); } public void setPrevaylerTemplateWithTx(PrevaylerTemplate template) { this.template = template; } public void setTransactionManager(PrevaylerTransactionManager transactionManager) { this.transactionManager = transactionManager; } protected String[] getConfigLocations() { return new String[]{"testContext.xml"}; } }