diff --git a/build.gradle b/build.gradle
index 87aa765f46..13f6049d56 100644
--- a/build.gradle
+++ b/build.gradle
@@ -804,7 +804,9 @@ project("spring-test") {
testCompile(project(":spring-context-support"))
testCompile(project(":spring-oxm"))
testCompile(project(":spring-webmvc-tiles3"))
+ testCompile("javax.ejb:ejb-api:3.0")
testCompile("org.hibernate:hibernate-core:${hibernate3Version}")
+ testCompile("org.hibernate:hibernate-entitymanager:${hibernate3Version}")
testCompile "org.slf4j:slf4j-jcl:${slf4jVersion}"
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
testCompile("org.hibernate:hibernate-validator:4.3.0.Final")
diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/AbstractEjbTxDaoTestNGTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/AbstractEjbTxDaoTestNGTests.java
new file mode 100644
index 0000000000..71686cc834
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/AbstractEjbTxDaoTestNGTests.java
@@ -0,0 +1,85 @@
+/*
+ * 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.test.context.testng.transaction.ejb;
+
+import javax.ejb.EJB;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
+import org.springframework.test.context.transaction.ejb.dao.TestEntityDao;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import static org.testng.AssertJUnit.*;
+
+/**
+ * Abstract base class for all TestNG-based tests involving EJB transaction
+ * support in the TestContext framework.
+ *
+ * @author Sam Brannen
+ * @author Xavier Detant
+ * @since 4.0.1
+ */
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
+public abstract class AbstractEjbTxDaoTestNGTests extends AbstractTransactionalTestNGSpringContextTests {
+
+ protected static final String TEST_NAME = "test-name";
+
+ @EJB
+ protected TestEntityDao dao;
+
+ @PersistenceContext
+ protected EntityManager em;
+
+
+ @Test
+ public void test1InitialState() {
+ int count = dao.getCount(TEST_NAME);
+ assertEquals("New TestEntity should have count=0.", 0, count);
+ }
+
+ @Test(dependsOnMethods = "test1InitialState")
+ public void test2IncrementCount1() {
+ int count = dao.incrementCount(TEST_NAME);
+ assertEquals("Expected count=1 after first increment.", 1, count);
+ }
+
+ /**
+ * The default implementation of this method assumes that the transaction
+ * for {@link #test2IncrementCount1()} was committed. Therefore, it is
+ * expected that the previous increment has been persisted in the database.
+ */
+ @Test(dependsOnMethods = "test2IncrementCount1")
+ public void test3IncrementCount2() {
+ int count = dao.getCount(TEST_NAME);
+ assertEquals("Expected count=1 after test2IncrementCount1().", 1, count);
+
+ count = dao.incrementCount(TEST_NAME);
+ assertEquals("Expected count=2 now.", 2, count);
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void synchronizePersistenceContext() {
+ em.flush();
+ }
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/CommitForRequiredEjbTxDaoTestNGTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/CommitForRequiredEjbTxDaoTestNGTests.java
new file mode 100644
index 0000000000..851e674b7b
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/CommitForRequiredEjbTxDaoTestNGTests.java
@@ -0,0 +1,41 @@
+/*
+ * 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.test.context.testng.transaction.ejb;
+
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.transaction.TransactionConfiguration;
+import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
+import org.springframework.test.context.transaction.ejb.dao.RequiredEjbTxTestEntityDao;
+import org.testng.annotations.Test;
+
+/**
+ * Concrete subclass of {@link AbstractEjbTxDaoTestNGTests} which uses the
+ * {@link RequiredEjbTxTestEntityDao} and sets the default rollback semantics
+ * for the {@link TransactionalTestExecutionListener} to {@code false} (i.e.,
+ * commit).
+ *
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+@Test(suiteName = "Commit for REQUIRED")
+@ContextConfiguration("/org/springframework/test/context/transaction/ejb/required-tx-config.xml")
+@TransactionConfiguration(defaultRollback = false)
+public class CommitForRequiredEjbTxDaoTestNGTests extends AbstractEjbTxDaoTestNGTests {
+
+ /* test methods in superclass */
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/CommitForRequiresNewEjbTxDaoTestNGTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/CommitForRequiresNewEjbTxDaoTestNGTests.java
new file mode 100644
index 0000000000..0310c882de
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/CommitForRequiresNewEjbTxDaoTestNGTests.java
@@ -0,0 +1,41 @@
+/*
+ * 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.test.context.testng.transaction.ejb;
+
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.transaction.TransactionConfiguration;
+import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
+import org.springframework.test.context.transaction.ejb.dao.RequiresNewEjbTxTestEntityDao;
+import org.testng.annotations.Test;
+
+/**
+ * Concrete subclass of {@link AbstractEjbTxDaoTestNGTests} which uses the
+ * {@link RequiresNewEjbTxTestEntityDao} and sets the default rollback semantics
+ * for the {@link TransactionalTestExecutionListener} to {@code false} (i.e.,
+ * commit).
+ *
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+@Test(suiteName = "Commit for REQUIRES_NEW")
+@ContextConfiguration("/org/springframework/test/context/transaction/ejb/requires-new-tx-config.xml")
+@TransactionConfiguration(defaultRollback = false)
+public class CommitForRequiresNewEjbTxDaoTestNGTests extends AbstractEjbTxDaoTestNGTests {
+
+ /* test methods in superclass */
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/RollbackForRequiredEjbTxDaoTestNGTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/RollbackForRequiredEjbTxDaoTestNGTests.java
new file mode 100644
index 0000000000..cf00e5d5de
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/RollbackForRequiredEjbTxDaoTestNGTests.java
@@ -0,0 +1,78 @@
+/*
+ * 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.test.context.testng.transaction.ejb;
+
+import org.springframework.test.context.transaction.TransactionConfiguration;
+import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
+import org.testng.annotations.Test;
+
+import static org.testng.AssertJUnit.*;
+
+/**
+ * Extension of {@link CommitForRequiredEjbTxDaoTestNGTests} which sets the default
+ * rollback semantics for the {@link TransactionalTestExecutionListener} to
+ * {@code true}. The transaction managed by the TestContext framework will be
+ * rolled back after each test method. Consequently, any work performed in
+ * transactional methods that participate in the test-managed transaction will
+ * be rolled back automatically.
+ *
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+@Test(suiteName = "Rollback for REQUIRED")
+@TransactionConfiguration(defaultRollback = true)
+public class RollbackForRequiredEjbTxDaoTestNGTests extends CommitForRequiredEjbTxDaoTestNGTests {
+
+ /**
+ * Redeclared to ensure test method execution order. Simply delegates to super.
+ */
+ @Test
+ @Override
+ public void test1InitialState() {
+ super.test1InitialState();
+ }
+
+ /**
+ * Redeclared to ensure test method execution order. Simply delegates to super.
+ */
+ @Test(dependsOnMethods = "test1InitialState")
+ @Override
+ public void test2IncrementCount1() {
+ super.test2IncrementCount1();
+ }
+
+ /**
+ * Overrides parent implementation in order to change expectations to align with
+ * behavior associated with "required" transactions on repositories/DAOs and
+ * default rollback semantics for transactions managed by the TestContext
+ * framework.
+ */
+ @Test(dependsOnMethods = "test2IncrementCount1")
+ @Override
+ public void test3IncrementCount2() {
+ int count = dao.getCount(TEST_NAME);
+ // Expecting count=0 after test2IncrementCount1() since REQUIRED transactions
+ // participate in the existing transaction (if present), which in this case is the
+ // transaction managed by the TestContext framework which will be rolled back
+ // after each test method.
+ assertEquals("Expected count=0 after test2IncrementCount1().", 0, count);
+
+ count = dao.incrementCount(TEST_NAME);
+ assertEquals("Expected count=1 now.", 1, count);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/RollbackForRequiresNewEjbTxDaoTestNGTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/RollbackForRequiresNewEjbTxDaoTestNGTests.java
new file mode 100644
index 0000000000..fa5b62afca
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/RollbackForRequiresNewEjbTxDaoTestNGTests.java
@@ -0,0 +1,44 @@
+/*
+ * 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.test.context.testng.transaction.ejb;
+
+import org.springframework.test.context.transaction.TransactionConfiguration;
+import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
+import org.testng.annotations.Test;
+
+/**
+ * Extension of {@link CommitForRequiresNewEjbTxDaoTestNGTests} which sets the default
+ * rollback semantics for the {@link TransactionalTestExecutionListener} to
+ * {@code true}. The transaction managed by the TestContext framework will be
+ * rolled back after each test method. Consequently, any work performed in
+ * transactional methods that participate in the test-managed transaction will
+ * be rolled back automatically. On the other hand, any work performed in
+ * transactional methods that do not participate in the
+ * test-managed transaction will not be affected by the rollback of the
+ * test-managed transaction. For example, such work may in fact be committed
+ * outside the scope of the test-managed transaction.
+ *
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+@Test(suiteName = "Rollback for REQUIRES_NEW")
+@TransactionConfiguration(defaultRollback = true)
+public class RollbackForRequiresNewEjbTxDaoTestNGTests extends CommitForRequiresNewEjbTxDaoTestNGTests {
+
+ /* test methods in superclass */
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/testng-package.xml b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/testng-package.xml
new file mode 100644
index 0000000000..c3567d58e5
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/testng-package.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/testng-test-separate.xml b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/testng-test-separate.xml
new file mode 100644
index 0000000000..fc95db9b8b
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/testng-test-separate.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/testng-test-together.xml b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/testng-test-together.xml
new file mode 100644
index 0000000000..e3c4e0078a
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/testng-test-together.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/AbstractEjbTxDaoTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/AbstractEjbTxDaoTests.java
new file mode 100644
index 0000000000..89fbd7bec5
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/AbstractEjbTxDaoTests.java
@@ -0,0 +1,88 @@
+/*
+ * 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.test.context.transaction.ejb;
+
+import javax.ejb.EJB;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import org.junit.After;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
+import org.springframework.test.context.transaction.ejb.dao.TestEntityDao;
+
+import static org.junit.Assert.*;
+
+/**
+ * Abstract base class for all tests involving EJB transaction support in the
+ * TestContext framework.
+ *
+ * @author Sam Brannen
+ * @author Xavier Detant
+ * @since 4.0.1
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
+public abstract class AbstractEjbTxDaoTests extends AbstractTransactionalJUnit4SpringContextTests {
+
+ protected static final String TEST_NAME = "test-name";
+
+ @EJB
+ protected TestEntityDao dao;
+
+ @PersistenceContext
+ protected EntityManager em;
+
+
+ @Test
+ public void test1InitialState() {
+ int count = dao.getCount(TEST_NAME);
+ assertEquals("New TestEntity should have count=0.", 0, count);
+ }
+
+ @Test
+ public void test2IncrementCount1() {
+ int count = dao.incrementCount(TEST_NAME);
+ assertEquals("Expected count=1 after first increment.", 1, count);
+ }
+
+ /**
+ * The default implementation of this method assumes that the transaction
+ * for {@link #test2IncrementCount1()} was committed. Therefore, it is
+ * expected that the previous increment has been persisted in the database.
+ */
+ @Test
+ public void test3IncrementCount2() {
+ int count = dao.getCount(TEST_NAME);
+ assertEquals("Expected count=1 after test2IncrementCount1().", 1, count);
+
+ count = dao.incrementCount(TEST_NAME);
+ assertEquals("Expected count=2 now.", 2, count);
+ }
+
+ @After
+ public void synchronizePersistenceContext() {
+ em.flush();
+ }
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/CommitForRequiredEjbTxDaoTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/CommitForRequiredEjbTxDaoTests.java
new file mode 100644
index 0000000000..74d8067d1a
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/CommitForRequiredEjbTxDaoTests.java
@@ -0,0 +1,39 @@
+/*
+ * 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.test.context.transaction.ejb;
+
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.transaction.TransactionConfiguration;
+import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
+import org.springframework.test.context.transaction.ejb.dao.RequiredEjbTxTestEntityDao;
+
+/**
+ * Concrete subclass of {@link AbstractEjbTxDaoTests} which uses the
+ * {@link RequiredEjbTxTestEntityDao} and sets the default rollback semantics
+ * for the {@link TransactionalTestExecutionListener} to {@code false} (i.e.,
+ * commit).
+ *
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+@ContextConfiguration("required-tx-config.xml")
+@TransactionConfiguration(defaultRollback = false)
+public class CommitForRequiredEjbTxDaoTests extends AbstractEjbTxDaoTests {
+
+ /* test methods in superclass */
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/CommitForRequiresNewEjbTxDaoTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/CommitForRequiresNewEjbTxDaoTests.java
new file mode 100644
index 0000000000..4651b119de
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/CommitForRequiresNewEjbTxDaoTests.java
@@ -0,0 +1,39 @@
+/*
+ * 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.test.context.transaction.ejb;
+
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.transaction.TransactionConfiguration;
+import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
+import org.springframework.test.context.transaction.ejb.dao.RequiresNewEjbTxTestEntityDao;
+
+/**
+ * Concrete subclass of {@link AbstractEjbTxDaoTests} which uses the
+ * {@link RequiresNewEjbTxTestEntityDao} and sets the default rollback semantics
+ * for the {@link TransactionalTestExecutionListener} to {@code false} (i.e.,
+ * commit).
+ *
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+@ContextConfiguration("requires-new-tx-config.xml")
+@TransactionConfiguration(defaultRollback = false)
+public class CommitForRequiresNewEjbTxDaoTests extends AbstractEjbTxDaoTests {
+
+ /* test methods in superclass */
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/RollbackForRequiredEjbTxDaoTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/RollbackForRequiredEjbTxDaoTests.java
new file mode 100644
index 0000000000..491afebeaf
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/RollbackForRequiredEjbTxDaoTests.java
@@ -0,0 +1,80 @@
+/*
+ * 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.test.context.transaction.ejb;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.springframework.test.context.transaction.TransactionConfiguration;
+import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
+
+import static org.junit.Assert.*;
+
+/**
+ * Extension of {@link CommitForRequiredEjbTxDaoTests} which sets the default
+ * rollback semantics for the {@link TransactionalTestExecutionListener} to
+ * {@code true}. The transaction managed by the TestContext framework will be
+ * rolled back after each test method. Consequently, any work performed in
+ * transactional methods that participate in the test-managed transaction will
+ * be rolled back automatically.
+ *
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@TransactionConfiguration(defaultRollback = true)
+public class RollbackForRequiredEjbTxDaoTests extends CommitForRequiredEjbTxDaoTests {
+
+ /**
+ * Redeclared to ensure test method execution order. Simply delegates to super.
+ */
+ @Test
+ @Override
+ public void test1InitialState() {
+ super.test1InitialState();
+ }
+
+ /**
+ * Redeclared to ensure test method execution order. Simply delegates to super.
+ */
+ @Test
+ @Override
+ public void test2IncrementCount1() {
+ super.test2IncrementCount1();
+ }
+
+ /**
+ * Overrides parent implementation in order to change expectations to align with
+ * behavior associated with "required" transactions on repositories/DAOs and
+ * default rollback semantics for transactions managed by the TestContext
+ * framework.
+ */
+ @Test
+ @Override
+ public void test3IncrementCount2() {
+ int count = dao.getCount(TEST_NAME);
+ // Expecting count=0 after test2IncrementCount1() since REQUIRED transactions
+ // participate in the existing transaction (if present), which in this case is the
+ // transaction managed by the TestContext framework which will be rolled back
+ // after each test method.
+ assertEquals("Expected count=0 after test2IncrementCount1().", 0, count);
+
+ count = dao.incrementCount(TEST_NAME);
+ assertEquals("Expected count=1 now.", 1, count);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/RollbackForRequiresNewEjbTxDaoTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/RollbackForRequiresNewEjbTxDaoTests.java
new file mode 100644
index 0000000000..ec3147258c
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/RollbackForRequiresNewEjbTxDaoTests.java
@@ -0,0 +1,42 @@
+/*
+ * 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.test.context.transaction.ejb;
+
+import org.springframework.test.context.transaction.TransactionConfiguration;
+import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
+
+/**
+ * Extension of {@link CommitForRequiresNewEjbTxDaoTests} which sets the default
+ * rollback semantics for the {@link TransactionalTestExecutionListener} to
+ * {@code true}. The transaction managed by the TestContext framework will be
+ * rolled back after each test method. Consequently, any work performed in
+ * transactional methods that participate in the test-managed transaction will
+ * be rolled back automatically. On the other hand, any work performed in
+ * transactional methods that do not participate in the
+ * test-managed transaction will not be affected by the rollback of the
+ * test-managed transaction. For example, such work may in fact be committed
+ * outside the scope of the test-managed transaction.
+ *
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+@TransactionConfiguration(defaultRollback = true)
+public class RollbackForRequiresNewEjbTxDaoTests extends CommitForRequiresNewEjbTxDaoTests {
+
+ /* test methods in superclass */
+
+}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/AbstractEjbTxTestEntityDao.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/AbstractEjbTxTestEntityDao.java
new file mode 100644
index 0000000000..24fc4cac1f
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/AbstractEjbTxTestEntityDao.java
@@ -0,0 +1,63 @@
+/*
+ * 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.test.context.transaction.ejb.dao;
+
+import javax.ejb.TransactionAttribute;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import org.springframework.test.context.transaction.ejb.model.TestEntity;
+
+/**
+ * Abstract base class for EJB implementations of {@link TestEntityDao} which
+ * declare transaction semantics for {@link #incrementCount(String)} via
+ * {@link TransactionAttribute}.
+ *
+ * @author Sam Brannen
+ * @author Xavier Detant
+ * @since 4.0.1
+ * @see RequiredEjbTxTestEntityDao
+ * @see RequiresNewEjbTxTestEntityDao
+ */
+public abstract class AbstractEjbTxTestEntityDao implements TestEntityDao {
+
+ @PersistenceContext
+ protected EntityManager entityManager;
+
+
+ protected final TestEntity getTestEntity(String name) {
+ TestEntity te = entityManager.find(TestEntity.class, name);
+ if (te == null) {
+ te = new TestEntity(name, 0);
+ entityManager.persist(te);
+ }
+ return te;
+ }
+
+ protected final int getCountInternal(String name) {
+ return getTestEntity(name).getCount();
+ }
+
+ protected final int incrementCountInternal(String name) {
+ TestEntity te = getTestEntity(name);
+ int count = te.getCount();
+ count++;
+ te.setCount(count);
+ return count;
+ }
+
+}
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/RequiredEjbTxTestEntityDao.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/RequiredEjbTxTestEntityDao.java
new file mode 100644
index 0000000000..340e39a273
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/RequiredEjbTxTestEntityDao.java
@@ -0,0 +1,50 @@
+/*
+ * 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.test.context.transaction.ejb.dao;
+
+import javax.ejb.Local;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.ejb.TransactionAttributeType;
+
+/**
+ * EJB implementation of {@link TestEntityDao} which declares transaction
+ * semantics for {@link #incrementCount(String)} with
+ * {@link TransactionAttributeType#REQUIRED}.
+ *
+ * @author Sam Brannen
+ * @author Xavier Detant
+ * @since 4.0.1
+ * @see RequiresNewEjbTxTestEntityDao
+ */
+@Stateless
+@Local(TestEntityDao.class)
+@TransactionAttribute(TransactionAttributeType.MANDATORY)
+public class RequiredEjbTxTestEntityDao extends AbstractEjbTxTestEntityDao {
+
+ @Override
+ public int getCount(String name) {
+ return super.getCountInternal(name);
+ }
+
+ @TransactionAttribute(TransactionAttributeType.REQUIRED)
+ @Override
+ public int incrementCount(String name) {
+ return super.incrementCountInternal(name);
+ }
+
+}
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/RequiresNewEjbTxTestEntityDao.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/RequiresNewEjbTxTestEntityDao.java
new file mode 100644
index 0000000000..68fdcd3938
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/RequiresNewEjbTxTestEntityDao.java
@@ -0,0 +1,50 @@
+/*
+ * 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.test.context.transaction.ejb.dao;
+
+import javax.ejb.Local;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.ejb.TransactionAttributeType;
+
+/**
+ * EJB implementation of {@link TestEntityDao} which declares transaction
+ * semantics for {@link #incrementCount(String)} with
+ * {@link TransactionAttributeType#REQUIRES_NEW}.
+ *
+ * @author Sam Brannen
+ * @author Xavier Detant
+ * @since 4.0.1
+ * @see RequiredEjbTxTestEntityDao
+ */
+@Stateless
+@Local(TestEntityDao.class)
+@TransactionAttribute(TransactionAttributeType.MANDATORY)
+public class RequiresNewEjbTxTestEntityDao extends AbstractEjbTxTestEntityDao {
+
+ @Override
+ public int getCount(String name) {
+ return super.getCountInternal(name);
+ }
+
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ @Override
+ public int incrementCount(String name) {
+ return super.incrementCountInternal(name);
+ }
+
+}
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/TestEntityDao.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/TestEntityDao.java
new file mode 100644
index 0000000000..361f0ec63b
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/dao/TestEntityDao.java
@@ -0,0 +1,32 @@
+/*
+ * 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.test.context.transaction.ejb.dao;
+
+/**
+ * Test DAO for EJB transaction support in the TestContext framework.
+ *
+ * @author Xavier Detant
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+public interface TestEntityDao {
+
+ int getCount(String name);
+
+ int incrementCount(String name);
+
+}
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/model/TestEntity.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/model/TestEntity.java
new file mode 100644
index 0000000000..9d2e82b9d4
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/model/TestEntity.java
@@ -0,0 +1,68 @@
+/*
+ * 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.test.context.transaction.ejb.model;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * Test entity for EJB transaction support in the TestContext framework.
+ *
+ * @author Xavier Detant
+ * @author Sam Brannen
+ * @since 4.0.1
+ */
+@Entity
+@Table(name = TestEntity.TABLE_NAME)
+public class TestEntity {
+
+ public static final String TABLE_NAME = "TEST_ENTITY";
+
+ @Id
+ @Column(name = "TE_NAME", nullable = false)
+ private String name;
+
+ @Column(name = "TE_COUNT", nullable = false)
+ private int count;
+
+
+ public TestEntity() {
+ }
+
+ public TestEntity(String name, int count) {
+ this.name = name;
+ this.count = count;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getCount() {
+ return this.count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+}
diff --git a/spring-test/src/test/resources/org/springframework/test/context/transaction/ejb/common-config.xml b/spring-test/src/test/resources/org/springframework/test/context/transaction/ejb/common-config.xml
new file mode 100644
index 0000000000..b801b600d1
--- /dev/null
+++ b/spring-test/src/test/resources/org/springframework/test/context/transaction/ejb/common-config.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-test/src/test/resources/org/springframework/test/context/transaction/ejb/required-tx-config.xml b/spring-test/src/test/resources/org/springframework/test/context/transaction/ejb/required-tx-config.xml
new file mode 100644
index 0000000000..a159597bc6
--- /dev/null
+++ b/spring-test/src/test/resources/org/springframework/test/context/transaction/ejb/required-tx-config.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-test/src/test/resources/org/springframework/test/context/transaction/ejb/requires-new-tx-config.xml b/spring-test/src/test/resources/org/springframework/test/context/transaction/ejb/requires-new-tx-config.xml
new file mode 100644
index 0000000000..a061be1db5
--- /dev/null
+++ b/spring-test/src/test/resources/org/springframework/test/context/transaction/ejb/requires-new-tx-config.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file