001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.data.jpa.eclipselink; 017 018import static org.junit.Assert.assertEquals; 019import static org.junit.Assert.assertFalse; 020import static org.junit.Assert.assertNotNull; 021import static org.junit.Assert.assertTrue; 022 023import java.util.HashSet; 024import java.util.Map; 025import java.util.Set; 026 027import javax.persistence.Entity; 028import javax.persistence.EntityManager; 029import javax.persistence.EntityManagerFactory; 030import javax.persistence.FetchType; 031import javax.persistence.Id; 032import javax.persistence.ManyToOne; 033import javax.persistence.metamodel.EntityType; 034import javax.persistence.spi.PersistenceUnitInfo; 035import javax.persistence.spi.PersistenceUnitTransactionType; 036import javax.transaction.TransactionManager; 037 038import org.apache.commons.dbcp.BasicDataSource; 039import org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate; 040import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl; 041import org.eclipse.persistence.jpa.JpaEntityManager; 042import org.junit.After; 043import org.junit.Before; 044import org.junit.Test; 045import org.junit.runner.RunWith; 046import org.kuali.rice.core.api.config.property.ConfigContext; 047import org.kuali.rice.core.framework.config.property.SimpleConfig; 048import org.kuali.rice.core.framework.persistence.jta.Jta; 049import org.kuali.rice.krad.data.jpa.KradEntityManagerFactoryBean; 050import org.kuali.rice.krad.data.jpa.eclipselink.testentities.TestEntity; 051import org.mockito.Mock; 052import org.mockito.runners.MockitoJUnitRunner; 053import org.springframework.context.support.ClassPathXmlApplicationContext; 054import org.springframework.instrument.classloading.SimpleInstrumentableClassLoader; 055import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo; 056import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor; 057 058/** 059 * Tests the {@link KradEclipseLinkEntityManagerFactoryBean}. 060 * 061 * @author Kuali Rice Team (rice.collab@kuali.org) 062 */ 063@RunWith(MockitoJUnitRunner.class) 064public class KradEclipseLinkEntityManagerFactoryBeanTest { 065 066 @Mock TransactionManager transactionManager; 067 @Mock javax.transaction.UserTransaction userTransaction; 068 069 private ClassPathXmlApplicationContext context; 070 private EntityManagerFactory entityManagerFactory; 071 072 @Before 073 public void setUp() throws Exception { 074 initializeConfig(); 075 } 076 077 @After 078 public void tearDown() throws Exception { 079 if (context != null) { 080 context.destroy(); 081 } 082 ConfigContext.destroy(); 083 } 084 085 private void initializeConfig() { 086 SimpleConfig config = new SimpleConfig(); 087 config.putProperty("rice.krad.jpa.global.randomProperty", "randomValue"); 088 config.putProperty("rice.krad.jpa.global.eclipselink.weaving", "false"); 089 ConfigContext.init(config); 090 } 091 092 private void loadContext(String springXmlFile) throws Exception { 093 this.context = new ClassPathXmlApplicationContext(springXmlFile, getClass()); 094 Map<String, EntityManagerFactory> factories = context.getBeansOfType(EntityManagerFactory.class); 095 assertEquals(1, factories.size()); 096 this.entityManagerFactory = factories.values().iterator().next(); 097 } 098 099 @Test 100 public void testMinimal() throws Exception { 101 loadContext(getClass().getSimpleName() + "_Minimal.xml"); 102 103 Set<EntityType<?>> minimalEntities = entityManagerFactory.getMetamodel().getEntities(); 104 // there should be only the ConverterHolder which is loaded by default 105 assertEquals(0, minimalEntities.size()); 106 107 // create the entity manager to verify that it works 108 EntityManager entityManager = entityManagerFactory.createEntityManager(); 109 // assertFalse(entityManager.contains(new ConverterHolder())); 110 entityManager.close(); 111 112 assertFalse(isJtaEnabled()); 113 } 114 115 @Test 116 public void testFull() throws Exception { 117 loadContext(getClass().getSimpleName() + "_Full.xml"); 118 119 Set<EntityType<?>> fullEntities = entityManagerFactory.getMetamodel().getEntities(); 120 assertEquals(5, fullEntities.size()); 121 Set<Class<?>> entityClasses = new HashSet<Class<?>>(); 122 for (EntityType<?> entityType : fullEntities) { 123 entityClasses.add(entityType.getJavaType()); 124 } 125 126 assertTrue(entityClasses.contains(TestEntity.class)); 127 assertTrue(entityClasses.contains(TestEntity1.class)); 128 assertTrue(entityClasses.contains(TestEntity2.class)); 129 assertTrue(entityClasses.contains(TestEntity3.class)); 130 assertTrue(entityClasses.contains(TestEntity4.class)); 131 132 assertFalse(isJtaEnabled()); 133 } 134 135 @Test 136 public void testJta() throws Exception { 137 Jta.configure(transactionManager, userTransaction); 138 try { 139 loadContext(getClass().getSimpleName() + "_Jta.xml"); 140 assertTrue("JTA should be enabled.", isJtaEnabled()); 141 } finally { 142 Jta.reset(); 143 } 144 } 145 146 @Test 147 public void testLoadTimeWeaving() throws Exception { 148 loadContext(getClass().getSimpleName() + "_LoadTimeWeaving.xml"); 149 EntityManagerFactoryDelegate delegate = 150 entityManagerFactory.unwrap(EntityManagerFactoryDelegate.class); 151 PersistenceUnitInfo info = delegate.getSetupImpl().getPersistenceUnitInfo(); 152 assertTrue(info.getClassLoader() instanceof SimpleInstrumentableClassLoader); 153 } 154 155 /** 156 * Verifies that it's not permitted to configure with both a JTA and Non-JTA datasource. 157 */ 158 @Test(expected = IllegalStateException.class) 159 public void testInvalidDataSourceConfiguration() throws Exception { 160 // kind of a random addition to throw the superclass in here, but allows me to get some 161 // coverage on some of the other methods from the superclass without having to write a separate test 162 KradEntityManagerFactoryBean factoryBean = 163 new KradEntityManagerFactoryBean(); 164 factoryBean.setDataSource(new BasicDataSource()); 165 factoryBean.setJtaDataSource(new BasicDataSource()); 166 factoryBean.afterPropertiesSet(); 167 } 168 169 @Test 170 public void testGetDataSource() throws Exception { 171 KradEclipseLinkEntityManagerFactoryBean factoryBean = 172 new KradEclipseLinkEntityManagerFactoryBean(); 173 174 BasicDataSource dataSourceNonJta = new BasicDataSource(); 175 factoryBean.setDataSource(dataSourceNonJta); 176 assertEquals(dataSourceNonJta, factoryBean.getDataSource()); 177 178 BasicDataSource dataSourceJta = new BasicDataSource(); 179 factoryBean.setJtaDataSource(dataSourceJta); 180 assertEquals(dataSourceJta, factoryBean.getDataSource()); 181 } 182 183 /** 184 * Just tests some of the getters to ensure they are delegating down to the internal factory bean and the 185 * PersistenceUnitManager appropriately. 186 */ 187 @Test 188 public void testVariousGetters() throws Exception { 189 loadContext(getClass().getSimpleName() + "_LoadTimeWeaving.xml"); 190 KradEclipseLinkEntityManagerFactoryBean factoryBean = 191 context.getBean(KradEclipseLinkEntityManagerFactoryBean.class); 192 assertNotNull(factoryBean); 193 194 assertEquals(2, factoryBean.getPersistenceUnitPostProcessors().length); 195 EntityManagerFactory entityManagerFactory = factoryBean.getNativeEntityManagerFactory(); 196 assertTrue(entityManagerFactory instanceof EntityManagerFactoryImpl); 197 assertEquals(factoryBean.getBeanClassLoader(), getClass().getClassLoader()); 198 assertEquals(JpaEntityManager.class, factoryBean.getEntityManagerInterface()); 199 200 } 201 202 private boolean isJtaEnabled() throws Exception { 203 EntityManagerFactoryDelegate delegate = 204 entityManagerFactory.unwrap(EntityManagerFactoryDelegate.class); 205 PersistenceUnitInfo info = delegate.getSetupImpl().getPersistenceUnitInfo(); 206 return info.getJtaDataSource() != null && info.getTransactionType() == PersistenceUnitTransactionType.JTA; 207 } 208 209 public static final class TestPersistenceUnitPostProcessor implements PersistenceUnitPostProcessor { 210 @Override 211 public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) { 212 pui.getManagedClassNames().add(TestEntity3.class.getName()); 213 } 214 } 215 216 @Entity 217 public static final class TestEntity1 { 218 @Id 219 private String id; 220 } 221 222 @Entity 223 public static final class TestEntity2 { 224 @Id 225 private String id; 226 } 227 228 @Entity 229 public static final class TestEntity3 { 230 @Id 231 private String id; 232 } 233 234 public static final class TestEntity4 { 235 private String id; 236 } 237 238 @Entity 239 public static final class TestEntity5 { 240 @Id 241 private String id; 242 243 @ManyToOne(fetch = FetchType.LAZY) 244 private TestEntity3 testEntity3; 245 246 } 247 248 249}