X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=test%2Fenterprise%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Ftest%2Fpersistence%2FJpaBuilder.java;h=223971c6cdfec69eec48daf8e224f452b2f61663;hb=31389a635dd4aa4eb18b5897962ff8ecb450350a;hp=331ea9a10390b11b88375b32dfbe714ce9e9f9e7;hpb=cb91054f35281c6fc5619f93ff71df46bf4686b9;p=utils diff --git a/test/enterprise/src/main/java/org/wamblee/test/persistence/JpaBuilder.java b/test/enterprise/src/main/java/org/wamblee/test/persistence/JpaBuilder.java index 331ea9a1..223971c6 100644 --- a/test/enterprise/src/main/java/org/wamblee/test/persistence/JpaBuilder.java +++ b/test/enterprise/src/main/java/org/wamblee/test/persistence/JpaBuilder.java @@ -26,7 +26,10 @@ import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import javax.persistence.PersistenceException; +import org.wamblee.general.ThreadSpecificProxyFactory; import org.wamblee.test.jndi.StubInitialContextFactory; +import org.wamblee.test.transactions.TransactionResource; +import org.wamblee.test.transactions.TransactionResult; /** * Utility for building an appropriately configured EntityManagerFactory. The @@ -37,7 +40,7 @@ import org.wamblee.test.jndi.StubInitialContextFactory; * The other purpose is to to shield dependencies of the test code on a * particular JPA provider. */ -public class JpaBuilder { +public class JpaBuilder implements TransactionResource { private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class .getName()); @@ -60,26 +63,32 @@ public class JpaBuilder { } private PersistenceUnitDescription persistenceUnit; - private String url; - private String user; - private String password; + private String url; + private String user; + private String password; private EntityManagerFactory factory; + private ThreadSpecificProxyFactory entityManager; /** * Constructs the builder. * - * @param aUrl JDBC URL - * @param aUser User name - * @param aPassword Password. + * @param aUrl + * JDBC URL + * @param aUser + * User name + * @param aPassword + * Password. * @param aPersistenceUnit * Persistence unit. */ public JpaBuilder(String aUrl, String aUser, String aPassword, PersistenceUnitDescription aPersistenceUnit) { persistenceUnit = aPersistenceUnit; - url = aUrl; - user = aUser; - password = aPassword; + url = aUrl; + user = aUser; + password = aPassword; + entityManager = new ThreadSpecificProxyFactory( + EntityManager.class); } /** @@ -117,7 +126,7 @@ public class JpaBuilder { */ public EntityManagerFactory createFactory() { Map jpaProps = new TreeMap(); - + jpaProps.put("javax.persistence.jtaDataSource", null); jpaProps.put("javax.persistence.transactionType", "RESOURCE_LOCAL"); jpaProps.put("javax.persistence.jdbc.url", url); @@ -126,7 +135,7 @@ public class JpaBuilder { JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit, jpaProps); - + // jpaProps.put("javax.persistence.provider", // HibernatePersistence.class.getName()); EntityManagerFactory emf = Persistence.createEntityManagerFactory( @@ -142,24 +151,100 @@ public class JpaBuilder { * passing it the entity manager. Use of this method saves a lot of typing * for applications. * + * This method requires the transaction to succeed. Otherwise the test will + * fail. See {@link #execute(JpaUnitOfWork, TransactionResultCallback)} and + * {@link RequireTransactionStatus} for more possibilities. + * * @param aWork * Work to execute. + * * @return The return value of the execute method of the unit of work. */ public T execute(JpaUnitOfWork aWork) throws Exception { - EntityManager em = factory.createEntityManager(); - EntityTransaction transaction = em.getTransaction(); - transaction.begin(); + return execute(aWork, new RequireTransactionStatus(TransactionResult.COMMIT)); + } + + /** + * Executes a unit of work. This creates an entitymanager and runs the + * {@link JpaUnitOfWork#execute(EntityManager)} within a transaction, + * passing it the entity manager. Use of this method saves a lot of typing + * for applications. + * + * @param aWork + * Work to execute. + * @param aTransactionResultCallback + * callback to notify of the result of the transaction. + * + * @return The return value of the execute method of the unit of work. + */ + public T execute(JpaUnitOfWork aWork, + TransactionResultCallback aCallback) throws Exception { + EntityManager em = begin(); try { T value = aWork.execute(em); - transaction.commit(); + TransactionResult result = commit(em); + aCallback.status(result); return value; } catch (Exception e) { LOGGER.log(Level.WARNING, "Exception occured", e); - transaction.rollback(); + TransactionResult result = rollback(em); + aCallback.status(result); throw e; + } + } + + @Override + public EntityManager begin() { + EntityManager em = factory.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + entityManager.set(em); + return em; + } + + @Override + public TransactionResult commit(EntityManager aEntityManager) { + try { + EntityTransaction transaction = aEntityManager.getTransaction(); + if (transaction.isActive()) { + if (transaction.getRollbackOnly()) { + transaction.rollback(); + return TransactionResult.ROLLBACK; + } + transaction.commit(); + return TransactionResult.COMMIT; + } + return TransactionResult.UNKNOWN; } finally { - em.close(); + aEntityManager.close(); + entityManager.set(null); } } + + @Override + public TransactionResult rollback(EntityManager aEntityManager) { + try { + EntityTransaction transaction = aEntityManager.getTransaction(); + if (transaction.isActive()) { + transaction.rollback(); + return TransactionResult.ROLLBACK; + } + return TransactionResult.UNKNOWN; + } finally { + if (aEntityManager.isOpen()) { + aEntityManager.close(); + } + entityManager.set(null); + } + } + + /** + * Gets a contextual reference to an entity manager that delegates to the + * appropriate (current) one which is active for the current transaction. + * + * @return EntityManager. + */ + public EntityManager getContextualEntityManager() { + return entityManager.getProxy(); + } }