Skip to content

Commit dbcf510

Browse files
committed
Add test that programmatically uses DataSourceTransactionManager
This test expects Spring to auto-config DataSourceTransactionManager
1 parent 9a022a0 commit dbcf510

File tree

20 files changed

+597
-0
lines changed

20 files changed

+597
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<classpath>
3+
<classpathentry kind="src" path="src/main/java"/>
4+
<classpathentry kind="src" path="src/main/resources"/>
5+
<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
6+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
7+
<classpathentry kind="output" path="bin"/>
8+
</classpath>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/bin/
2+
/bin_test/
3+
/generated/
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>com.ibm.ws.springboot.fat20.programmatic.trans.app</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.eclipse.jdt.core.javabuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
<buildCommand>
14+
<name>bndtools.core.bndbuilder</name>
15+
<arguments>
16+
</arguments>
17+
</buildCommand>
18+
</buildSpec>
19+
<natures>
20+
<nature>org.eclipse.jdt.core.javanature</nature>
21+
<nature>bndtools.core.bndnature</nature>
22+
</natures>
23+
</projectDescription>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
compileErrorAction=build
2+
eclipse.preferences.version=1
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
eclipse.preferences.version=1
2+
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3+
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
4+
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
5+
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
6+
org.eclipse.jdt.core.compiler.compliance=1.8
7+
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
8+
org.eclipse.jdt.core.compiler.debug.localVariable=generate
9+
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
10+
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
11+
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
12+
org.eclipse.jdt.core.compiler.source=1.8
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#*******************************************************************************
2+
# Copyright (c) 2025 IBM Corporation and others.
3+
# All rights reserved. This program and the accompanying materials
4+
# are made available under the terms of the Eclipse Public License 2.0
5+
# which accompanies this distribution, and is available at
6+
# http://www.eclipse.org/legal/epl-2.0/
7+
#
8+
# SPDX-License-Identifier: EPL-2.0
9+
#
10+
#*******************************************************************************
11+
-include= \
12+
~../cnf/resources/bnd/bundle.props, \
13+
~../cnf/resources/bnd/bundle.spring.props
14+
-nouses=true
15+
16+
bVersion=1.0
17+
18+
test.project: true
19+
instrument.disabled: true
20+
publish.wlp.jar.disabled: true
21+
22+
src: \
23+
src/main/java, \
24+
src/main/resources
25+
26+
# Specify bundles to be added to the classpath of a VM used in testing.
27+
# Entries in the -testpath instruction enable the Eclipse Package Explorer
28+
# to resolve compile dependencies for test classes. The instruction is not
29+
# required to build Spring Boot test artifacts. Each entry requies a
30+
# corresponding entry in file cnf/oss_depenendcies.maven.
31+
# Ref: https://bndtools.org/manual/packageexplorer.html
32+
33+
-testpath: \
34+
org.springframework.boot:spring-boot;${springBootVersion20}, \
35+
org.springframework.boot:spring-boot-autoconfigure;${springBootVersion20}, \
36+
\
37+
org.springframework:spring-beans;${springVersion20}, \
38+
org.springframework:spring-context;${springVersion20}, \
39+
org.springframework:spring-core;${springVersion20}, \
40+
org.springframework:spring-jdbc;${springVersion20}, \
41+
org.springframework:spring-tx;${springVersion20}, \
42+
org.springframework:spring-web;${springVersion20}, \
43+
org.slf4j:slf4j-api;version=1.7.36, \
44+
com.ibm.websphere.javaee.servlet.3.1
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License 2.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
********************************************************************************/
11+
12+
plugins {
13+
id 'org.springframework.boot' version '2.7.1'
14+
}
15+
apply from: '../wlp-gradle/subprojects/spring.gradle'
16+
def sv = springVersions[ '2.0' ]
17+
18+
apply plugin: 'war'
19+
apply plugin: 'io.spring.dependency-management'
20+
21+
group = 'com.ibm.ws.example.spring'
22+
version = '0.0.1-SNAPSHOT'
23+
sourceCompatibility = 1.8
24+
25+
apply from: '../wlp-gradle/subprojects/maven-central-mirror.gradle'
26+
27+
dependencies {
28+
implementation('org.springframework.boot:spring-boot-starter-web') // + ':' + sv['springBoot'])
29+
implementation('org.springframework.boot:spring-boot-starter-jdbc') // + ':' + sv['springBoot']) // x
30+
31+
providedCompile 'org.springframework.boot:spring-boot-starter-tomcat'
32+
}
33+
34+
bootJar {
35+
duplicatesStrategy 'warn'
36+
}
37+
38+
// Disable jar because it would need a dependency on ':com.ibm.ws.springboot.fat20.war.app:module:compileTestJava' and
39+
// ':com.ibm.ws.springboot.fat20.war.app:module:processTestResources' which seems silly since we don't actually need a jar for this project. We only need the war.
40+
jar {
41+
enabled = false
42+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License 2.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
*******************************************************************************/
11+
package com.ibm.ws.springboot.fat20.programmatic.trans.app;
12+
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
import org.springframework.boot.CommandLineRunner;
16+
import org.springframework.stereotype.Component;
17+
import org.springframework.util.Assert;
18+
19+
@Component
20+
class AppRunner implements CommandLineRunner {
21+
22+
private final static Logger logger = LoggerFactory.getLogger(AppRunner.class);
23+
24+
private final BookingService bookingService;
25+
26+
public AppRunner(BookingService bookingService) {
27+
this.bookingService = bookingService;
28+
}
29+
30+
@Override
31+
public void run(String... args) throws Exception {
32+
try {
33+
testTransactions();
34+
} catch (Exception e) {
35+
logger.error("Exception on testTransactions.", e);
36+
}
37+
}
38+
39+
private void testTransactions() {
40+
bookingService.book("Alice", "Bob", "Carol");
41+
Assert.isTrue(bookingService.findAllBookings1().size() == 3,
42+
"First booking should work with no problem");
43+
logger.info("Alice, Bob and Carol have been booked");
44+
try {
45+
bookingService.book("Chris", "Samuel");
46+
} catch (RuntimeException e) {
47+
logger.info("v--- The following exception is expect because 'Samuel' is too " +
48+
"big for the DB ---v");
49+
logger.error(e.getMessage());
50+
}
51+
52+
for (String person : bookingService.findAllBookings1()) {
53+
logger.info("Bookings1: So far, " + person + " is booked.");
54+
}
55+
logger.info("You shouldn't see Chris or Samuel. Samuel violated DB constraints, " +
56+
"and Chris was rolled back in the same TX");
57+
Assert.isTrue(bookingService.findAllBookings1().size() == 3,
58+
"'Samuel' should have triggered a rollback");
59+
try {
60+
bookingService.book("Buddy", null);
61+
} catch (RuntimeException e) {
62+
logger.info("v--- The following exception is expect because null is not " +
63+
"valid for the DB ---v");
64+
logger.error(e.getMessage());
65+
}
66+
67+
for (String person : bookingService.findAllBookings1()) {
68+
logger.info("Bookings1: So far, " + person + " is booked.");
69+
}
70+
logger.info("You shouldn't see Buddy or null. null violated DB constraints, and " +
71+
"Buddy was rolled back in the same TX");
72+
Assert.isTrue(bookingService.findAllBookings1().size() == 3,
73+
"'null' should have triggered a rollback");
74+
75+
logger.info("AppRunner: TRANSACTION TESTS PASSED");
76+
}
77+
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License 2.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
*******************************************************************************/
11+
package com.ibm.ws.springboot.fat20.programmatic.trans.app;
12+
13+
import java.util.List;
14+
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
17+
import org.springframework.beans.factory.annotation.Qualifier;
18+
import org.springframework.jdbc.core.JdbcTemplate;
19+
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
20+
import org.springframework.stereotype.Component;
21+
import org.springframework.transaction.support.TransactionTemplate;
22+
23+
@Component
24+
public class BookingService {
25+
26+
private final static Logger logger = LoggerFactory.getLogger(BookingService.class);
27+
28+
private final JdbcTemplate jdbcTemplate1;
29+
30+
private final TransactionTemplate transactionTemplate;
31+
32+
public BookingService(@Qualifier("db1JdbcTemplate") JdbcTemplate jdbcTemplate1, DataSourceTransactionManager tm) {
33+
this.jdbcTemplate1 = jdbcTemplate1;
34+
// first database will allow first names up to 5 characters long
35+
jdbcTemplate1.update("create table BOOKINGS(ID bigint, FIRST_NAME varchar(5) NOT NULL)");
36+
logger.info("jdbcTemplate1 datasource = " + jdbcTemplate1.getDataSource());
37+
38+
transactionTemplate = new TransactionTemplate(tm);
39+
}
40+
41+
public boolean book(String... persons) {
42+
return transactionTemplate.execute(s -> {
43+
for (String person : persons) {
44+
logger.info("Booking1: " + person + " in a seat...");
45+
jdbcTemplate1.update("insert into BOOKINGS(FIRST_NAME) values (?)", person);
46+
}
47+
return true;
48+
});
49+
}
50+
51+
public List<String> findAllBookings1() {
52+
return jdbcTemplate1.query("select FIRST_NAME from BOOKINGS",
53+
(rs, rowNum) -> rs.getString("FIRST_NAME"));
54+
}
55+
}

0 commit comments

Comments
 (0)