View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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  
17  package org.springframework.orm.jpa;
18  
19  import java.lang.reflect.Proxy;
20  import java.util.List;
21  import javax.persistence.EntityManager;
22  import javax.persistence.PersistenceException;
23  import javax.persistence.Query;
24  import javax.persistence.TransactionRequiredException;
25  
26  import org.springframework.dao.DataAccessException;
27  import org.springframework.dao.support.PersistenceExceptionTranslator;
28  import org.springframework.orm.jpa.domain.Person;
29  import org.springframework.transaction.annotation.Propagation;
30  import org.springframework.transaction.annotation.Transactional;
31  
32  /**
33   * Integration tests using in-memory database for container-managed JPA
34   *
35   * @author Rod Johnson
36   * @since 2.0
37   */
38  @SuppressWarnings("deprecation")
39  public class ContainerManagedEntityManagerIntegrationTests extends AbstractEntityManagerFactoryIntegrationTests {
40  
41  	@Transactional(propagation = Propagation.NOT_SUPPORTED)
42  	public void testExceptionTranslationWithDialectFoundOnIntroducedEntityManagerInfo() throws Exception {
43  		doTestExceptionTranslationWithDialectFound(((EntityManagerFactoryInfo) entityManagerFactory).getJpaDialect());
44  	}
45  
46  	@Transactional(propagation = Propagation.NOT_SUPPORTED)
47  	public void testExceptionTranslationWithDialectFoundOnEntityManagerFactoryBean() throws Exception {
48  		AbstractEntityManagerFactoryBean aefb =
49  				(AbstractEntityManagerFactoryBean) applicationContext.getBean("&entityManagerFactory");
50  		assertNotNull("Dialect must have been set", aefb.getJpaDialect());
51  		doTestExceptionTranslationWithDialectFound(aefb);
52  	}
53  
54  	protected void doTestExceptionTranslationWithDialectFound(PersistenceExceptionTranslator pet) throws Exception {
55  		RuntimeException in1 = new RuntimeException("in1");
56  		PersistenceException in2 = new PersistenceException();
57  		assertNull("No translation here", pet.translateExceptionIfPossible(in1));
58  		DataAccessException dex = pet.translateExceptionIfPossible(in2);
59  		assertNotNull(dex);
60  		assertSame(in2, dex.getCause());
61  	}
62  
63  	public void testEntityManagerProxyIsProxy() {
64  		EntityManager em = createContainerManagedEntityManager();
65  		assertTrue(Proxy.isProxyClass(em.getClass()));
66  		Query q = em.createQuery("select p from Person as p");
67  		List<Person> people = q.getResultList();
68  		assertTrue(people.isEmpty());
69  
70  		assertTrue("Should be open to start with", em.isOpen());
71  		try {
72  			em.close();
73  			fail("Close should not work on container managed EM");
74  		}
75  		catch (IllegalStateException ex) {
76  			// Ok
77  		}
78  		assertTrue(em.isOpen());
79  	}
80  
81  	// This would be legal, at least if not actually _starting_ a tx
82  	public void testEntityManagerProxyRejectsProgrammaticTxManagement() {
83  		try {
84  			createContainerManagedEntityManager().getTransaction();
85  			fail("Should have thrown an IllegalStateException");
86  		}
87  		catch (IllegalStateException e) {
88  			/* expected */
89  		}
90  	}
91  
92  	/*
93  	 * See comments in spec on EntityManager.joinTransaction().
94  	 * We take the view that this is a valid no op.
95  	 */
96  	public void testContainerEntityManagerProxyAllowsJoinTransactionInTransaction() {
97  		createContainerManagedEntityManager().joinTransaction();
98  	}
99  
100 	@Transactional(propagation = Propagation.NOT_SUPPORTED)
101 	public void testContainerEntityManagerProxyRejectsJoinTransactionWithoutTransaction() {
102 		try {
103 			createContainerManagedEntityManager().joinTransaction();
104 			fail("Should have thrown a TransactionRequiredException");
105 		}
106 		catch (TransactionRequiredException e) {
107 			/* expected */
108 		}
109 	}
110 
111 	public void testInstantiateAndSave() {
112 		EntityManager em = createContainerManagedEntityManager();
113 		doInstantiateAndSave(em);
114 	}
115 
116 	public void doInstantiateAndSave(EntityManager em) {
117 		assertEquals("Should be no people from previous transactions", 0, countRowsInTable(em, "person"));
118 		Person p = new Person();
119 
120 		p.setFirstName("Tony");
121 		p.setLastName("Blair");
122 		em.persist(p);
123 
124 		em.flush();
125 		assertEquals("1 row must have been inserted", 1, countRowsInTable(em, "person"));
126 	}
127 
128 	public void testReuseInNewTransaction() {
129 		EntityManager em = createContainerManagedEntityManager();
130 		doInstantiateAndSave(em);
131 		endTransaction();
132 
133 		//assertFalse(em.getTransaction().isActive());
134 
135 		startNewTransaction();
136 		// Call any method: should cause automatic tx invocation
137 		assertFalse(em.contains(new Person()));
138 		//assertTrue(em.getTransaction().isActive());
139 
140 		doInstantiateAndSave(em);
141 		setComplete();
142 		endTransaction();	// Should rollback
143 		assertEquals("Tx must have committed back", 1, countRowsInTable(em, "person"));
144 
145 		// Now clean up the database
146 		deleteFromTables("person");
147 	}
148 
149 	public void testRollbackOccurs() {
150 		EntityManager em = createContainerManagedEntityManager();
151 		doInstantiateAndSave(em);
152 		endTransaction();	// Should rollback
153 		assertEquals("Tx must have been rolled back", 0, countRowsInTable(em, "person"));
154 	}
155 
156 	public void testCommitOccurs() {
157 		EntityManager em = createContainerManagedEntityManager();
158 		doInstantiateAndSave(em);
159 		setComplete();
160 		endTransaction();	// Should rollback
161 		assertEquals("Tx must have committed back", 1, countRowsInTable(em, "person"));
162 
163 		// Now clean up the database
164 		deleteFromTables("person");
165 	}
166 
167 }