Skip to content

Commit a181b40

Browse files
committed
PersistenceAnnotationBeanPostProcessor correctly detects JPA 2.1 synchronization attribute
Issue: SPR-12396
1 parent fc7e606 commit a181b40

File tree

3 files changed

+506
-13
lines changed

3 files changed

+506
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
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.jpa21;
18+
19+
import javax.persistence.EntityManager;
20+
import javax.persistence.EntityManagerFactory;
21+
import javax.persistence.EntityTransaction;
22+
import javax.persistence.PersistenceContext;
23+
import javax.persistence.PersistenceContextType;
24+
import javax.persistence.SynchronizationType;
25+
26+
import org.junit.After;
27+
import org.junit.Before;
28+
import org.junit.Test;
29+
30+
import org.springframework.orm.jpa.JpaTransactionManager;
31+
import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor;
32+
import org.springframework.transaction.TransactionDefinition;
33+
import org.springframework.transaction.TransactionStatus;
34+
import org.springframework.transaction.support.TransactionCallback;
35+
import org.springframework.transaction.support.TransactionSynchronizationManager;
36+
import org.springframework.transaction.support.TransactionTemplate;
37+
38+
import static org.junit.Assert.*;
39+
import static org.mockito.BDDMockito.*;
40+
41+
/**
42+
* Copy of {@link org.springframework.orm.jpa.support.PersistenceContextTransactionTests},
43+
* here to be tested against JPA 2.1, including unsynchronized persistence contexts.
44+
*
45+
* @author Juergen Hoeller
46+
* @since 4.1.2
47+
*/
48+
public class PersistenceContextTransactionTests {
49+
50+
private EntityManagerFactory factory;
51+
52+
private EntityManager manager;
53+
54+
private EntityTransaction tx;
55+
56+
private TransactionTemplate tt;
57+
58+
private EntityManagerHoldingBean bean;
59+
60+
61+
@Before
62+
public void setUp() throws Exception {
63+
factory = mock(EntityManagerFactory.class);
64+
manager = mock(EntityManager.class);
65+
tx = mock(EntityTransaction.class);
66+
67+
JpaTransactionManager tm = new JpaTransactionManager(factory);
68+
tt = new TransactionTemplate(tm);
69+
70+
given(factory.createEntityManager()).willReturn(manager);
71+
given(manager.getTransaction()).willReturn(tx);
72+
given(manager.isOpen()).willReturn(true);
73+
74+
bean = new EntityManagerHoldingBean();
75+
PersistenceAnnotationBeanPostProcessor pabpp = new PersistenceAnnotationBeanPostProcessor() {
76+
@Override
77+
protected EntityManagerFactory findEntityManagerFactory(String unitName, String requestingBeanName) {
78+
return factory;
79+
}
80+
};
81+
pabpp.postProcessPropertyValues(null, null, bean, "bean");
82+
83+
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
84+
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
85+
}
86+
87+
@After
88+
public void tearDown() throws Exception {
89+
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
90+
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
91+
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
92+
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
93+
}
94+
95+
96+
@Test
97+
public void testTransactionCommitWithSharedEntityManager() {
98+
given(manager.getTransaction()).willReturn(tx);
99+
100+
tt.execute(new TransactionCallback() {
101+
@Override
102+
public Object doInTransaction(TransactionStatus status) {
103+
bean.sharedEntityManager.flush();
104+
return null;
105+
}
106+
});
107+
108+
verify(tx).commit();
109+
verify(manager).flush();
110+
verify(manager).close();
111+
}
112+
113+
@Test
114+
public void testTransactionCommitWithSharedEntityManagerAndPropagationSupports() {
115+
given(manager.isOpen()).willReturn(true);
116+
117+
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
118+
119+
tt.execute(new TransactionCallback() {
120+
@Override
121+
public Object doInTransaction(TransactionStatus status) {
122+
bean.sharedEntityManager.flush();
123+
return null;
124+
}
125+
});
126+
127+
verify(manager).flush();
128+
verify(manager).close();
129+
}
130+
131+
@Test
132+
public void testTransactionCommitWithExtendedEntityManager() {
133+
given(manager.getTransaction()).willReturn(tx);
134+
135+
tt.execute(new TransactionCallback() {
136+
@Override
137+
public Object doInTransaction(TransactionStatus status) {
138+
bean.extendedEntityManager.flush();
139+
return null;
140+
}
141+
});
142+
143+
verify(tx, times(2)).commit();
144+
verify(manager).flush();
145+
verify(manager).close();
146+
}
147+
148+
@Test
149+
public void testTransactionCommitWithExtendedEntityManagerAndPropagationSupports() {
150+
given(manager.isOpen()).willReturn(true);
151+
152+
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
153+
154+
tt.execute(new TransactionCallback() {
155+
@Override
156+
public Object doInTransaction(TransactionStatus status) {
157+
bean.extendedEntityManager.flush();
158+
return null;
159+
}
160+
});
161+
162+
verify(manager).flush();
163+
}
164+
165+
@Test
166+
public void testTransactionCommitWithSharedEntityManagerUnsynchronized() {
167+
given(manager.getTransaction()).willReturn(tx);
168+
169+
tt.execute(new TransactionCallback() {
170+
@Override
171+
public Object doInTransaction(TransactionStatus status) {
172+
bean.sharedEntityManagerUnsynchronized.flush();
173+
return null;
174+
}
175+
});
176+
177+
verify(tx).commit();
178+
verify(manager).flush();
179+
verify(manager, times(2)).close();
180+
}
181+
182+
@Test
183+
public void testTransactionCommitWithSharedEntityManagerUnsynchronizedAndPropagationSupports() {
184+
given(manager.isOpen()).willReturn(true);
185+
186+
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
187+
188+
tt.execute(new TransactionCallback() {
189+
@Override
190+
public Object doInTransaction(TransactionStatus status) {
191+
bean.sharedEntityManagerUnsynchronized.flush();
192+
return null;
193+
}
194+
});
195+
196+
verify(manager).flush();
197+
verify(manager).close();
198+
}
199+
200+
@Test
201+
public void testTransactionCommitWithExtendedEntityManagerUnsynchronized() {
202+
given(manager.getTransaction()).willReturn(tx);
203+
204+
tt.execute(new TransactionCallback() {
205+
@Override
206+
public Object doInTransaction(TransactionStatus status) {
207+
bean.extendedEntityManagerUnsynchronized.flush();
208+
return null;
209+
}
210+
});
211+
212+
verify(tx).commit();
213+
verify(manager).flush();
214+
verify(manager).close();
215+
}
216+
217+
@Test
218+
public void testTransactionCommitWithExtendedEntityManagerUnsynchronizedAndPropagationSupports() {
219+
given(manager.isOpen()).willReturn(true);
220+
221+
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
222+
223+
tt.execute(new TransactionCallback() {
224+
@Override
225+
public Object doInTransaction(TransactionStatus status) {
226+
bean.extendedEntityManagerUnsynchronized.flush();
227+
return null;
228+
}
229+
});
230+
231+
verify(manager).flush();
232+
}
233+
234+
@Test
235+
public void testTransactionCommitWithSharedEntityManagerUnsynchronizedJoined() {
236+
given(manager.getTransaction()).willReturn(tx);
237+
238+
tt.execute(new TransactionCallback() {
239+
@Override
240+
public Object doInTransaction(TransactionStatus status) {
241+
bean.sharedEntityManagerUnsynchronized.joinTransaction();
242+
bean.sharedEntityManagerUnsynchronized.flush();
243+
return null;
244+
}
245+
});
246+
247+
verify(tx).commit();
248+
verify(manager).flush();
249+
verify(manager, times(2)).close();
250+
}
251+
252+
@Test
253+
public void testTransactionCommitWithSharedEntityManagerUnsynchronizedJoinedAndPropagationSupports() {
254+
given(manager.isOpen()).willReturn(true);
255+
256+
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
257+
258+
tt.execute(new TransactionCallback() {
259+
@Override
260+
public Object doInTransaction(TransactionStatus status) {
261+
bean.sharedEntityManagerUnsynchronized.joinTransaction();
262+
bean.sharedEntityManagerUnsynchronized.flush();
263+
return null;
264+
}
265+
});
266+
267+
verify(manager).flush();
268+
verify(manager).close();
269+
}
270+
271+
@Test
272+
public void testTransactionCommitWithExtendedEntityManagerUnsynchronizedJoined() {
273+
given(manager.getTransaction()).willReturn(tx);
274+
275+
tt.execute(new TransactionCallback() {
276+
@Override
277+
public Object doInTransaction(TransactionStatus status) {
278+
bean.extendedEntityManagerUnsynchronized.joinTransaction();
279+
bean.extendedEntityManagerUnsynchronized.flush();
280+
return null;
281+
}
282+
});
283+
284+
verify(tx, times(2)).commit();
285+
verify(manager).flush();
286+
verify(manager).close();
287+
}
288+
289+
@Test
290+
public void testTransactionCommitWithExtendedEntityManagerUnsynchronizedJoinedAndPropagationSupports() {
291+
given(manager.isOpen()).willReturn(true);
292+
293+
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
294+
295+
tt.execute(new TransactionCallback() {
296+
@Override
297+
public Object doInTransaction(TransactionStatus status) {
298+
bean.extendedEntityManagerUnsynchronized.joinTransaction();
299+
bean.extendedEntityManagerUnsynchronized.flush();
300+
return null;
301+
}
302+
});
303+
304+
verify(manager).flush();
305+
}
306+
307+
308+
public static class EntityManagerHoldingBean {
309+
310+
@PersistenceContext
311+
public EntityManager sharedEntityManager;
312+
313+
@PersistenceContext(type = PersistenceContextType.EXTENDED)
314+
public EntityManager extendedEntityManager;
315+
316+
@PersistenceContext(synchronization = SynchronizationType.UNSYNCHRONIZED)
317+
public EntityManager sharedEntityManagerUnsynchronized;
318+
319+
@PersistenceContext(type = PersistenceContextType.EXTENDED, synchronization = SynchronizationType.UNSYNCHRONIZED)
320+
public EntityManager extendedEntityManagerUnsynchronized;
321+
}
322+
323+
}

0 commit comments

Comments
 (0)