1 package org.wamblee.support.persistence;
4 import java.util.TreeMap;
5 import java.util.logging.Level;
6 import java.util.logging.Logger;
8 import javax.naming.InitialContext;
9 import javax.naming.NamingException;
10 import javax.persistence.EntityManager;
11 import javax.persistence.EntityManagerFactory;
12 import javax.persistence.EntityTransaction;
13 import javax.persistence.Persistence;
14 import javax.sql.DataSource;
16 import org.wamblee.support.jndi.StubInitialContextFactory;
19 * Utility for building an appropriately configured EntityManagerFactory. The
20 * idea is that a persistence.xml is used unchanged from the production version.
21 * This utility will then add the additional properties required for execution
22 * in a standalone environment.
24 * The other purpose is to to shield dependencies of the test code on a
25 * particular JPA provider.
27 public class JpaBuilder {
29 private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class
33 * Callback interface to execute some JPA code within a transaction with the
34 * entitymanager to use provided as input.
36 public static interface JpaUnitOfWork<T> {
38 * Executes the unit of work. A transaction has been started.
42 * @return Result of the execute method. If you don't want to return
43 * anything use <code>Void</code> for the return type and return
44 * null from the implementation.
46 T execute(EntityManager em);
49 private PersistenceUnitDescription persistenceUnit;
50 private DataSource dataSource;
51 private EntityManagerFactory factory;
54 * Constructs the builder.
57 * Datasource of database.
58 * @param aPersistenceUnit
61 public JpaBuilder(DataSource aDataSource,
62 PersistenceUnitDescription aPersistenceUnit) {
63 persistenceUnit = aPersistenceUnit;
64 dataSource = aDataSource;
65 StubInitialContextFactory.register();
69 * Starts the builder, which in particular, mocks JNDI, binds the datasource
70 * the JNDI where the persistence unit expects it, creates the entity
71 * manager factory, and forces creation of the database schema.
73 public void start() throws Exception {
75 InitialContext ctx = new InitialContext();
76 ctx.bind(persistenceUnit.getJndiName(), dataSource);
77 } catch (NamingException e) {
78 throw new RuntimeException("JNDI problem", e);
80 factory = createFactory();
81 execute(new JpaUnitOfWork<Void>() {
82 public Void execute(EntityManager em) {
83 // Empty, just to trigger database schema creation.
90 * Stops the entity manager factory and disables JNDI mocking.
93 StubInitialContextFactory.unregister();
98 * Creates a new entity manager factory. Typically not used by test code.
100 * @return Entity manager factory.
102 public EntityManagerFactory createFactory() {
103 Map<String, String> jpaProps = new TreeMap<String, String>();
105 JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit,
108 // jpaProps.put("javax.persistence.provider",
109 // HibernatePersistence.class.getName());
110 EntityManagerFactory factory = Persistence.createEntityManagerFactory(
111 persistenceUnit.getUnitName(), jpaProps);
113 LOGGER.info("Using " + factory.getClass());
118 * Executes a unit of work. This creates an entitymanager and runs the
119 * {@link JpaUnitOfWork#execute(EntityManager)} within a transaction,
120 * passing it the entity manager. Use of this method saves a lot of typing
125 * @return The return value of the execute method of the unit of work.
127 public <T> T execute(JpaUnitOfWork<T> aWork) throws Exception {
128 EntityManager em = factory.createEntityManager();
129 EntityTransaction transaction = em.getTransaction();
132 T value = aWork.execute(em);
133 transaction.commit();
135 } catch (Exception e) {
136 LOGGER.log(Level.WARNING, "Exception occured", e);
137 transaction.rollback();