Introduce EJB-based transactional tests in the TCF

This commit introduces transactional integration tests executing
against both JUnit and TestNG in the TestContext framework (TCF) using
@TransactionAttribute in EJBs instead of Spring’s @Transactional
annotation.

These tests disprove the claims raised in SPR-6132 by demonstrating that
transaction support in the TCF works as expected when a transactional
EJB method that is configured with TransactionAttribute.REQUIRES_NEW is
invoked. Specifically:

 - The transaction managed by the TCF is suspended while such an EJB
   method is invoked.
 - Any work performed within the new transaction for the EJB method is
   committed after the method invocation completes.
 - The transaction managed by the TCF is resumed and subsequently
   either rolled back or committed as necessary based on the
   configuration of @Rollback and @TransactionConfiguration.

The configuration for the JUnit-based tests is straightforward and self
explanatory; however, the configuration for the TestNG tests is less
intuitive.

In order for the TCF to function properly, the developer must ensure
that test methods within a given TestNG test (whether defined locally,
in a superclass, or somewhere else in the suite) are executed in the
proper order. In a stand-alone test class this is straightforward;
however, in a test class hierarchy (or test suite) with dependent
methods, it is necessary to configure TestNG so that all methods within
an individual test are executed in isolation from test methods in other
tests. This can be achieved by configuring a test class to run in its
own uniquely identified suite (e.g., by annotating each concrete
TestNG-based test class with @Test(suiteName = "< Some Unique Suite
Name >")).

For example, without specifying a unique suite name for the TestNG
tests introduced in this commit, test methods will be executed in the
following (incorrect) order:

 - CommitForRequiredEjbTxDaoTestNGTests.test1InitialState()
 - CommitForRequiresNewEjbTxDaoTestNGTests.test1InitialState()
 - RollbackForRequiresNewEjbTxDaoTestNGTests.test1InitialState()
 - RollbackForRequiredEjbTxDaoTestNGTests.test1InitialState()
 - CommitForRequiredEjbTxDaoTestNGTests.test2IncrementCount1()

The reason for this ordering is that test2IncrementCount1() depends on
test1InitialState(); however, the intention of the developer is that
the tests for an individual test class are independent of those in
other test classes. So by specifying unique suite names for each test
class, the following (correct) ordering is achieved:

 - RollbackForRequiresNewEjbTxDaoTestNGTests.test1InitialState()
 - RollbackForRequiresNewEjbTxDaoTestNGTests.test2IncrementCount1()
 - RollbackForRequiresNewEjbTxDaoTestNGTests.test3IncrementCount2()
 - CommitForRequiredEjbTxDaoTestNGTests.test1InitialState()
 - CommitForRequiredEjbTxDaoTestNGTests.test2IncrementCount1()
 - CommitForRequiredEjbTxDaoTestNGTests.test3IncrementCount2()
 - RollbackForRequiredEjbTxDaoTestNGTests.test1InitialState()
 - RollbackForRequiredEjbTxDaoTestNGTests.test2IncrementCount1()
 - RollbackForRequiredEjbTxDaoTestNGTests.test3IncrementCount2()
 - CommitForRequiresNewEjbTxDaoTestNGTests.test1InitialState()
 - CommitForRequiresNewEjbTxDaoTestNGTests.test2IncrementCount1()
 - CommitForRequiresNewEjbTxDaoTestNGTests.test3IncrementCount2()

See the JIRA issue for more detailed log output.

Furthermore, @DirtiesContext(classMode = ClassMode.AFTER_CLASS) has
been used in both the JUnit and TestNG tests introduced in this commit
in order to ensure that the in-memory database is reinitialized between
each test class.

Issue: SPR-6132
This commit is contained in:
Sam Brannen 2014-01-15 15:53:23 +01:00
parent 597ef099d0
commit c0eafa9ea1
22 changed files with 938 additions and 0 deletions

View File

@ -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")

View File

@ -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();
}
}

View File

@ -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.,
* <em>commit</em>).
*
* @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 */
}

View File

@ -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.,
* <em>commit</em>).
*
* @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 */
}

View File

@ -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);
}
}

View File

@ -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 <strong>not</strong> 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 */
}

View File

@ -0,0 +1,9 @@
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="EJB-TX-Package" verbose="1">
<test name="Package">
<packages>
<package name="org.springframework.test.context.testng.transaction.ejb" />
</packages>
</test>
</suite>

View File

@ -0,0 +1,24 @@
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="EJB-TX-Separate" verbose="1">
<test name="RollbackForRequiredEjbTxDaoTestNGTests">
<classes>
<class name="org.springframework.test.context.testng.transaction.ejb.RollbackForRequiredEjbTxDaoTestNGTests" />
</classes>
</test>
<test name="CommitForRequiredEjbTxDaoTestNGTests">
<classes>
<class name="org.springframework.test.context.testng.transaction.ejb.CommitForRequiredEjbTxDaoTestNGTests" />
</classes>
</test>
<test name="CommitForRequiresNewEjbTxDaoTestNGTests">
<classes>
<class name="org.springframework.test.context.testng.transaction.ejb.CommitForRequiresNewEjbTxDaoTestNGTests" />
</classes>
</test>
<test name="RollbackForRequiresNewEjbTxDaoTestNGTests">
<classes>
<class name="org.springframework.test.context.testng.transaction.ejb.RollbackForRequiresNewEjbTxDaoTestNGTests" />
</classes>
</test>
</suite>

View File

@ -0,0 +1,12 @@
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="EJB-TX-Together" verbose="1">
<test name="Together">
<classes>
<class name="org.springframework.test.context.testng.transaction.ejb.RollbackForRequiredEjbTxDaoTestNGTests" />
<class name="org.springframework.test.context.testng.transaction.ejb.CommitForRequiredEjbTxDaoTestNGTests" />
<class name="org.springframework.test.context.testng.transaction.ejb.CommitForRequiresNewEjbTxDaoTestNGTests" />
<class name="org.springframework.test.context.testng.transaction.ejb.RollbackForRequiresNewEjbTxDaoTestNGTests" />
</classes>
</test>
</suite>

View File

@ -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();
}
}

View File

@ -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.,
* <em>commit</em>).
*
* @author Sam Brannen
* @since 4.0.1
*/
@ContextConfiguration("required-tx-config.xml")
@TransactionConfiguration(defaultRollback = false)
public class CommitForRequiredEjbTxDaoTests extends AbstractEjbTxDaoTests {
/* test methods in superclass */
}

View File

@ -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.,
* <em>commit</em>).
*
* @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 */
}

View File

@ -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);
}
}

View File

@ -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 <strong>not</strong> 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 */
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" default-lazy-init="true" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:annotation-config />
<tx:annotation-driven />
<jdbc:embedded-database id="dataSource" />
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
<property name="database" value="HSQL" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="packagesToScan" value="org.springframework.test.context.transaction.ejb.model" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
</beans>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="common-config.xml" />
<bean class="org.springframework.test.context.transaction.ejb.dao.RequiredEjbTxTestEntityDao" />
</beans>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="common-config.xml" />
<bean class="org.springframework.test.context.transaction.ejb.dao.RequiresNewEjbTxTestEntityDao" />
</beans>