Skip to content

Commit b55a0df

Browse files
committed
Add test for Java 21 ExecutorFactory
1 parent b98aaee commit b55a0df

File tree

8 files changed

+192
-5
lines changed

8 files changed

+192
-5
lines changed

blackbox-tests/pom.xml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>io.ebean</groupId>
8+
<artifactId>ebean-datasource-parent</artifactId>
9+
<version>9.7-RC1</version>
10+
</parent>
11+
12+
<artifactId>blackbox-tests</artifactId>
13+
14+
<properties>
15+
<maven.compiler.release>21</maven.compiler.release>
16+
</properties>
17+
18+
<dependencies>
19+
<dependency>
20+
<groupId>io.ebean</groupId>
21+
<artifactId>ebean-datasource</artifactId>
22+
<version>9.6</version>
23+
</dependency>
24+
25+
<dependency>
26+
<groupId>io.avaje</groupId>
27+
<artifactId>junit</artifactId>
28+
<version>1.5</version>
29+
<scope>test</scope>
30+
</dependency>
31+
32+
<dependency>
33+
<groupId>io.ebean</groupId>
34+
<artifactId>ebean-test-containers</artifactId>
35+
<version>7.8</version>
36+
<scope>test</scope>
37+
</dependency>
38+
39+
<dependency>
40+
<groupId>org.postgresql</groupId>
41+
<artifactId>postgresql</artifactId>
42+
<version>42.7.2</version>
43+
<scope>test</scope>
44+
</dependency>
45+
46+
<dependency>
47+
<groupId>ch.qos.logback</groupId>
48+
<artifactId>logback-classic</artifactId>
49+
<version>1.5.17</version>
50+
<scope>test</scope>
51+
</dependency>
52+
53+
<dependency>
54+
<groupId>org.slf4j</groupId>
55+
<artifactId>slf4j-jdk-platform-logging</artifactId>
56+
<version>2.0.17</version>
57+
<scope>test</scope>
58+
</dependency>
59+
60+
<dependency>
61+
<groupId>io.avaje</groupId>
62+
<artifactId>avaje-slf4j-jpl</artifactId>
63+
<version>1.2</version>
64+
<scope>test</scope>
65+
</dependency>
66+
67+
</dependencies>
68+
</project>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.example.tests;
2+
3+
import io.ebean.datasource.DataSourceBuilder;
4+
import io.ebean.datasource.DataSourcePool;
5+
import io.ebean.test.containers.PostgresContainer;
6+
import org.junit.jupiter.api.BeforeAll;
7+
import org.junit.jupiter.api.Test;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
11+
import java.sql.Connection;
12+
import java.sql.SQLException;
13+
import java.util.ArrayList;
14+
import java.util.List;
15+
import java.util.Properties;
16+
17+
class Java21TrimAndShutdownTest {
18+
19+
private static Logger log = LoggerFactory.getLogger(Java21TrimAndShutdownTest.class);
20+
21+
@BeforeAll
22+
static void before() {
23+
PostgresContainer.builder("15")
24+
.port(9999)
25+
.containerName("pool_test")
26+
.dbName("app")
27+
.user("db_owner")
28+
.build()
29+
.startWithDropCreate();
30+
}
31+
32+
@Test
33+
void test() throws InterruptedException, SQLException {
34+
Properties clientInfo = new Properties();
35+
clientInfo.setProperty("ApplicationName", "my-test");
36+
37+
DataSourcePool pool = DataSourceBuilder.create()
38+
.url("jdbc:postgresql://127.0.0.1:9999/app")
39+
.username("db_owner")
40+
.password("test")
41+
.clientInfo(clientInfo)
42+
.maxInactiveTimeSecs(2)
43+
.heartbeatFreqSecs(1)
44+
.trimPoolFreqSecs(1)
45+
.build();
46+
47+
List<Connection> connectionList = new ArrayList<>();
48+
for (int i = 0; i < 50; i++) {
49+
connectionList.add(pool.getConnection());
50+
}
51+
52+
// close them slowly to allow multiple trims
53+
for (Connection connection : connectionList) {
54+
connection.rollback();
55+
connection.close();
56+
Thread.sleep(200);
57+
}
58+
59+
log.info("----------- Sleep allowing trim -------------");
60+
Thread.sleep(9_000);
61+
log.info("----------- Shutdown pool -------------");
62+
pool.shutdown();
63+
}
64+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<configuration scan="true" scanPeriod="10 seconds">
2+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3+
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
4+
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
5+
</encoder>
6+
</appender>
7+
8+
<root level="INFO">
9+
<appender-ref ref="STDOUT"/>
10+
</root>
11+
12+
<logger name="java.lang" level="WARN"/>
13+
<logger name="io.ebean" level="INFO"/>
14+
<logger name="io.avaje.config" level="TRACE"/>
15+
<logger name="io.ebean.docker" level="DEBUG"/>
16+
<logger name="io.ebean.test" level="TRACE"/>
17+
<logger name="io.ebean.datasource" level="TRACE"/>
18+
19+
</configuration>

ebean-datasource/src/main/java/io/ebean/datasource/pool/ConnectionPoolFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
import io.ebean.datasource.DataSourceFactory;
55
import io.ebean.datasource.DataSourcePool;
66

7+
import static java.util.Objects.requireNonNullElse;
8+
79
/**
810
* DataSourceFactory implementation that is service loaded.
911
*/
1012
public final class ConnectionPoolFactory implements DataSourceFactory {
1113

1214
@Override
1315
public DataSourcePool createPool(String name, DataSourceConfig config) {
14-
return new ConnectionPool(name, config);
16+
return new ConnectionPool(requireNonNullElse(name, ""), config);
1517
}
1618
}

ebean-datasource/src/main/java/io/ebean/datasource/pool/ExecutorFactory.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,35 @@
66
import java.util.TimerTask;
77
import java.util.concurrent.ExecutorService;
88
import java.util.concurrent.Executors;
9+
import java.util.concurrent.ThreadFactory;
910

1011
final class ExecutorFactory {
1112

1213
static ExecutorService newExecutor() {
13-
return Executors.newSingleThreadExecutor();
14+
return Executors.newSingleThreadExecutor(factory());
15+
}
16+
17+
private static ThreadFactory factory() {
18+
return runnable -> {
19+
Thread thread = new Thread(runnable);
20+
thread.setName("datasource.reaper");
21+
return thread;
22+
};
1423
}
1524

1625
/**
1726
* Return a new Heartbeat for the pool.
1827
*/
1928
static Heartbeat newHeartBeat(ConnectionPool pool, int freqMillis) {
20-
final Timer timer = new Timer(pool.name() + ".heartbeat", true);
29+
final Timer timer = new Timer(nm(pool.name()), true);
2130
timer.scheduleAtFixedRate(new HeartbeatTask(pool), freqMillis, freqMillis);
2231
return new TimerHeartbeat(timer);
2332
}
2433

34+
private static String nm(String poolName) {
35+
return poolName.isEmpty() ? "datasource.heartbeat" : "datasource." + poolName + ".heartbeat";
36+
}
37+
2538
private static final class TimerHeartbeat implements Heartbeat {
2639

2740
private final Timer timer;

ebean-datasource/src/main/java21/io/ebean/datasource/pool/ExecutorFactory.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44

55
import java.util.concurrent.ExecutorService;
66
import java.util.concurrent.Executors;
7+
import java.util.concurrent.ThreadFactory;
78
import java.util.concurrent.atomic.AtomicBoolean;
89

910
final class ExecutorFactory {
1011

1112
static ExecutorService newExecutor() {
12-
return Executors.newVirtualThreadPerTaskExecutor();
13+
ThreadFactory factory = Thread.ofVirtual().name("datasource.reaper").factory();
14+
return Executors.newThreadPerTaskExecutor(factory);
1315
}
1416

1517
static Heartbeat newHeartBeat(ConnectionPool pool, int freqMillis) {
@@ -27,10 +29,14 @@ private VTHeartbeat(ConnectionPool pool, int freqMillis) {
2729
this.pool = pool;
2830
this.freqMillis = freqMillis;
2931
this.thread = Thread.ofVirtual()
30-
.name(pool.name() + ".heartbeat")
32+
.name(nm(pool.name()))
3133
.unstarted(this::run);
3234
}
3335

36+
private static String nm(String poolName) {
37+
return poolName.isEmpty() ? "datasource.heartbeat" : "datasource." + poolName + ".heartbeat";
38+
}
39+
3440
private void run() {
3541
while (running.get()) {
3642
try {

ebean-datasource/src/test/java/io/ebean/datasource/test/NetworkOutageTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*
1919
* @author Roland Praml, Foconis Analytics GmbH
2020
*/
21+
@Disabled
2122
public class NetworkOutageTest {
2223

2324
static void openPort(int port) throws Exception {

pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,18 @@
2222
<module>ebean-datasource-api</module>
2323
</modules>
2424

25+
<profiles>
26+
<profile>
27+
<id>central</id>
28+
</profile>
29+
<profile>
30+
<id>default</id>
31+
<activation>
32+
<jdk>[21,]</jdk>
33+
</activation>
34+
<modules>
35+
<module>blackbox-tests</module>
36+
</modules>
37+
</profile>
38+
</profiles>
2539
</project>

0 commit comments

Comments
 (0)