Removed DOCUMENT ME comments that were generated and applied source code
[utils] / test / enterprise / src / main / java / org / wamblee / support / persistence / JpaBuilder.java
1 package org.wamblee.support.persistence;
2
3 import java.util.Map;
4 import java.util.TreeMap;
5 import java.util.logging.Level;
6 import java.util.logging.Logger;
7
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;
15
16 import org.wamblee.support.jndi.StubInitialContextFactory;
17
18 /**
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.
23  * 
24  * The other purpose is to to shield dependencies of the test code on a
25  * particular JPA provider.
26  */
27 public class JpaBuilder {
28
29     private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class
30         .getName());
31
32     /**
33      * Callback interface to execute some JPA code within a transaction with the
34      * entitymanager to use provided as input.
35      */
36     public static interface JpaUnitOfWork<T> {
37         /**
38          * Executes the unit of work. A transaction has been started.
39          * 
40          * @param em
41          *            Entity manager.
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.
45          */
46         T execute(EntityManager em);
47     }
48
49     private PersistenceUnitDescription persistenceUnit;
50     private DataSource dataSource;
51     private EntityManagerFactory factory;
52
53     /**
54      * Constructs the builder.
55      * 
56      * @param aDataSource
57      *            Datasource of database.
58      * @param aPersistenceUnit
59      *            Persistence unit.
60      */
61     public JpaBuilder(DataSource aDataSource,
62         PersistenceUnitDescription aPersistenceUnit) {
63         persistenceUnit = aPersistenceUnit;
64         dataSource = aDataSource;
65         StubInitialContextFactory.register();
66     }
67
68     /**
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.
72      */
73     public void start() throws Exception {
74         try {
75             InitialContext ctx = new InitialContext();
76             ctx.bind(persistenceUnit.getJndiName(), dataSource);
77         } catch (NamingException e) {
78             throw new RuntimeException("JNDI problem", e);
79         }
80         factory = createFactory();
81         execute(new JpaUnitOfWork<Void>() {
82             public Void execute(EntityManager em) {
83                 // Empty, just to trigger database schema creation.
84                 return null;
85             }
86         });
87     }
88
89     /**
90      * Stops the entity manager factory and disables JNDI mocking.
91      */
92     public void stop() {
93         StubInitialContextFactory.unregister();
94         factory.close();
95     }
96
97     /**
98      * Creates a new entity manager factory. Typically not used by test code.
99      * 
100      * @return Entity manager factory.
101      */
102     public EntityManagerFactory createFactory() {
103         Map<String, String> jpaProps = new TreeMap<String, String>();
104
105         JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit,
106             jpaProps);
107
108         // jpaProps.put("javax.persistence.provider",
109         // HibernatePersistence.class.getName());
110         EntityManagerFactory factory = Persistence.createEntityManagerFactory(
111             persistenceUnit.getUnitName(), jpaProps);
112
113         LOGGER.info("Using " + factory.getClass());
114         return factory;
115     }
116
117     /**
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
121      * for applications.
122      * 
123      * @param aWork
124      *            Work to execute.
125      * @return The return value of the execute method of the unit of work.
126      */
127     public <T> T execute(JpaUnitOfWork<T> aWork) throws Exception {
128         EntityManager em = factory.createEntityManager();
129         EntityTransaction transaction = em.getTransaction();
130         transaction.begin();
131         try {
132             T value = aWork.execute(em);
133             transaction.commit();
134             return value;
135         } catch (Exception e) {
136             LOGGER.log(Level.WARNING, "Exception occured", e);
137             transaction.rollback();
138             throw e;
139         } finally {
140             em.close();
141         }
142     }
143 }