diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
index 7647a6cabe8..f35bc6c8a7e 100644
--- a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
+++ b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
@@ -82,7 +82,7 @@ import org.springframework.util.StringUtils;
* with the "unitName" attribute, or no attribute at all (for the default unit).
* If those annotations are present with the "name" attribute at the class level,
* they will simply be ignored, since those only serve as deployment hint
- * (as per the Java EE 5 specification).
+ * (as per the Java EE specification).
*
*
This post-processor can either obtain EntityManagerFactory beans defined
* in the Spring application context (the default), or obtain EntityManagerFactory
@@ -167,9 +167,9 @@ public class PersistenceAnnotationBeanPostProcessor
implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware, Serializable {
- /* Check JPA 2.1 PersistenceContext.synchronizationType attribute */
- private static final Method synchronizationTypeAttribute =
- ClassUtils.getMethodIfAvailable(PersistenceContext.class, "synchronizationType");
+ /* Check JPA 2.1 PersistenceContext.synchronization() attribute */
+ private static final Method synchronizationAttribute =
+ ClassUtils.getMethodIfAvailable(PersistenceContext.class, "synchronization");
private Object jndiEnvironment;
@@ -231,8 +231,8 @@ public class PersistenceAnnotationBeanPostProcessor
* for the {@link #setDefaultPersistenceUnitName default persistence unit}
* will be taken (by default, the value mapped to the empty String),
* or simply the single persistence unit if there is only one.
- *
This is mainly intended for use in a Java EE 5 environment, with all
- * lookup driven by the standard JPA annotations, and all EntityManagerFactory
+ *
This is mainly intended for use in a Java EE environment, with all lookup
+ * driven by the standard JPA annotations, and all EntityManagerFactory
* references obtained from JNDI. No separate EntityManagerFactory bean
* definitions are necessary in such a scenario.
*
If no corresponding "persistenceContexts"/"extendedPersistenceContexts"
@@ -240,7 +240,7 @@ public class PersistenceAnnotationBeanPostProcessor
* EntityManagers built on top of the EntityManagerFactory defined here.
* Note that those will be Spring-managed EntityManagers, which implement
* transaction synchronization based on Spring's facilities.
- * If you prefer the Java EE 5 server's own EntityManager handling,
+ * If you prefer the Java EE server's own EntityManager handling,
* specify corresponding "persistenceContexts"/"extendedPersistenceContexts".
*/
public void setPersistenceUnits(Map persistenceUnits) {
@@ -258,11 +258,11 @@ public class PersistenceAnnotationBeanPostProcessor
* for the {@link #setDefaultPersistenceUnitName default persistence unit}
* will be taken (by default, the value mapped to the empty String),
* or simply the single persistence unit if there is only one.
- * This is mainly intended for use in a Java EE 5 environment, with all
+ *
This is mainly intended for use in a Java EE environment, with all
* lookup driven by the standard JPA annotations, and all EntityManager
* references obtained from JNDI. No separate EntityManagerFactory bean
* definitions are necessary in such a scenario, and all EntityManager
- * handling is done by the Java EE 5 server itself.
+ * handling is done by the Java EE server itself.
*/
public void setPersistenceContexts(Map persistenceContexts) {
this.persistenceContexts = persistenceContexts;
@@ -279,11 +279,11 @@ public class PersistenceAnnotationBeanPostProcessor
* for the {@link #setDefaultPersistenceUnitName default persistence unit}
* will be taken (by default, the value mapped to the empty String),
* or simply the single persistence unit if there is only one.
- * This is mainly intended for use in a Java EE 5 environment, with all
+ *
This is mainly intended for use in a Java EE environment, with all
* lookup driven by the standard JPA annotations, and all EntityManager
* references obtained from JNDI. No separate EntityManagerFactory bean
* definitions are necessary in such a scenario, and all EntityManager
- * handling is done by the Java EE 5 server itself.
+ * handling is done by the Java EE server itself.
*/
public void setExtendedPersistenceContexts(Map extendedPersistenceContexts) {
this.extendedPersistenceContexts = extendedPersistenceContexts;
@@ -632,8 +632,8 @@ public class PersistenceAnnotationBeanPostProcessor
}
this.unitName = pc.unitName();
this.type = pc.type();
- this.synchronizedWithTransaction = (synchronizationTypeAttribute == null ||
- "SYNCHRONIZED".equals(ReflectionUtils.invokeMethod(synchronizationTypeAttribute, pc).toString()));
+ this.synchronizedWithTransaction = (synchronizationAttribute == null ||
+ "SYNCHRONIZED".equals(ReflectionUtils.invokeMethod(synchronizationAttribute, pc).toString()));
this.properties = properties;
}
else {
diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceContextTransactionTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceContextTransactionTests.java
new file mode 100644
index 00000000000..8d37c81359d
--- /dev/null
+++ b/spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceContextTransactionTests.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2002-2014 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 javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.PersistenceContext;
+import javax.persistence.PersistenceContextType;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import static org.junit.Assert.*;
+import static org.mockito.BDDMockito.*;
+
+/**
+ * @author Juergen Hoeller
+ * @since 4.1.2
+ */
+public class PersistenceContextTransactionTests {
+
+ private EntityManagerFactory factory;
+
+ private EntityManager manager;
+
+ private EntityTransaction tx;
+
+ private TransactionTemplate tt;
+
+ private EntityManagerHoldingBean bean;
+
+
+ @Before
+ public void setUp() throws Exception {
+ factory = mock(EntityManagerFactory.class);
+ manager = mock(EntityManager.class);
+ tx = mock(EntityTransaction.class);
+
+ JpaTransactionManager tm = new JpaTransactionManager(factory);
+ tt = new TransactionTemplate(tm);
+
+ given(factory.createEntityManager()).willReturn(manager);
+ given(manager.getTransaction()).willReturn(tx);
+ given(manager.isOpen()).willReturn(true);
+
+ bean = new EntityManagerHoldingBean();
+ PersistenceAnnotationBeanPostProcessor pabpp = new PersistenceAnnotationBeanPostProcessor() {
+ @Override
+ protected EntityManagerFactory findEntityManagerFactory(String unitName, String requestingBeanName) {
+ return factory;
+ }
+ };
+ pabpp.postProcessPropertyValues(null, null, bean, "bean");
+
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+
+
+ @Test
+ public void testTransactionCommitWithSharedEntityManager() {
+ given(manager.getTransaction()).willReturn(tx);
+
+ tt.execute(new TransactionCallback() {
+ @Override
+ public Object doInTransaction(TransactionStatus status) {
+ bean.sharedEntityManager.flush();
+ return null;
+ }
+ });
+
+ verify(tx).commit();
+ verify(manager).flush();
+ verify(manager).close();
+ }
+
+ @Test
+ public void testTransactionCommitWithSharedEntityManagerAndPropagationSupports() {
+ given(manager.isOpen()).willReturn(true);
+
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+
+ tt.execute(new TransactionCallback() {
+ @Override
+ public Object doInTransaction(TransactionStatus status) {
+ bean.sharedEntityManager.flush();
+ return null;
+ }
+ });
+
+ verify(manager).flush();
+ verify(manager).close();
+ }
+
+ @Test
+ public void testTransactionCommitWithExtendedEntityManager() {
+ given(manager.getTransaction()).willReturn(tx);
+
+ tt.execute(new TransactionCallback() {
+ @Override
+ public Object doInTransaction(TransactionStatus status) {
+ bean.extendedEntityManager.flush();
+ return null;
+ }
+ });
+
+ verify(tx, times(2)).commit();
+ verify(manager).flush();
+ verify(manager).close();
+ }
+
+ @Test
+ public void testTransactionCommitWithExtendedEntityManagerAndPropagationSupports() {
+ given(manager.isOpen()).willReturn(true);
+
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+
+ tt.execute(new TransactionCallback() {
+ @Override
+ public Object doInTransaction(TransactionStatus status) {
+ bean.extendedEntityManager.flush();
+ return null;
+ }
+ });
+
+ verify(manager).flush();
+ }
+
+
+ public static class EntityManagerHoldingBean {
+
+ @PersistenceContext
+ public EntityManager sharedEntityManager;
+
+ @PersistenceContext(type = PersistenceContextType.EXTENDED)
+ public EntityManager extendedEntityManager;
+ }
+
+}