/* * Copyright 2002-2016 the original author or authors. * * 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.springframework.orm.jpa.support; import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; import java.util.Properties; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContextType; import javax.persistence.PersistenceProperty; import javax.persistence.PersistenceUnit; import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.support.GenericApplicationContext; import org.springframework.orm.jpa.AbstractEntityManagerFactoryBeanTests; import org.springframework.orm.jpa.DefaultJpaDialect; import org.springframework.orm.jpa.EntityManagerFactoryInfo; import org.springframework.orm.jpa.EntityManagerHolder; import org.springframework.stereotype.Repository; import org.springframework.tests.context.SimpleMapScope; import org.springframework.tests.mock.jndi.ExpectedLookupTemplate; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.SerializationTestUtils; import static org.junit.Assert.*; import static org.mockito.BDDMockito.*; /** * Unit tests for persistence context and persistence unit injection. * * @author Rod Johnson * @author Juergen Hoeller * @author Phillip Webb */ @SuppressWarnings("resource") public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanTests { @Test public void testPrivatePersistenceContextField() throws Exception { mockEmf = mock(EntityManagerFactory.class, withSettings().serializable()); GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); gac.registerBeanDefinition(DefaultPrivatePersistenceContextField.class.getName(), new RootBeanDefinition(DefaultPrivatePersistenceContextField.class)); gac.registerBeanDefinition(FactoryBeanWithPersistenceContextField.class.getName(), new RootBeanDefinition(FactoryBeanWithPersistenceContextField.class)); gac.refresh(); DefaultPrivatePersistenceContextField bean = (DefaultPrivatePersistenceContextField) gac.getBean( DefaultPrivatePersistenceContextField.class.getName()); FactoryBeanWithPersistenceContextField bean2 = (FactoryBeanWithPersistenceContextField) gac.getBean( "&" + FactoryBeanWithPersistenceContextField.class.getName()); assertNotNull(bean.em); assertNotNull(bean2.em); assertNotNull(SerializationTestUtils.serializeAndDeserialize(bean.em)); assertNotNull(SerializationTestUtils.serializeAndDeserialize(bean2.em)); } @Test public void testPrivateVendorSpecificPersistenceContextField() { GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); gac.registerBeanDefinition(DefaultVendorSpecificPrivatePersistenceContextField.class.getName(), new RootBeanDefinition(DefaultVendorSpecificPrivatePersistenceContextField.class)); gac.refresh(); DefaultVendorSpecificPrivatePersistenceContextField bean = (DefaultVendorSpecificPrivatePersistenceContextField) gac.getBean(DefaultVendorSpecificPrivatePersistenceContextField.class.getName()); assertNotNull(bean.em); } @Test public void testPublicExtendedPersistenceContextSetter() throws Exception { EntityManager mockEm = mock(EntityManager.class); given(mockEmf.createEntityManager()).willReturn(mockEm); GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); gac.registerBeanDefinition(DefaultPublicPersistenceContextSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceContextSetter.class)); gac.refresh(); DefaultPublicPersistenceContextSetter bean = (DefaultPublicPersistenceContextSetter) gac.getBean( DefaultPublicPersistenceContextSetter.class.getName()); assertNotNull(bean.em); } @Test public void testPublicSpecificExtendedPersistenceContextSetter() throws Exception { EntityManagerFactory mockEmf2 = mock(EntityManagerFactory.class); EntityManager mockEm2 = mock(EntityManager.class); given(mockEmf2.createEntityManager()).willReturn(mockEm2); GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.getDefaultListableBeanFactory().registerSingleton("unit2", mockEmf2); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); gac.registerBeanDefinition(SpecificPublicPersistenceContextSetter.class.getName(), new RootBeanDefinition(SpecificPublicPersistenceContextSetter.class)); gac.refresh(); SpecificPublicPersistenceContextSetter bean = (SpecificPublicPersistenceContextSetter) gac.getBean( SpecificPublicPersistenceContextSetter.class.getName()); assertNotNull(bean.getEntityManager()); bean.getEntityManager().flush(); verify(mockEm2).getTransaction(); verify(mockEm2).flush(); } @Test public void testInjectionIntoExistingObjects() { EntityManager mockEm = mock(EntityManager.class); given(mockEmf.createEntityManager()).willReturn(mockEm); GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); gac.refresh(); DefaultPrivatePersistenceContextField existingBean1 = new DefaultPrivatePersistenceContextField(); gac.getAutowireCapableBeanFactory().autowireBean(existingBean1); assertNotNull(existingBean1.em); DefaultPublicPersistenceContextSetter existingBean2 = new DefaultPublicPersistenceContextSetter(); gac.getAutowireCapableBeanFactory().autowireBean(existingBean2); assertNotNull(existingBean2.em); } @Test public void testPublicExtendedPersistenceContextSetterWithSerialization() throws Exception { DummyInvocationHandler ih = new DummyInvocationHandler(); Object mockEm = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {EntityManager.class}, ih); given(mockEmf.createEntityManager()).willReturn((EntityManager) mockEm); GenericApplicationContext gac = new GenericApplicationContext(); SimpleMapScope myScope = new SimpleMapScope(); gac.getDefaultListableBeanFactory().registerScope("myScope", myScope); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); RootBeanDefinition bd = new RootBeanDefinition(DefaultPublicPersistenceContextSetter.class); bd.setScope("myScope"); gac.registerBeanDefinition(DefaultPublicPersistenceContextSetter.class.getName(), bd); gac.refresh(); DefaultPublicPersistenceContextSetter bean = (DefaultPublicPersistenceContextSetter) gac.getBean( DefaultPublicPersistenceContextSetter.class.getName()); assertNotNull(bean.em); assertNotNull(SerializationTestUtils.serializeAndDeserialize(bean.em)); SimpleMapScope serialized = (SimpleMapScope) SerializationTestUtils.serializeAndDeserialize(myScope); serialized.close(); assertTrue(DummyInvocationHandler.closed); DummyInvocationHandler.closed = false; } @Test @SuppressWarnings({ "unchecked", "rawtypes" }) public void testPublicExtendedPersistenceContextSetterWithEntityManagerInfoAndSerialization() throws Exception { EntityManager mockEm = mock(EntityManager.class, withSettings().serializable()); given(mockEm.isOpen()).willReturn(true); EntityManagerFactoryWithInfo mockEmf = mock(EntityManagerFactoryWithInfo.class); given(mockEmf.getNativeEntityManagerFactory()).willReturn(mockEmf); given(mockEmf.getJpaDialect()).willReturn(new DefaultJpaDialect()); given(mockEmf.getEntityManagerInterface()).willReturn((Class)EntityManager.class); given(mockEmf.getBeanClassLoader()).willReturn(getClass().getClassLoader()); given(mockEmf.createEntityManager()).willReturn(mockEm); GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); gac.registerBeanDefinition(DefaultPublicPersistenceContextSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceContextSetter.class)); gac.refresh(); DefaultPublicPersistenceContextSetter bean = (DefaultPublicPersistenceContextSetter) gac.getBean( DefaultPublicPersistenceContextSetter.class.getName()); assertNotNull(bean.em); assertNotNull(SerializationTestUtils.serializeAndDeserialize(bean.em)); } @Test public void testPublicExtendedPersistenceContextSetterWithOverriding() { EntityManager mockEm2 = mock(EntityManager.class); GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); RootBeanDefinition bd = new RootBeanDefinition(DefaultPublicPersistenceContextSetter.class); bd.getPropertyValues().add("entityManager", mockEm2); gac.registerBeanDefinition(DefaultPublicPersistenceContextSetter.class.getName(), bd); gac.refresh(); DefaultPublicPersistenceContextSetter bean = (DefaultPublicPersistenceContextSetter) gac.getBean( DefaultPublicPersistenceContextSetter.class.getName()); assertSame(mockEm2, bean.em); } @Test public void testPrivatePersistenceUnitField() { GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); gac.registerBeanDefinition(DefaultPrivatePersistenceUnitField.class.getName(), new RootBeanDefinition(DefaultPrivatePersistenceUnitField.class)); gac.refresh(); DefaultPrivatePersistenceUnitField bean = (DefaultPrivatePersistenceUnitField) gac.getBean( DefaultPrivatePersistenceUnitField.class.getName()); assertSame(mockEmf, bean.emf); } @Test public void testPublicPersistenceUnitSetter() { GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); gac.registerBeanDefinition(DefaultPublicPersistenceUnitSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetter.class)); gac.refresh(); DefaultPublicPersistenceUnitSetter bean = (DefaultPublicPersistenceUnitSetter) gac.getBean( DefaultPublicPersistenceUnitSetter.class.getName()); assertSame(mockEmf, bean.emf); } @Test public void testPublicPersistenceUnitSetterWithOverriding() { EntityManagerFactory mockEmf2 = mock(EntityManagerFactory.class); GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.registerBeanDefinition("annotationProcessor", new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class)); RootBeanDefinition bd = new RootBeanDefinition(DefaultPublicPersistenceUnitSetter.class); bd.getPropertyValues().add("emf", mockEmf2); gac.registerBeanDefinition(DefaultPublicPersistenceUnitSetter.class.getName(), bd); gac.refresh(); DefaultPublicPersistenceUnitSetter bean = (DefaultPublicPersistenceUnitSetter) gac.getBean( DefaultPublicPersistenceUnitSetter.class.getName()); assertSame(mockEmf2, bean.emf); } @Test public void testPublicPersistenceUnitSetterWithUnitIdentifiedThroughBeanName() { EntityManagerFactory mockEmf2 = mock(EntityManagerFactory.class); GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory2", mockEmf2); gac.registerAlias("entityManagerFactory2", "Person"); RootBeanDefinition processorDef = new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class); processorDef.getPropertyValues().add("defaultPersistenceUnitName", "entityManagerFactory"); gac.registerBeanDefinition("annotationProcessor", processorDef); gac.registerBeanDefinition(DefaultPublicPersistenceUnitSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetter.class)); gac.registerBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class)); gac.refresh(); DefaultPublicPersistenceUnitSetter bean = (DefaultPublicPersistenceUnitSetter) gac.getBean(DefaultPublicPersistenceUnitSetter.class.getName()); DefaultPublicPersistenceUnitSetterNamedPerson bean2 = (DefaultPublicPersistenceUnitSetterNamedPerson) gac.getBean(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName()); assertSame(mockEmf, bean.emf); assertSame(mockEmf2, bean2.emf); } @Test public void testPublicPersistenceUnitSetterWithMultipleUnitsIdentifiedThroughUnitName() { EntityManagerFactoryWithInfo mockEmf2 = mock(EntityManagerFactoryWithInfo.class); given(mockEmf2.getPersistenceUnitName()).willReturn("Person"); GenericApplicationContext gac = new GenericApplicationContext(); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory", mockEmf); gac.getDefaultListableBeanFactory().registerSingleton("entityManagerFactory2", mockEmf2); RootBeanDefinition processorDef = new RootBeanDefinition(PersistenceAnnotationBeanPostProcessor.class); processorDef.getPropertyValues().add("defaultPersistenceUnitName", "entityManagerFactory"); gac.registerBeanDefinition("annotationProcessor", processorDef); gac.registerBeanDefinition(DefaultPublicPersistenceUnitSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetter.class)); gac.registerBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class)); gac.refresh(); DefaultPublicPersistenceUnitSetter bean = (DefaultPublicPersistenceUnitSetter) gac.getBean(DefaultPublicPersistenceUnitSetter.class.getName()); DefaultPublicPersistenceUnitSetterNamedPerson bean2 = (DefaultPublicPersistenceUnitSetterNamedPerson) gac.getBean(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName()); assertSame(mockEmf, bean.emf); assertSame(mockEmf2, bean2.emf); } @Test @Ignore public void testPersistenceUnitsFromJndi() { EntityManager mockEm = mock(EntityManager.class); given(mockEmf.createEntityManager()).willReturn(mockEm); EntityManagerFactoryWithInfo mockEmf2 = mock(EntityManagerFactoryWithInfo.class); Map<String, String> persistenceUnits = new HashMap<>(); persistenceUnits.put("", "pu1"); persistenceUnits.put("Person", "pu2"); ExpectedLookupTemplate jt = new ExpectedLookupTemplate(); jt.addObject("java:comp/env/pu1", mockEmf); jt.addObject("java:comp/env/pu2", mockEmf2); DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); PersistenceAnnotationBeanPostProcessor bpp = new PersistenceAnnotationBeanPostProcessor(); bpp.setPersistenceUnits(persistenceUnits); bpp.setJndiTemplate(jt); bf.addBeanPostProcessor(bpp); bf.registerBeanDefinition(DefaultPublicPersistenceUnitSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetter.class)); bf.registerBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class)); bf.registerBeanDefinition(DefaultPrivatePersistenceContextField.class.getName(), new RootBeanDefinition(DefaultPrivatePersistenceContextField.class)); bf.registerBeanDefinition(DefaultPublicPersistenceContextSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceContextSetter.class)); DefaultPublicPersistenceUnitSetter bean = (DefaultPublicPersistenceUnitSetter) bf.getBean(DefaultPublicPersistenceUnitSetter.class.getName()); DefaultPublicPersistenceUnitSetterNamedPerson bean2 = (DefaultPublicPersistenceUnitSetterNamedPerson) bf.getBean(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName()); DefaultPrivatePersistenceContextField bean3 = (DefaultPrivatePersistenceContextField) bf.getBean(DefaultPrivatePersistenceContextField.class.getName()); DefaultPublicPersistenceContextSetter bean4 = (DefaultPublicPersistenceContextSetter) bf.getBean(DefaultPublicPersistenceContextSetter.class.getName()); assertSame(mockEmf, bean.emf); assertSame(mockEmf2, bean2.emf); assertNotNull(bean3.em); assertNotNull(bean4.em); } @Test public void testPersistenceUnitsFromJndiWithDefaultUnit() { EntityManagerFactoryWithInfo mockEmf2 = mock(EntityManagerFactoryWithInfo.class); Map<String, String> persistenceUnits = new HashMap<>(); persistenceUnits.put("System", "pu1"); persistenceUnits.put("Person", "pu2"); ExpectedLookupTemplate jt = new ExpectedLookupTemplate(); jt.addObject("java:comp/env/pu1", mockEmf); jt.addObject("java:comp/env/pu2", mockEmf2); DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); PersistenceAnnotationBeanPostProcessor bpp = new PersistenceAnnotationBeanPostProcessor(); bpp.setPersistenceUnits(persistenceUnits); bpp.setDefaultPersistenceUnitName("System"); bpp.setJndiTemplate(jt); bf.addBeanPostProcessor(bpp); bf.registerBeanDefinition(DefaultPublicPersistenceUnitSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetter.class)); bf.registerBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class)); DefaultPublicPersistenceUnitSetter bean = (DefaultPublicPersistenceUnitSetter) bf.getBean(DefaultPublicPersistenceUnitSetter.class.getName()); DefaultPublicPersistenceUnitSetterNamedPerson bean2 = (DefaultPublicPersistenceUnitSetterNamedPerson) bf.getBean(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName()); assertSame(mockEmf, bean.emf); assertSame(mockEmf2, bean2.emf); } @Test public void testSinglePersistenceUnitFromJndi() { Map<String, String> persistenceUnits = new HashMap<>(); persistenceUnits.put("Person", "pu1"); ExpectedLookupTemplate jt = new ExpectedLookupTemplate(); jt.addObject("java:comp/env/pu1", mockEmf); DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); PersistenceAnnotationBeanPostProcessor bpp = new PersistenceAnnotationBeanPostProcessor(); bpp.setPersistenceUnits(persistenceUnits); bpp.setJndiTemplate(jt); bf.addBeanPostProcessor(bpp); bf.registerBeanDefinition(DefaultPublicPersistenceUnitSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetter.class)); bf.registerBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceUnitSetterNamedPerson.class)); DefaultPublicPersistenceUnitSetter bean = (DefaultPublicPersistenceUnitSetter) bf.getBean(DefaultPublicPersistenceUnitSetter.class.getName()); DefaultPublicPersistenceUnitSetterNamedPerson bean2 = (DefaultPublicPersistenceUnitSetterNamedPerson) bf.getBean(DefaultPublicPersistenceUnitSetterNamedPerson.class.getName()); assertSame(mockEmf, bean.emf); assertSame(mockEmf, bean2.emf); } @Test public void testPersistenceContextsFromJndi() { EntityManager mockEm = mock(EntityManager.class); EntityManager mockEm2 = mock(EntityManager.class); EntityManager mockEm3 = mock(EntityManager.class); Map<String, String> persistenceContexts = new HashMap<>(); persistenceContexts.put("", "pc1"); persistenceContexts.put("Person", "pc2"); Map<String, String> extendedPersistenceContexts = new HashMap<>(); extendedPersistenceContexts .put("", "pc3"); ExpectedLookupTemplate jt = new ExpectedLookupTemplate(); jt.addObject("java:comp/env/pc1", mockEm); jt.addObject("java:comp/env/pc2", mockEm2); jt.addObject("java:comp/env/pc3", mockEm3); DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); PersistenceAnnotationBeanPostProcessor bpp = new PersistenceAnnotationBeanPostProcessor(); bpp.setPersistenceContexts(persistenceContexts); bpp.setExtendedPersistenceContexts(extendedPersistenceContexts); bpp.setJndiTemplate(jt); bf.addBeanPostProcessor(bpp); bf.registerBeanDefinition(DefaultPrivatePersistenceContextField.class.getName(), new RootBeanDefinition(DefaultPrivatePersistenceContextField.class)); bf.registerBeanDefinition(DefaultPrivatePersistenceContextFieldNamedPerson.class.getName(), new RootBeanDefinition(DefaultPrivatePersistenceContextFieldNamedPerson.class)); bf.registerBeanDefinition(DefaultPublicPersistenceContextSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceContextSetter.class)); DefaultPrivatePersistenceContextField bean1 = (DefaultPrivatePersistenceContextField) bf.getBean(DefaultPrivatePersistenceContextField.class.getName()); DefaultPrivatePersistenceContextFieldNamedPerson bean2 = (DefaultPrivatePersistenceContextFieldNamedPerson) bf.getBean(DefaultPrivatePersistenceContextFieldNamedPerson.class.getName()); DefaultPublicPersistenceContextSetter bean3 = (DefaultPublicPersistenceContextSetter) bf.getBean(DefaultPublicPersistenceContextSetter.class.getName()); assertSame(mockEm, bean1.em); assertSame(mockEm2, bean2.em); assertSame(mockEm3, bean3.em); } @Test public void testPersistenceContextsFromJndiWithDefaultUnit() { EntityManager mockEm = mock(EntityManager.class); EntityManager mockEm2 = mock(EntityManager.class); EntityManager mockEm3 = mock(EntityManager.class); Map<String, String> persistenceContexts = new HashMap<>(); persistenceContexts.put("System", "pc1"); persistenceContexts.put("Person", "pc2"); Map<String, String> extendedPersistenceContexts = new HashMap<>(); extendedPersistenceContexts .put("System", "pc3"); ExpectedLookupTemplate jt = new ExpectedLookupTemplate(); jt.addObject("java:comp/env/pc1", mockEm); jt.addObject("java:comp/env/pc2", mockEm2); jt.addObject("java:comp/env/pc3", mockEm3); DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); PersistenceAnnotationBeanPostProcessor bpp = new PersistenceAnnotationBeanPostProcessor(); bpp.setPersistenceContexts(persistenceContexts); bpp.setExtendedPersistenceContexts(extendedPersistenceContexts); bpp.setDefaultPersistenceUnitName("System"); bpp.setJndiTemplate(jt); bf.addBeanPostProcessor(bpp); bf.registerBeanDefinition(DefaultPrivatePersistenceContextField.class.getName(), new RootBeanDefinition(DefaultPrivatePersistenceContextField.class)); bf.registerBeanDefinition(DefaultPrivatePersistenceContextFieldNamedPerson.class.getName(), new RootBeanDefinition(DefaultPrivatePersistenceContextFieldNamedPerson.class)); bf.registerBeanDefinition(DefaultPublicPersistenceContextSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceContextSetter.class)); DefaultPrivatePersistenceContextField bean1 = (DefaultPrivatePersistenceContextField) bf.getBean(DefaultPrivatePersistenceContextField.class.getName()); DefaultPrivatePersistenceContextFieldNamedPerson bean2 = (DefaultPrivatePersistenceContextFieldNamedPerson) bf.getBean(DefaultPrivatePersistenceContextFieldNamedPerson.class.getName()); DefaultPublicPersistenceContextSetter bean3 = (DefaultPublicPersistenceContextSetter) bf.getBean(DefaultPublicPersistenceContextSetter.class.getName()); assertSame(mockEm, bean1.em); assertSame(mockEm2, bean2.em); assertSame(mockEm3, bean3.em); } @Test public void testSinglePersistenceContextFromJndi() { EntityManager mockEm = mock(EntityManager.class); EntityManager mockEm2 = mock(EntityManager.class); Map<String, String> persistenceContexts = new HashMap<>(); persistenceContexts.put("System", "pc1"); Map<String, String> extendedPersistenceContexts = new HashMap<>(); extendedPersistenceContexts .put("System", "pc2"); ExpectedLookupTemplate jt = new ExpectedLookupTemplate(); jt.addObject("java:comp/env/pc1", mockEm); jt.addObject("java:comp/env/pc2", mockEm2); DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); PersistenceAnnotationBeanPostProcessor bpp = new PersistenceAnnotationBeanPostProcessor(); bpp.setPersistenceContexts(persistenceContexts); bpp.setExtendedPersistenceContexts(extendedPersistenceContexts); bpp.setJndiTemplate(jt); bf.addBeanPostProcessor(bpp); bf.registerBeanDefinition(DefaultPrivatePersistenceContextField.class.getName(), new RootBeanDefinition(DefaultPrivatePersistenceContextField.class)); bf.registerBeanDefinition(DefaultPublicPersistenceContextSetter.class.getName(), new RootBeanDefinition(DefaultPublicPersistenceContextSetter.class)); DefaultPrivatePersistenceContextField bean1 = (DefaultPrivatePersistenceContextField) bf.getBean(DefaultPrivatePersistenceContextField.class.getName()); DefaultPublicPersistenceContextSetter bean2 = (DefaultPublicPersistenceContextSetter) bf.getBean(DefaultPublicPersistenceContextSetter.class.getName()); assertSame(mockEm, bean1.em); assertSame(mockEm2, bean2.em); } @Test public void testFieldOfWrongTypeAnnotatedWithPersistenceUnit() { PersistenceAnnotationBeanPostProcessor pabpp = new PersistenceAnnotationBeanPostProcessor(); try { pabpp.postProcessPropertyValues(null, null, new FieldOfWrongTypeAnnotatedWithPersistenceUnit(), "bean"); fail("Can't inject this field"); } catch (IllegalStateException ex) { // Ok } } @Test public void testSetterOfWrongTypeAnnotatedWithPersistenceUnit() { PersistenceAnnotationBeanPostProcessor pabpp = new PersistenceAnnotationBeanPostProcessor(); try { pabpp.postProcessPropertyValues(null, null, new SetterOfWrongTypeAnnotatedWithPersistenceUnit(), "bean"); fail("Can't inject this setter"); } catch (IllegalStateException ex) { // Ok } } @Test public void testSetterWithNoArgs() { PersistenceAnnotationBeanPostProcessor pabpp = new PersistenceAnnotationBeanPostProcessor(); try { pabpp.postProcessPropertyValues(null, null, new SetterWithNoArgs(), "bean"); fail("Can't inject this setter"); } catch (IllegalStateException ex) { // Ok } } @Test public void testNoPropertiesPassedIn() { EntityManager mockEm = mock(EntityManager.class); given(mockEmf.createEntityManager()).willReturn(mockEm); PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor(); DefaultPrivatePersistenceContextFieldExtended dppcf = new DefaultPrivatePersistenceContextFieldExtended(); pabpp.postProcessPropertyValues(null, null, dppcf, "bean"); assertNotNull(dppcf.em); } @Test public void testPropertiesPassedIn() { Properties props = new Properties(); props.put("foo", "bar"); EntityManager mockEm = mock(EntityManager.class); given(mockEmf.createEntityManager(props)).willReturn(mockEm); PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor(); DefaultPrivatePersistenceContextFieldExtendedWithProps dppcf = new DefaultPrivatePersistenceContextFieldExtendedWithProps(); pabpp.postProcessPropertyValues(null, null, dppcf, "bean"); assertNotNull(dppcf.em); } @Test public void testPropertiesForTransactionalEntityManager() { Properties props = new Properties(); props.put("foo", "bar"); EntityManager em = mock(EntityManager.class); given(mockEmf.createEntityManager(props)).willReturn(em); given(em.getDelegate()).willReturn(new Object()); given(em.isOpen()).willReturn(true); PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor(); DefaultPrivatePersistenceContextFieldWithProperties transactionalField = new DefaultPrivatePersistenceContextFieldWithProperties(); pabpp.postProcessPropertyValues(null, null, transactionalField, "bean"); assertNotNull(transactionalField.em); assertNotNull(transactionalField.em.getDelegate()); verify(em).close(); } /** * Binds an EMF to the thread and tests if EM with different properties * generate new EMs or not. */ @Test public void testPropertiesForSharedEntityManager1() { Properties props = new Properties(); props.put("foo", "bar"); EntityManager em = mock(EntityManager.class); // only one call made - the first EM definition wins (in this case the one w/ the properties) given(mockEmf.createEntityManager(props)).willReturn(em); given(em.getDelegate()).willReturn(new Object()); given(em.isOpen()).willReturn(true); PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor(); DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties = new DefaultPrivatePersistenceContextFieldWithProperties(); DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField(); pabpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, "bean1"); pabpp.postProcessPropertyValues(null, null, transactionalField, "bean2"); assertNotNull(transactionalFieldWithProperties.em); assertNotNull(transactionalField.em); // the EM w/ properties will be created assertNotNull(transactionalFieldWithProperties.em.getDelegate()); // bind em to the thread now since it's created try { TransactionSynchronizationManager.bindResource(mockEmf, new EntityManagerHolder(em)); assertNotNull(transactionalField.em.getDelegate()); verify(em).close(); } finally { TransactionSynchronizationManager.unbindResource(mockEmf); } } @Test public void testPropertiesForSharedEntityManager2() { Properties props = new Properties(); props.put("foo", "bar"); EntityManager em = mock(EntityManager.class); // only one call made - the first EM definition wins (in this case the one w/o the properties) given(mockEmf.createEntityManager()).willReturn(em); given(em.getDelegate()).willReturn(new Object(), 2); given(em.isOpen()).willReturn(true); PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor(); DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties = new DefaultPrivatePersistenceContextFieldWithProperties(); DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField(); pabpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, "bean1"); pabpp.postProcessPropertyValues(null, null, transactionalField, "bean2"); assertNotNull(transactionalFieldWithProperties.em); assertNotNull(transactionalField.em); // the EM w/o properties will be created assertNotNull(transactionalField.em.getDelegate()); // bind em to the thread now since it's created try { TransactionSynchronizationManager.bindResource(mockEmf, new EntityManagerHolder(em)); assertNotNull(transactionalFieldWithProperties.em.getDelegate()); verify(em).close(); } finally { TransactionSynchronizationManager.unbindResource(mockEmf); } } @SuppressWarnings("serial") private static class MockPersistenceAnnotationBeanPostProcessor extends PersistenceAnnotationBeanPostProcessor { @Override protected EntityManagerFactory findEntityManagerFactory(String emfName, String requestingBeanName) { return mockEmf; } } public static class DefaultPrivatePersistenceContextField { @PersistenceContext private EntityManager em; } public static class DefaultVendorSpecificPrivatePersistenceContextField { @PersistenceContext @SuppressWarnings("deprecation") private org.hibernate.ejb.HibernateEntityManager em; } @SuppressWarnings("rawtypes") public static class FactoryBeanWithPersistenceContextField implements FactoryBean { @PersistenceContext private EntityManager em; @Override public Object getObject() throws Exception { return null; } @Override public Class getObjectType() { return null; } @Override public boolean isSingleton() { return true; } } public static class DefaultPrivatePersistenceContextFieldNamedPerson { @PersistenceContext(unitName = "Person") private EntityManager em; } public static class DefaultPrivatePersistenceContextFieldWithProperties { @PersistenceContext(properties = { @PersistenceProperty(name = "foo", value = "bar") }) private EntityManager em; } @Repository @SuppressWarnings("serial") public static class DefaultPublicPersistenceContextSetter implements Serializable { private EntityManager em; @PersistenceContext(type = PersistenceContextType.EXTENDED) public void setEntityManager(EntityManager em) { if (this.em != null) { throw new IllegalStateException("Already called"); } this.em = em; } public EntityManager getEntityManager() { return em; } } @SuppressWarnings("serial") static class PublicPersistenceContextSetterOnNonPublicClass extends DefaultPublicPersistenceContextSetter { @Override @PersistenceContext(unitName="unit2", type = PersistenceContextType.EXTENDED) public void setEntityManager(EntityManager em) { super.setEntityManager(em); } } @SuppressWarnings("serial") public static class SpecificPublicPersistenceContextSetter extends PublicPersistenceContextSetterOnNonPublicClass { } public static class DefaultPrivatePersistenceUnitField { @PersistenceUnit private EntityManagerFactory emf; } public static class DefaultPublicPersistenceUnitSetter { private EntityManagerFactory emf; @PersistenceUnit public void setEmf(EntityManagerFactory emf) { if (this.emf != null) { throw new IllegalStateException("Already called"); } this.emf = emf; } public EntityManagerFactory getEmf() { return emf; } } @Repository public static class DefaultPublicPersistenceUnitSetterNamedPerson { private EntityManagerFactory emf; @PersistenceUnit(unitName = "Person") public void setEmf(EntityManagerFactory emf) { this.emf = emf; } public EntityManagerFactory getEntityManagerFactory() { return emf; } } public static class FieldOfWrongTypeAnnotatedWithPersistenceUnit { @PersistenceUnit public String thisFieldIsOfTheWrongType; } public static class SetterOfWrongTypeAnnotatedWithPersistenceUnit { @PersistenceUnit @SuppressWarnings("rawtypes") public void setSomething(Comparable c) { } } public static class SetterWithNoArgs { @PersistenceUnit public void setSomething() { } } public static class DefaultPrivatePersistenceContextFieldExtended { @PersistenceContext(type = PersistenceContextType.EXTENDED) private EntityManager em; } public static class DefaultPrivatePersistenceContextFieldExtendedWithProps { @PersistenceContext(type = PersistenceContextType.EXTENDED, properties = { @PersistenceProperty(name = "foo", value = "bar") }) private EntityManager em; } private interface EntityManagerFactoryWithInfo extends EntityManagerFactory, EntityManagerFactoryInfo { } @SuppressWarnings("serial") private static class DummyInvocationHandler implements InvocationHandler, Serializable { public static boolean closed; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("isOpen".equals(method.getName())) { return true; } if ("close".equals(method.getName())) { closed = true; return null; } if ("toString".equals(method.getName())) { return ""; } throw new IllegalStateException(); } } }