All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unitils.orm.jpa.JpaModule Maven / Gradle / Ivy

/*
 * Copyright 2008,  Unitils.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.unitils.orm.jpa;

import static org.unitils.util.AnnotationUtils.getFieldsAnnotatedWith;
import static org.unitils.util.AnnotationUtils.getMethodsAnnotatedWith;
import static org.unitils.util.PropertyUtils.getString;
import static org.unitils.util.ReflectionUtils.setFieldAndSetterValue;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.unitils.core.TestListener;
import org.unitils.core.util.ConfigUtils;
import org.unitils.database.DataSourceWrapper;
import org.unitils.database.transaction.impl.UnitilsTransactionManagementConfiguration;
import org.unitils.orm.common.OrmModule;
import org.unitils.orm.common.util.OrmPersistenceUnitLoader;
import org.unitils.orm.jpa.annotation.JpaEntityManagerFactory;
import org.unitils.orm.jpa.util.JpaAnnotationConfigLoader;
import org.unitils.orm.jpa.util.JpaConfig;
import org.unitils.orm.jpa.util.JpaEntityManagerFactoryLoader;
import org.unitils.orm.jpa.util.JpaProviderSupport;
import org.unitils.util.AnnotationUtils;

/**
 * Module providing support for unit tests for code that uses JPA. It offers an easy way of loading a 
 * EntityManagerFactory and having it injected into the test. The configured 
 * EntityManagerFactory will connect to the unitils configured test datasource, and
 * join in unitils test-bound transactions.
 * 

* EntityManagerFactory instances are cached, to make sure that for any two tests that share the same * configuration, the same instance of this object is used. *

* An EntityManagerFactory is injected into all fields or methods of the test object * annotated with {@link JpaEntityManagerFactory} or javax.persistence.PersistenceUnit. An * EntityManager is injected into all fields or methods of the test annotated with * javax.persistence.PersistenceContext. * todo injection into other objects *

* This module also offers a test to check whether the mapping of all entities is consistent with the structure of the * database. It is highly recommended to write a unit test that invokes {@link JpaUnitils#assertMappingWithDatabaseConsistent()}, * This is a very useful test that verifies whether the mapping of all your objects entities still corresponds * with the actual structure of the database. Currently, it's only available when the persistence provider is hibernate. * * @author Filip Neven * @author Tim Ducheyne */ public class JpaModule extends OrmModule { /* Property key that defines the persistence provider */ public static final String PROPKEY_PERSISTENCE_PROVIDER = "jpa.persistenceProvider"; /* The logger instance for this class */ private static Log logger = LogFactory.getLog(JpaModule.class); /** * Implements provider specific operations */ protected JpaProviderSupport jpaProviderSupport; /** * Constructor for JpaModule. */ public JpaModule() { super(); // Make sure recent version spring ORM module is in the classpath AbstractEntityManagerFactoryBean.class.getName(); } /** * @param configuration The Unitils configuration, not null */ public void init(Properties configuration) { super.init(configuration); String persistenceProviderImplClassName = getString(PROPKEY_PERSISTENCE_PROVIDER, configuration); jpaProviderSupport = ConfigUtils.getInstanceOf(JpaProviderSupport.class, configuration, persistenceProviderImplClassName); } public void afterInit() { super.afterInit(); } public void registerTransactionManagementConfiguration() { // Make sure that a spring JpaTransactionManager is used for transaction management in the database module, if the // current test object defines a JPA EntityManagerFactory for (final DataSourceWrapper wrapper : wrappers) { getDatabaseModule().registerTransactionManagementConfiguration(new UnitilsTransactionManagementConfiguration() { public boolean isApplicableFor(Object testObject) { return isPersistenceUnitConfiguredFor(testObject); } public PlatformTransactionManager getSpringPlatformTransactionManager(Object testObject) { EntityManagerFactory entityManagerFactory = getPersistenceUnit(testObject); JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(entityManagerFactory); jpaTransactionManager.setDataSource(getDataSource()); jpaTransactionManager.setJpaDialect(jpaProviderSupport.getSpringJpaVendorAdaptor().getJpaDialect()); return jpaTransactionManager; } public boolean isTransactionalResourceAvailable(Object testObject) { return wrapper.isDataSourceLoaded(); } public Integer getPreference() { return 10; } }); } } @Override protected JpaAnnotationConfigLoader createOrmConfigLoader() { return new JpaAnnotationConfigLoader(); } @Override protected Class getPersistenceUnitConfigAnnotationClass() { return JpaEntityManagerFactory.class; } @Override protected Class getPersistenceUnitClass() { return EntityManagerFactory.class; } @Override protected OrmPersistenceUnitLoader createOrmPersistenceUnitLoader() { return new JpaEntityManagerFactoryLoader(databaseName); } @Override protected String getOrmSpringSupportImplClassName() { return "org.unitils.orm.jpa.util.spring.JpaSpringSupport"; } protected EntityManager doGetPersistenceContext(Object testObject) { return EntityManagerFactoryUtils.getTransactionalEntityManager(getPersistenceUnit(testObject)); } protected EntityManager doGetActivePersistenceContext(Object testObject) { EntityManagerHolder entityManagerHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(getPersistenceUnit(testObject)); if (entityManagerHolder != null && entityManagerHolder.getEntityManager() != null && entityManagerHolder.getEntityManager().isOpen()) { return entityManagerHolder.getEntityManager(); } return null; } protected void flushOrmPersistenceContext(EntityManager activeEntityManager) { logger.info("Flushing entity manager " + activeEntityManager); activeEntityManager.flush(); } /** * Checks if the mapping of the managed objects with the database is still correct. * * @param testObject The test instance, not null */ public void assertMappingWithDatabaseConsistent(Object testObject) { jpaProviderSupport.assertMappingWithDatabaseConsistent(getPersistenceUnit(testObject).createEntityManager(), getConfiguredPersistenceUnit(testObject).getOrmConfigurationObject()); } /** * Injects the currently configured EntityManagerFactory and currently active * EntityManager into fields or methods or the test object annotated with * javax.persistence.PersistenceUnit or javax.persistence.PersistenceContext, * respectively. * * @param testObject The test instance, not null */ public void injectJpaResourcesIntoTestObject(Object testObject) { // If no EntityManagerFactory was configured in unitils, nothing can be injected if (!isPersistenceUnitConfiguredFor(testObject)) { return; } injectJpaResourcesInto(testObject, testObject); } /** * Injects the EntityManagerFactory and currently active EntityManager into fields * or methods of the given target object annotated with javax.persistence.PersistenceUnit or * javax.persistence.PersistenceContext, respectively. * * @param testObject The test object, not null * @param target The target object to inject the resources into, not null */ public void injectJpaResourcesInto(Object testObject, Object target) { injectEntityManagerFactory(testObject, target); injectEntityManager(testObject, target); } /** * Injects the JPA EntityManagerFactory into all fields and methods that are * annotated with javax.persistence.PersistenceUnit * * @param testObject The test object, not null */ public void injectEntityManagerFactory(Object testObject, Object target) { Set fields = getFieldsAnnotatedWith(target.getClass(), PersistenceUnit.class); Set methods = getMethodsAnnotatedWith(target.getClass(), PersistenceUnit.class); if (fields.isEmpty() && methods.isEmpty()) { // Jump out to make sure that we don't try to instantiate the EntityManagerFactory return; } EntityManagerFactory entityManagerFactory = getPersistenceUnit(testObject); setFieldAndSetterValue(target, fields, methods, entityManagerFactory); } /** * Injects the currently active JPA EntityManager into all fields and methods that are * annotated with javax.persistence.PersistenceContext * * @param testObject The test object, not null */ public void injectEntityManager(Object testObject, Object target) { Set fields = getFieldsAnnotatedWith(target.getClass(), PersistenceContext.class); Set methods = getMethodsAnnotatedWith(target.getClass(), PersistenceContext.class); if (fields.isEmpty() && methods.isEmpty()) { // Jump out to make sure that we don't try to instantiate the EntityManagerFactory return; } EntityManager entityManager = getPersistenceContext(testObject); setFieldAndSetterValue(target, fields, methods, entityManager); } protected DataSource getDataSource() { return getDatabaseModule().getWrapper(databaseName).getDataSourceAndActivateTransactionIfNeeded(); } public JpaProviderSupport getJpaProviderSupport() { return jpaProviderSupport; } /** * @return The TestListener associated with this module */ public TestListener getTestListener() { return new JpaTestListener(); } /** * The {@link TestListener} for this module */ protected class JpaTestListener extends OrmTestListener { @Override public void beforeTestSetUp(Object testObject, Method testMethod) { getDatabaseName(testObject, testMethod); registerTransactionManagementConfiguration(); injectJpaResourcesIntoTestObject(testObject); } } /** * @see org.unitils.orm.common.OrmModule#getDatabaseName(java.lang.Object, java.lang.reflect.Method) */ @Override protected void getDatabaseName(Object testObject, Method testMethod) { JpaEntityManagerFactory dataSource = AnnotationUtils.getMethodOrClassLevelAnnotation(JpaEntityManagerFactory.class, testMethod, testObject.getClass()); if (dataSource != null) { wrappers.add(getDatabaseModule().getWrapper(dataSource.databaseName())); } Set lstDataSources = AnnotationUtils.getFieldLevelAnnotations(testObject.getClass(), JpaEntityManagerFactory.class); if (!lstDataSources.isEmpty()) { for (JpaEntityManagerFactory testDataSource : lstDataSources) { wrappers.add(getDatabaseModule().getWrapper(testDataSource.databaseName())); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy