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.persistence.PersistenceException;
30 import javax.sql.DataSource;
32 import org.wamblee.support.jndi.StubInitialContextFactory;
35 * Utility for building an appropriately configured EntityManagerFactory. The
36 * idea is that a persistence.xml is used unchanged from the production version.
37 * This utility will then add the additional properties required for execution
38 * in a standalone environment.
40 * The other purpose is to to shield dependencies of the test code on a
41 * particular JPA provider.
43 public class JpaBuilder {
45 private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class
49 * Callback interface to execute some JPA code within a transaction with the
50 * entitymanager to use provided as input.
52 public static interface JpaUnitOfWork<T> {
54 * Executes the unit of work. A transaction has been started.
58 * @return Result of the execute method. If you don't want to return
59 * anything use <code>Void</code> for the return type and return
60 * null from the implementation.
62 T execute(EntityManager aEm) throws Exception;
65 private PersistenceUnitDescription persistenceUnit;
66 private DataSource dataSource;
67 private EntityManagerFactory factory;
70 * Constructs the builder.
73 * Datasource of database.
74 * @param aPersistenceUnit
77 public JpaBuilder(DataSource aDataSource,
78 PersistenceUnitDescription aPersistenceUnit) {
79 persistenceUnit = aPersistenceUnit;
80 dataSource = aDataSource;
81 StubInitialContextFactory.register();
85 * Starts the builder, which in particular, mocks JNDI, binds the datasource
86 * the JNDI where the persistence unit expects it, creates the entity
87 * manager factory, and forces creation of the database schema.
89 public void start() throws Exception {
91 InitialContext ctx = new InitialContext();
92 ctx.bind(persistenceUnit.getJndiName(), dataSource);
93 } catch (NamingException e) {
94 throw new RuntimeException("JNDI problem", e);
96 factory = createFactory();
98 execute(new JpaUnitOfWork<Void>() {
99 public Void execute(EntityManager aEm) {
100 // Empty, just to trigger database schema creation.
104 } catch (PersistenceException e) {
111 * Stops the entity manager factory and disables JNDI mocking.
114 StubInitialContextFactory.unregister();
119 * Creates a new entity manager factory. Typically not used by test code.
121 * @return Entity manager factory.
123 public EntityManagerFactory createFactory() {
124 Map<String, String> jpaProps = new TreeMap<String, String>();
126 JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit,
129 // jpaProps.put("javax.persistence.provider",
130 // HibernatePersistence.class.getName());
131 EntityManagerFactory factory = Persistence.createEntityManagerFactory(
132 persistenceUnit.getUnitName(), jpaProps);
134 LOGGER.info("Using " + factory.getClass());
139 * Executes a unit of work. This creates an entitymanager and runs the
140 * {@link JpaUnitOfWork#execute(EntityManager)} within a transaction,
141 * passing it the entity manager. Use of this method saves a lot of typing
146 * @return The return value of the execute method of the unit of work.
148 public <T> T execute(JpaUnitOfWork<T> aWork) throws Exception {
149 EntityManager em = factory.createEntityManager();
150 EntityTransaction transaction = em.getTransaction();
153 T value = aWork.execute(em);
154 transaction.commit();
156 } catch (Exception e) {
157 LOGGER.log(Level.WARNING, "Exception occured", e);
158 transaction.rollback();