2 * Copyright 2005-2010 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.support.persistence;
19 import java.util.TreeMap;
20 import java.util.logging.Level;
21 import java.util.logging.Logger;
23 import javax.persistence.EntityManager;
24 import javax.persistence.EntityManagerFactory;
25 import javax.persistence.EntityTransaction;
26 import javax.persistence.Persistence;
27 import javax.persistence.PersistenceException;
29 import org.wamblee.support.jndi.StubInitialContextFactory;
32 * Utility for building an appropriately configured EntityManagerFactory. The
33 * idea is that a persistence.xml is used unchanged from the production version.
34 * This utility will then add the additional properties required for execution
35 * in a standalone environment.
37 * The other purpose is to to shield dependencies of the test code on a
38 * particular JPA provider.
40 public class JpaBuilder {
42 private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class
46 * Callback interface to execute some JPA code within a transaction with the
47 * entitymanager to use provided as input.
49 public static interface JpaUnitOfWork<T> {
51 * Executes the unit of work. A transaction has been started.
55 * @return Result of the execute method. If you don't want to return
56 * anything use <code>Void</code> for the return type and return
57 * null from the implementation.
59 T execute(EntityManager aEm) throws Exception;
62 private PersistenceUnitDescription persistenceUnit;
65 private String password;
66 private EntityManagerFactory factory;
69 * Constructs the builder.
71 * @param aUrl JDBC URL
72 * @param aUser User name
73 * @param aPassword Password.
74 * @param aPersistenceUnit
77 public JpaBuilder(String aUrl, String aUser, String aPassword,
78 PersistenceUnitDescription aPersistenceUnit) {
79 persistenceUnit = aPersistenceUnit;
86 * Starts the builder, which in particular, mocks JNDI, binds the datasource
87 * the JNDI where the persistence unit expects it, creates the entity
88 * manager factory, and forces creation of the database schema.
90 public void start() throws Exception {
91 factory = createFactory();
93 execute(new JpaUnitOfWork<Void>() {
94 public Void execute(EntityManager aEm) {
95 // Empty, just to trigger database schema creation.
99 } catch (PersistenceException e) {
106 * Stops the entity manager factory and disables JNDI mocking.
109 StubInitialContextFactory.unregister();
114 * Creates a new entity manager factory. Typically not used by test code.
116 * @return Entity manager factory.
118 public EntityManagerFactory createFactory() {
119 Map<String, String> jpaProps = new TreeMap<String, String>();
121 jpaProps.put("javax.persistence.jtaDataSource", null);
122 jpaProps.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
123 jpaProps.put("javax.persistence.jdbc.url", url);
124 jpaProps.put("javax.persistence.jdbc.user", user);
125 jpaProps.put("javax.persistence.jdbc.password", password);
127 JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit,
130 // jpaProps.put("javax.persistence.provider",
131 // HibernatePersistence.class.getName());
132 EntityManagerFactory emf = Persistence.createEntityManagerFactory(
133 persistenceUnit.getUnitName(), jpaProps);
135 LOGGER.info("Using " + emf.getClass());
140 * Executes a unit of work. This creates an entitymanager and runs the
141 * {@link JpaUnitOfWork#execute(EntityManager)} within a transaction,
142 * passing it the entity manager. Use of this method saves a lot of typing
147 * @return The return value of the execute method of the unit of work.
149 public <T> T execute(JpaUnitOfWork<T> aWork) throws Exception {
150 EntityManager em = factory.createEntityManager();
151 EntityTransaction transaction = em.getTransaction();
154 T value = aWork.execute(em);
155 transaction.commit();
157 } catch (Exception e) {
158 LOGGER.log(Level.WARNING, "Exception occured", e);
159 transaction.rollback();