X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=test%2Fenterprise%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsupport%2Fpersistence%2FJpaBuilder.java;fp=test%2Fenterprise%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsupport%2Fpersistence%2FJpaBuilder.java;h=8b6e339935f01206ee3f795e16a8df4be49beeed;hb=2207a1e695ce23e79678c232cff2ceb84ebaa801;hp=0000000000000000000000000000000000000000;hpb=4985b85f86028eb896ac853134cb66a1299815a5;p=utils diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java new file mode 100644 index 00000000..8b6e3399 --- /dev/null +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java @@ -0,0 +1,136 @@ +package org.wamblee.support.persistence; + +import java.util.Map; +import java.util.TreeMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.Persistence; +import javax.sql.DataSource; + +import org.wamblee.support.jndi.StubInitialContextFactory; + + +/** + * Utility for building an appropriately configured EntityManagerFactory. The + * idea is that a persistence.xml is used unchanged from the production version. + * This utility will then add the additional properties required for execution + * in a standalone environment. + * + * The other purpose is to to shield dependencies of the test code on a + * particular JPA provider. + */ +public class JpaBuilder { + + private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class + .getName()); + + /** + * Callback interface to execute some JPA code within a transaction with the + * entitymanager to use provided as input. + */ + public static interface JpaUnitOfWork { + /** + * Executes the unit of work. A transaction has been started. + * @param em Entity manager. + * @return Result of the execute method. If you don't want to return anything use + * Void for the return type and return null from the implementation. + */ + T execute(EntityManager em); + } + + private PersistenceUnitDescription persistenceUnit; + private DataSource dataSource; + private EntityManagerFactory factory; + + /** + * Constructs the builder. + * + * @param aDataSource + * Datasource of database. + * @param aPersistenceUnit + * Persistence unit. + */ + public JpaBuilder(DataSource aDataSource, + PersistenceUnitDescription aPersistenceUnit) { + persistenceUnit = aPersistenceUnit; + dataSource = aDataSource; + StubInitialContextFactory.register(); + } + + /** + * Starts the builder, which in particular, mocks JNDI, binds the datasource + * the JNDI where the persistence unit expects it, creates the entity + * manager factory, and forces creation of the database schema. + */ + public void start() throws Exception { + try { + InitialContext ctx = new InitialContext(); + ctx.bind(persistenceUnit.getJndiName(), dataSource); + } catch (NamingException e) { + throw new RuntimeException("JNDI problem", e); + } + factory = createFactory(); + execute(new JpaUnitOfWork() { + public Void execute(EntityManager em) { + // Empty, just to trigger database schema creation. + return null; + } + }); + } + + /** + * Stops the entity manager factory and disables JNDI mocking. + */ + public void stop() { + StubInitialContextFactory.unregister(); + factory.close(); + } + + /** + * Creates a new entity manager factory. Typically not used by test code. + * @return Entity manager factory. + */ + public EntityManagerFactory createFactory() { + Map jpaProps = new TreeMap(); + + JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit, jpaProps); + + //jpaProps.put("javax.persistence.provider", HibernatePersistence.class.getName()); + EntityManagerFactory factory = Persistence.createEntityManagerFactory(persistenceUnit + .getUnitName(), jpaProps); + + LOGGER.info("Using " + factory.getClass()); + return factory; + } + + /** + * 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. + * @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(); + try { + T value = aWork.execute(em); + transaction.commit(); + return value; + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Exception occured", e); + transaction.rollback(); + throw e; + } finally { + em.close(); + } + } +}