Skip to content

Commit f21fe33

Browse files
committed
Support single, unqualified tx manager in the TCF
TransactionalTestExecutionListener currently requires that the PlatformTransactionManager bean be named "transactionManager" by default. Otherwise, the bean name can only be overridden via the transactionManager attribute of @TransactionConfiguration or the value attribute of @transactional. However, if there is only a single PlatformTransactionManager in the test's ApplicationContext, then the requirement to specify the exact name of that bean (or to name it exactly "transactionManager") is often superfluous. This commit addresses this issue by refactoring the TransactionalTestExecutionListener so that it is comparable to the algorithm for determining the transaction manager used in TransactionAspectSupport for "production" code. Specifically, the TTEL now uses the following algorithm to retrieve the transaction manager. - look up by type and qualifier from @transactional - else, look up by type and explicit name from @TransactionConfiguration - else, look up single bean by type - else, look up by type and default name from @TransactionConfiguration Issue: SPR-9645
1 parent c0b4e36 commit f21fe33

12 files changed

+879
-332
lines changed

spring-test/src/main/java/org/springframework/test/context/transaction/TransactionConfiguration.java

+16-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,17 +23,14 @@
2323
import java.lang.annotation.RetentionPolicy;
2424
import java.lang.annotation.Target;
2525

26-
import org.springframework.test.context.ContextConfiguration;
27-
import org.springframework.transaction.PlatformTransactionManager;
28-
2926
/**
30-
* TransactionConfiguration defines class-level metadata for configuring
27+
* {@code TransactionConfiguration} defines class-level metadata for configuring
3128
* transactional tests.
3229
*
3330
* @author Sam Brannen
3431
* @since 2.5
35-
* @see ContextConfiguration
3632
* @see TransactionalTestExecutionListener
33+
* @see org.springframework.test.context.ContextConfiguration
3734
*/
3835
@Documented
3936
@Inherited
@@ -42,15 +39,19 @@
4239
public @interface TransactionConfiguration {
4340

4441
/**
45-
* The bean name of the {@link PlatformTransactionManager} that is to be
46-
* used to drive transactions. This attribute is not required and only needs
47-
* to be specified explicitly if the bean name of the desired
48-
* PlatformTransactionManager is not "transactionManager".
49-
* <p><b>NOTE:</b> The XML <code>&lt;tx:annotation-driven&gt;</code> element
50-
* also refers to a bean named "transactionManager" by default. If you are
51-
* using both features in combination, make sure to point to the same
52-
* transaction manager bean - here in <code>@TransactionConfiguration</code> and
53-
* also in <code>&lt;tx:annotation-driven transaction-manager="..."&gt;</code>.
42+
* The bean name of the {@link org.springframework.transaction.PlatformTransactionManager
43+
* PlatformTransactionManager} that is to be used to drive transactions.
44+
*
45+
* <p>This attribute is not required and only needs to be specified explicitly
46+
* if there are multiple beans of type {@code PlatformTransactionManager} in
47+
* the test's {@code ApplicationContext} and the bean name of the desired
48+
* {@code PlatformTransactionManager} is not "transactionManager".
49+
*
50+
* <p><b>NOTE:</b> The XML {@code <tx:annotation-driven>} element also refers
51+
* to a bean named "transactionManager" by default. If you are using both
52+
* features in combination, make sure to point to the same transaction manager
53+
* bean - here in {@code @TransactionConfiguration} and also in
54+
* {@code <tx:annotation-driven transaction-manager="...">}.
5455
*/
5556
String transactionManager() default "transactionManager";
5657

spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java

+132-82
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2002-2012 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.test.context.junit4.spr9645;
18+
19+
import static org.junit.Assert.*;
20+
21+
import org.junit.Test;
22+
import org.junit.runner.RunWith;
23+
import org.springframework.context.annotation.Bean;
24+
import org.springframework.context.annotation.Configuration;
25+
import org.springframework.test.context.ContextConfiguration;
26+
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
27+
import org.springframework.test.context.transaction.AfterTransaction;
28+
import org.springframework.test.context.transaction.BeforeTransaction;
29+
import org.springframework.test.transaction.CallCountingTransactionManager;
30+
import org.springframework.transaction.PlatformTransactionManager;
31+
32+
/**
33+
* Integration tests that verify the behavior requested in
34+
* <a href="https://jira.springsource.org/browse/SPR-9645">SPR-9645</a>.
35+
*
36+
* @author Sam Brannen
37+
* @since 3.2
38+
*/
39+
@RunWith(SpringJUnit4ClassRunner.class)
40+
@ContextConfiguration
41+
public class LookUpNonexistentTxMgrTests {
42+
43+
private static final CallCountingTransactionManager txManager = new CallCountingTransactionManager();
44+
45+
46+
@Configuration
47+
static class Config {
48+
49+
@Bean
50+
public PlatformTransactionManager transactionManager() {
51+
return txManager;
52+
}
53+
}
54+
55+
56+
@BeforeTransaction
57+
public void beforeTransaction() {
58+
txManager.clear();
59+
}
60+
61+
@Test
62+
public void lookUpNothing() {
63+
assertEquals(0, txManager.begun);
64+
assertEquals(0, txManager.inflight);
65+
assertEquals(0, txManager.commits);
66+
assertEquals(0, txManager.rollbacks);
67+
}
68+
69+
@AfterTransaction
70+
public void afterTransaction() {
71+
assertEquals(0, txManager.begun);
72+
assertEquals(0, txManager.inflight);
73+
assertEquals(0, txManager.commits);
74+
assertEquals(0, txManager.rollbacks);
75+
}
76+
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2002-2012 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.test.context.junit4.spr9645;
18+
19+
import static org.junit.Assert.*;
20+
21+
import org.junit.Test;
22+
import org.junit.runner.RunWith;
23+
import org.springframework.context.annotation.Bean;
24+
import org.springframework.context.annotation.Configuration;
25+
import org.springframework.test.context.ContextConfiguration;
26+
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
27+
import org.springframework.test.context.transaction.AfterTransaction;
28+
import org.springframework.test.context.transaction.BeforeTransaction;
29+
import org.springframework.test.transaction.CallCountingTransactionManager;
30+
import org.springframework.transaction.PlatformTransactionManager;
31+
import org.springframework.transaction.annotation.Transactional;
32+
33+
/**
34+
* Integration tests that verify the behavior requested in
35+
* <a href="https://jira.springsource.org/browse/SPR-9645">SPR-9645</a>.
36+
*
37+
* @author Sam Brannen
38+
* @since 3.2
39+
*/
40+
@RunWith(SpringJUnit4ClassRunner.class)
41+
@ContextConfiguration
42+
@Transactional
43+
public class LookUpTxMgrByTypeAndDefaultNameTests {
44+
45+
private static final CallCountingTransactionManager txManager1 = new CallCountingTransactionManager();
46+
private static final CallCountingTransactionManager txManager2 = new CallCountingTransactionManager();
47+
48+
@Configuration
49+
static class Config {
50+
51+
@Bean
52+
public PlatformTransactionManager transactionManager() {
53+
return txManager1;
54+
}
55+
56+
@Bean
57+
public PlatformTransactionManager txManager2() {
58+
return txManager2;
59+
}
60+
}
61+
62+
@BeforeTransaction
63+
public void beforeTransaction() {
64+
txManager1.clear();
65+
txManager2.clear();
66+
}
67+
68+
@Test
69+
public void lookUpByTypeAndDefaultName() {
70+
assertEquals(1, txManager1.begun);
71+
assertEquals(1, txManager1.inflight);
72+
assertEquals(0, txManager1.commits);
73+
assertEquals(0, txManager1.rollbacks);
74+
}
75+
76+
@AfterTransaction
77+
public void afterTransaction() {
78+
assertEquals(1, txManager1.begun);
79+
assertEquals(0, txManager1.inflight);
80+
assertEquals(0, txManager1.commits);
81+
assertEquals(1, txManager1.rollbacks);
82+
}
83+
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2002-2012 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.test.context.junit4.spr9645;
18+
19+
import static org.junit.Assert.*;
20+
21+
import org.junit.Test;
22+
import org.junit.runner.RunWith;
23+
import org.springframework.context.annotation.Bean;
24+
import org.springframework.context.annotation.Configuration;
25+
import org.springframework.test.context.ContextConfiguration;
26+
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
27+
import org.springframework.test.context.transaction.AfterTransaction;
28+
import org.springframework.test.context.transaction.BeforeTransaction;
29+
import org.springframework.test.context.transaction.TransactionConfiguration;
30+
import org.springframework.test.transaction.CallCountingTransactionManager;
31+
import org.springframework.transaction.PlatformTransactionManager;
32+
import org.springframework.transaction.annotation.Transactional;
33+
34+
/**
35+
* Integration tests that verify the behavior requested in
36+
* <a href="https://jira.springsource.org/browse/SPR-9645">SPR-9645</a>.
37+
*
38+
* @author Sam Brannen
39+
* @since 3.2
40+
*/
41+
@RunWith(SpringJUnit4ClassRunner.class)
42+
@ContextConfiguration
43+
@Transactional
44+
@TransactionConfiguration(transactionManager = "txManager1")
45+
public class LookUpTxMgrByTypeAndNameTests {
46+
47+
private static final CallCountingTransactionManager txManager1 = new CallCountingTransactionManager();
48+
private static final CallCountingTransactionManager txManager2 = new CallCountingTransactionManager();
49+
50+
@Configuration
51+
static class Config {
52+
53+
@Bean
54+
public PlatformTransactionManager txManager1() {
55+
return txManager1;
56+
}
57+
58+
@Bean
59+
public PlatformTransactionManager txManager2() {
60+
return txManager2;
61+
}
62+
}
63+
64+
@BeforeTransaction
65+
public void beforeTransaction() {
66+
txManager1.clear();
67+
txManager2.clear();
68+
}
69+
70+
@Test
71+
public void lookUpByTypeAndName() {
72+
assertEquals(1, txManager1.begun);
73+
assertEquals(1, txManager1.inflight);
74+
assertEquals(0, txManager1.commits);
75+
assertEquals(0, txManager1.rollbacks);
76+
}
77+
78+
@AfterTransaction
79+
public void afterTransaction() {
80+
assertEquals(1, txManager1.begun);
81+
assertEquals(0, txManager1.inflight);
82+
assertEquals(0, txManager1.commits);
83+
assertEquals(1, txManager1.rollbacks);
84+
}
85+
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2002-2012 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.test.context.junit4.spr9645;
18+
19+
import static org.junit.Assert.*;
20+
21+
import org.junit.Test;
22+
import org.junit.runner.RunWith;
23+
import org.springframework.context.annotation.Bean;
24+
import org.springframework.context.annotation.Configuration;
25+
import org.springframework.test.context.ContextConfiguration;
26+
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
27+
import org.springframework.test.context.transaction.AfterTransaction;
28+
import org.springframework.test.context.transaction.BeforeTransaction;
29+
import org.springframework.test.transaction.CallCountingTransactionManager;
30+
import org.springframework.transaction.PlatformTransactionManager;
31+
import org.springframework.transaction.annotation.Transactional;
32+
33+
/**
34+
* Integration tests that verify the behavior requested in
35+
* <a href="https://jira.springsource.org/browse/SPR-9645">SPR-9645</a>.
36+
*
37+
* @author Sam Brannen
38+
* @since 3.2
39+
*/
40+
@RunWith(SpringJUnit4ClassRunner.class)
41+
@ContextConfiguration
42+
@Transactional("txManager1")
43+
public class LookUpTxMgrByTypeAndQualifierAtClassLevelTests {
44+
45+
private static final CallCountingTransactionManager txManager1 = new CallCountingTransactionManager();
46+
private static final CallCountingTransactionManager txManager2 = new CallCountingTransactionManager();
47+
48+
@Configuration
49+
static class Config {
50+
51+
@Bean
52+
public PlatformTransactionManager txManager1() {
53+
return txManager1;
54+
}
55+
56+
@Bean
57+
public PlatformTransactionManager txManager2() {
58+
return txManager2;
59+
}
60+
}
61+
62+
@BeforeTransaction
63+
public void beforeTransaction() {
64+
txManager1.clear();
65+
txManager2.clear();
66+
}
67+
68+
@Test
69+
public void lookUpByTypeAndQualifier() {
70+
assertEquals(1, txManager1.begun);
71+
assertEquals(1, txManager1.inflight);
72+
assertEquals(0, txManager1.commits);
73+
assertEquals(0, txManager1.rollbacks);
74+
}
75+
76+
@AfterTransaction
77+
public void afterTransaction() {
78+
assertEquals(1, txManager1.begun);
79+
assertEquals(0, txManager1.inflight);
80+
assertEquals(0, txManager1.commits);
81+
assertEquals(1, txManager1.rollbacks);
82+
}
83+
84+
}

0 commit comments

Comments
 (0)