/* * Copyright 2002-2008 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; import java.util.Map; import java.util.Properties; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.OptimisticLockException; import javax.persistence.PersistenceException; import javax.persistence.spi.PersistenceProvider; import javax.persistence.spi.PersistenceUnitInfo; import javax.persistence.spi.PersistenceUnitTransactionType; import org.easymock.MockControl; import org.springframework.dao.DataAccessException; import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver; import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.interceptor.DefaultTransactionAttribute; /** * @author Rod Johnson * @author Juergen Hoeller */ public class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerFactoryBeanTests { // Static fields set by inner class DummyPersistenceProvider private static Map actualProps; private static PersistenceUnitInfo actualPui; public void testValidPersistenceUnit() throws Exception { parseValidPersistenceUnit(); } public void testExceptionTranslationWithNoDialect() throws Exception { LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit(); EntityManagerFactory emf = cefb.getObject(); assertNull("No dialect set", cefb.getJpaDialect()); RuntimeException in1 = new RuntimeException("in1"); PersistenceException in2 = new PersistenceException(); assertNull("No translation here", cefb.translateExceptionIfPossible(in1)); DataAccessException dex = cefb.translateExceptionIfPossible(in2); assertNotNull(dex); assertSame(in2, dex.getCause()); } public void testEntityManagerFactoryIsProxied() throws Exception { LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit(); EntityManagerFactory emf = cefb.getObject(); assertSame("EntityManagerFactory reference must be cached after init", emf, cefb.getObject()); assertNotSame("EMF must be proxied", mockEmf, emf); assertTrue(emf.equals(emf)); } public void testApplicationManagedEntityManagerWithoutTransaction() throws Exception { Object testEntity = new Object(); MockControl emMc = MockControl.createControl(EntityManager.class); EntityManager mockEm = (EntityManager) emMc.getMock(); mockEm.contains(testEntity); emMc.setReturnValue(false); emMc.replay(); // finish recording mock calls mockEmf.createEntityManager(); emfMc.setReturnValue(mockEm); mockEmf.close(); emfMc.setVoidCallable(); emfMc.replay(); LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit(); EntityManagerFactory emf = cefb.getObject(); assertSame("EntityManagerFactory reference must be cached after init", emf, cefb.getObject()); assertNotSame("EMF must be proxied", mockEmf, emf); EntityManager em = emf.createEntityManager(); assertFalse(em.contains(testEntity)); cefb.destroy(); emfMc.verify(); emMc.verify(); } public void testApplicationManagedEntityManagerWithTransaction() throws Exception { Object testEntity = new Object(); MockControl tmMc = MockControl.createControl(EntityTransaction.class); EntityTransaction mockTx = (EntityTransaction) tmMc.getMock(); mockTx.isActive(); tmMc.setReturnValue(false); mockTx.begin(); tmMc.setVoidCallable(); mockTx.commit(); tmMc.setVoidCallable(); tmMc.replay(); // This one's for the tx (shared) MockControl sharedEmMc = MockControl.createControl(EntityManager.class); EntityManager sharedEm = (EntityManager) sharedEmMc.getMock(); sharedEm.getTransaction(); sharedEmMc.setReturnValue(new NoOpEntityTransaction(), 3); sharedEm.close(); sharedEmMc.setVoidCallable(); sharedEmMc.replay(); mockEmf.createEntityManager(); emfMc.setReturnValue(sharedEm); // This is the application-specific one MockControl emMc = MockControl.createControl(EntityManager.class); EntityManager mockEm = (EntityManager) emMc.getMock(); mockEm.getTransaction(); emMc.setReturnValue(mockTx, 3); mockEm.contains(testEntity); emMc.setReturnValue(false); emMc.replay(); mockEmf.createEntityManager(); emfMc.setReturnValue(mockEm); mockEmf.close(); emfMc.setVoidCallable(); emfMc.replay(); LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit(); JpaTransactionManager jpatm = new JpaTransactionManager(); jpatm.setEntityManagerFactory(cefb.getObject()); TransactionStatus txStatus = jpatm.getTransaction(new DefaultTransactionAttribute()); EntityManagerFactory emf = cefb.getObject(); assertSame("EntityManagerFactory reference must be cached after init", emf, cefb.getObject()); assertNotSame("EMF must be proxied", mockEmf, emf); EntityManager em = emf.createEntityManager(); em.joinTransaction(); assertFalse(em.contains(testEntity)); jpatm.commit(txStatus); cefb.destroy(); emfMc.verify(); emMc.verify(); tmMc.verify(); } public void testApplicationManagedEntityManagerWithTransactionAndCommitException() throws Exception { Object testEntity = new Object(); MockControl tmMc = MockControl.createControl(EntityTransaction.class); EntityTransaction mockTx = (EntityTransaction) tmMc.getMock(); mockTx.isActive(); tmMc.setReturnValue(false); mockTx.begin(); tmMc.setVoidCallable(); mockTx.commit(); tmMc.setThrowable(new OptimisticLockException()); tmMc.replay(); // This one's for the tx (shared) MockControl sharedEmMc = MockControl.createControl(EntityManager.class); EntityManager sharedEm = (EntityManager) sharedEmMc.getMock(); sharedEm.getTransaction(); sharedEmMc.setReturnValue(new NoOpEntityTransaction(), 3); sharedEm.close(); sharedEmMc.setVoidCallable(); sharedEmMc.replay(); mockEmf.createEntityManager(); emfMc.setReturnValue(sharedEm); // This is the application-specific one MockControl emMc = MockControl.createControl(EntityManager.class); EntityManager mockEm = (EntityManager) emMc.getMock(); mockEm.getTransaction(); emMc.setReturnValue(mockTx, 3); mockEm.contains(testEntity); emMc.setReturnValue(false); emMc.replay(); mockEmf.createEntityManager(); emfMc.setReturnValue(mockEm); mockEmf.close(); emfMc.setVoidCallable(); emfMc.replay(); LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit(); JpaTransactionManager jpatm = new JpaTransactionManager(); jpatm.setEntityManagerFactory(cefb.getObject()); TransactionStatus txStatus = jpatm.getTransaction(new DefaultTransactionAttribute()); EntityManagerFactory emf = cefb.getObject(); assertSame("EntityManagerFactory reference must be cached after init", emf, cefb.getObject()); assertNotSame("EMF must be proxied", mockEmf, emf); EntityManager em = emf.createEntityManager(); em.joinTransaction(); assertFalse(em.contains(testEntity)); try { jpatm.commit(txStatus); fail("Should have thrown OptimisticLockingFailureException"); } catch (OptimisticLockingFailureException ex) { // expected } cefb.destroy(); emfMc.verify(); emMc.verify(); tmMc.verify(); } public void testApplicationManagedEntityManagerWithJtaTransaction() throws Exception { Object testEntity = new Object(); // This one's for the tx (shared) MockControl sharedEmMc = MockControl.createControl(EntityManager.class); EntityManager sharedEm = (EntityManager) sharedEmMc.getMock(); sharedEm.getTransaction(); sharedEmMc.setReturnValue(new NoOpEntityTransaction(), 3); sharedEm.close(); sharedEmMc.setVoidCallable(1); sharedEmMc.replay(); mockEmf.createEntityManager(); emfMc.setReturnValue(sharedEm); // This is the application-specific one MockControl emMc = MockControl.createControl(EntityManager.class); EntityManager mockEm = (EntityManager) emMc.getMock(); mockEm.joinTransaction(); emMc.setVoidCallable(1); mockEm.contains(testEntity); emMc.setReturnValue(false); emMc.replay(); mockEmf.createEntityManager(); emfMc.setReturnValue(mockEm); mockEmf.close(); emfMc.setVoidCallable(); emfMc.replay(); LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit(); MutablePersistenceUnitInfo pui = ((MutablePersistenceUnitInfo) cefb.getPersistenceUnitInfo()); pui.setTransactionType(PersistenceUnitTransactionType.JTA); JpaTransactionManager jpatm = new JpaTransactionManager(); jpatm.setEntityManagerFactory(cefb.getObject()); TransactionStatus txStatus = jpatm.getTransaction(new DefaultTransactionAttribute()); EntityManagerFactory emf = cefb.getObject(); assertSame("EntityManagerFactory reference must be cached after init", emf, cefb.getObject()); assertNotSame("EMF must be proxied", mockEmf, emf); EntityManager em = emf.createEntityManager(); em.joinTransaction(); assertFalse(em.contains(testEntity)); jpatm.commit(txStatus); cefb.destroy(); emfMc.verify(); emMc.verify(); } public LocalContainerEntityManagerFactoryBean parseValidPersistenceUnit() throws Exception { LocalContainerEntityManagerFactoryBean emfb = createEntityManagerFactoryBean( "org/springframework/orm/jpa/domain/persistence.xml", null, "Person"); return emfb; } public void testInvalidPersistenceUnitName() throws Exception { try { createEntityManagerFactoryBean("org/springframework/orm/jpa/domain/persistence.xml", null, "call me Bob"); fail("Should not create factory with this name"); } catch (IllegalArgumentException ex) { // Ok } } protected LocalContainerEntityManagerFactoryBean createEntityManagerFactoryBean( String persistenceXml, Properties props, String entityManagerName) throws Exception { // This will be set by DummyPersistenceProvider actualPui = null; actualProps = null; LocalContainerEntityManagerFactoryBean containerEmfb = new LocalContainerEntityManagerFactoryBean(); containerEmfb.setPersistenceUnitName(entityManagerName); containerEmfb.setPersistenceProviderClass(DummyContainerPersistenceProvider.class); if (props != null) { containerEmfb.setJpaProperties(props); } containerEmfb.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver()); containerEmfb.setPersistenceXmlLocation(persistenceXml); containerEmfb.afterPropertiesSet(); assertEquals(entityManagerName, actualPui.getPersistenceUnitName()); if (props != null) { assertEquals(props, actualProps); } //checkInvariants(containerEmfb); return containerEmfb; //containerEmfb.destroy(); //emfMc.verify(); } public void testRejectsMissingPersistenceUnitInfo() throws Exception { LocalContainerEntityManagerFactoryBean containerEmfb = new LocalContainerEntityManagerFactoryBean(); String entityManagerName = "call me Bob"; containerEmfb.setPersistenceUnitName(entityManagerName); containerEmfb.setPersistenceProviderClass(DummyContainerPersistenceProvider.class); try { containerEmfb.afterPropertiesSet(); fail(); } catch (IllegalArgumentException ex) { // Ok } } private static class DummyContainerPersistenceProvider implements PersistenceProvider { public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo pui, Map map) { actualPui = pui; actualProps = map; return mockEmf; } public EntityManagerFactory createEntityManagerFactory(String emfName, Map properties) { throw new UnsupportedOperationException(); } } private static class NoOpEntityTransaction implements EntityTransaction { public void begin() { } public void commit() { } public void rollback() { } public void setRollbackOnly() { throw new UnsupportedOperationException(); } public boolean getRollbackOnly() { return false; } public boolean isActive() { return false; } } }