View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community 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
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
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.
15   */
16  package org.kuali.rice.krad.data.jpa.eclipselink;
17  
18  import static org.junit.Assert.assertEquals;
19  import static org.junit.Assert.assertFalse;
20  import static org.junit.Assert.assertNotNull;
21  import static org.junit.Assert.assertTrue;
22  
23  import java.util.HashSet;
24  import java.util.Map;
25  import java.util.Set;
26  
27  import javax.persistence.Entity;
28  import javax.persistence.EntityManager;
29  import javax.persistence.EntityManagerFactory;
30  import javax.persistence.FetchType;
31  import javax.persistence.Id;
32  import javax.persistence.ManyToOne;
33  import javax.persistence.metamodel.EntityType;
34  import javax.persistence.spi.PersistenceUnitInfo;
35  import javax.persistence.spi.PersistenceUnitTransactionType;
36  import javax.transaction.TransactionManager;
37  
38  import org.apache.commons.dbcp.BasicDataSource;
39  import org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate;
40  import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl;
41  import org.eclipse.persistence.jpa.JpaEntityManager;
42  import org.junit.After;
43  import org.junit.Before;
44  import org.junit.Test;
45  import org.junit.runner.RunWith;
46  import org.kuali.rice.core.api.config.property.ConfigContext;
47  import org.kuali.rice.core.framework.config.property.SimpleConfig;
48  import org.kuali.rice.core.framework.persistence.jta.Jta;
49  import org.kuali.rice.krad.data.jpa.KradEntityManagerFactoryBean;
50  import org.kuali.rice.krad.data.jpa.eclipselink.testentities.TestEntity;
51  import org.mockito.Mock;
52  import org.mockito.runners.MockitoJUnitRunner;
53  import org.springframework.context.support.ClassPathXmlApplicationContext;
54  import org.springframework.instrument.classloading.SimpleInstrumentableClassLoader;
55  import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
56  import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
57  
58  /**
59   * Tests the {@link KradEclipseLinkEntityManagerFactoryBean}.
60   *
61   * @author Kuali Rice Team (rice.collab@kuali.org)
62   */
63  @RunWith(MockitoJUnitRunner.class)
64  public class KradEclipseLinkEntityManagerFactoryBeanTest {
65  
66      @Mock TransactionManager transactionManager;
67      @Mock javax.transaction.UserTransaction userTransaction;
68  
69      private ClassPathXmlApplicationContext context;
70      private EntityManagerFactory entityManagerFactory;
71  
72      @Before
73      public void setUp() throws Exception {
74          initializeConfig();
75      }
76  
77      @After
78      public void tearDown() throws Exception {
79          if (context != null) {
80              context.destroy();
81          }
82          ConfigContext.destroy();
83      }
84  
85      private void initializeConfig() {
86          SimpleConfig config = new SimpleConfig();
87          config.putProperty("rice.krad.jpa.global.randomProperty", "randomValue");
88          config.putProperty("rice.krad.jpa.global.eclipselink.weaving", "false");
89          ConfigContext.init(config);
90      }
91  
92      private void loadContext(String springXmlFile) throws Exception {
93          this.context = new ClassPathXmlApplicationContext(springXmlFile, getClass());
94          Map<String, EntityManagerFactory> factories =  context.getBeansOfType(EntityManagerFactory.class);
95          assertEquals(1, factories.size());
96          this.entityManagerFactory = factories.values().iterator().next();
97      }
98  
99      @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 }