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.naming.InitialContext;
24 import javax.naming.NamingException;
25 import javax.persistence.EntityManager;
26 import javax.persistence.EntityManagerFactory;
27 import javax.persistence.EntityTransaction;
28 import javax.persistence.Persistence;
29 import javax.sql.DataSource;
31 import org.wamblee.support.jndi.StubInitialContextFactory;
34 * Utility for building an appropriately configured EntityManagerFactory. The
35 * idea is that a persistence.xml is used unchanged from the production version.
36 * This utility will then add the additional properties required for execution
37 * in a standalone environment.
39 * The other purpose is to to shield dependencies of the test code on a
40 * particular JPA provider.
42 public class JpaBuilder {
44 private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class
48 * Callback interface to execute some JPA code within a transaction with the
49 * entitymanager to use provided as input.
51 public static interface JpaUnitOfWork<T> {
53 * Executes the unit of work. A transaction has been started.
57 * @return Result of the execute method. If you don't want to return
58 * anything use <code>Void</code> for the return type and return
59 * null from the implementation.
61 T execute(EntityManager aEm) throws Exception;
64 private PersistenceUnitDescription persistenceUnit;
65 private DataSource dataSource;
66 private EntityManagerFactory factory;
69 * Constructs the builder.
72 * Datasource of database.
73 * @param aPersistenceUnit
76 public JpaBuilder(DataSource aDataSource,
77 PersistenceUnitDescription aPersistenceUnit) {
78 persistenceUnit = aPersistenceUnit;
79 dataSource = aDataSource;
80 StubInitialContextFactory.register();
84 * Starts the builder, which in particular, mocks JNDI, binds the datasource
85 * the JNDI where the persistence unit expects it, creates the entity
86 * manager factory, and forces creation of the database schema.
88 public void start() throws Exception {
90 InitialContext ctx = new InitialContext();
91 ctx.bind(persistenceUnit.getJndiName(), dataSource);
92 } catch (NamingException e) {
93 throw new RuntimeException("JNDI problem", e);
95 factory = createFactory();
96 execute(new JpaUnitOfWork<Void>() {
97 public Void execute(EntityManager aEm) {
98 // Empty, just to trigger database schema creation.
105 * Stops the entity manager factory and disables JNDI mocking.
108 StubInitialContextFactory.unregister();
113 * Creates a new entity manager factory. Typically not used by test code.
115 * @return Entity manager factory.
117 public EntityManagerFactory createFactory() {
118 Map<String, String> jpaProps = new TreeMap<String, String>();
120 JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit,
123 // jpaProps.put("javax.persistence.provider",
124 // HibernatePersistence.class.getName());
125 EntityManagerFactory factory = Persistence.createEntityManagerFactory(
126 persistenceUnit.getUnitName(), jpaProps);
128 LOGGER.info("Using " + factory.getClass());
133 * Executes a unit of work. This creates an entitymanager and runs the
134 * {@link JpaUnitOfWork#execute(EntityManager)} within a transaction,
135 * passing it the entity manager. Use of this method saves a lot of typing
140 * @return The return value of the execute method of the unit of work.
142 public <T> T execute(JpaUnitOfWork<T> aWork) throws Exception {
143 EntityManager em = factory.createEntityManager();
144 EntityTransaction transaction = em.getTransaction();
147 T value = aWork.execute(em);
148 transaction.commit();
150 } catch (Exception e) {
151 LOGGER.log(Level.WARNING, "Exception occured", e);
152 transaction.rollback();