Skip to content

Commit 7dfad3a

Browse files
Add DataSourcePoolNewConnectionListener to set up newly created connection by DataSourcePool.
1 parent 8f8aa2b commit 7dfad3a

File tree

5 files changed

+163
-0
lines changed

5 files changed

+163
-0
lines changed

ebean-datasource-api/src/main/java/io/ebean/datasource/DataSourceBuilder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,11 @@ default DataSourceBuilder listener(DataSourcePoolListener listener) {
379379
@Deprecated(forRemoval = true)
380380
DataSourceBuilder setListener(DataSourcePoolListener listener);
381381

382+
/**
383+
* Set the connection listener to use.
384+
*/
385+
DataSourceBuilder connectionListener(DataSourcePoolNewConnectionListener connectionListener);
386+
382387
/**
383388
* Set a SQL statement used to test the database is accessible.
384389
* <p>
@@ -933,6 +938,11 @@ default String driverClassName() {
933938
*/
934939
DataSourcePoolListener getListener();
935940

941+
/**
942+
* Return the new connection listener to use.
943+
*/
944+
DataSourcePoolNewConnectionListener getConnectionListener();
945+
936946
/**
937947
* Return a SQL statement used to test the database is accessible.
938948
* <p>

ebean-datasource-api/src/main/java/io/ebean/datasource/DataSourceConfig.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public class DataSourceConfig implements DataSourceBuilder.Settings {
8484
private List<String> initSql;
8585
private DataSourceAlert alert;
8686
private DataSourcePoolListener listener;
87+
private DataSourcePoolNewConnectionListener connectionListener;
8788
private Properties clientInfo;
8889
private String applicationName;
8990
private boolean shutdownOnJvmExit;
@@ -477,6 +478,17 @@ public DataSourceConfig setListener(DataSourcePoolListener listener) {
477478
return this;
478479
}
479480

481+
@Override
482+
public DataSourcePoolNewConnectionListener getConnectionListener() {
483+
return connectionListener;
484+
}
485+
486+
@Override
487+
public DataSourceBuilder connectionListener(DataSourcePoolNewConnectionListener connectionListener) {
488+
this.connectionListener= connectionListener;
489+
return this;
490+
}
491+
480492
@Override
481493
public String getHeartbeatSql() {
482494
return heartbeatSql;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.ebean.datasource;
2+
3+
import java.sql.Connection;
4+
5+
/**
6+
* A {@link DataSourcePool} listener which allows you to hook on the create connections process of the pool.
7+
*/
8+
public interface DataSourcePoolNewConnectionListener {
9+
/**
10+
* Called after a connection has been created, before any initialization.
11+
* @param connection the created connection
12+
*/
13+
default void onCreatedConnection(Connection connection) {}
14+
15+
/**
16+
* Called after a connection has been initialized (after onCreatedConnection) and all settings applied.
17+
* @param connection the created connection
18+
*/
19+
default void onAfterInitialized(Connection connection) {}
20+
21+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ interface Heartbeat {
4646
*/
4747
private final DataSourceAlert notify;
4848
private final DataSourcePoolListener poolListener;
49+
private final DataSourcePoolNewConnectionListener connectionListener;
4950
private final List<String> initSql;
5051
private final String user;
5152
private final String schema;
@@ -109,6 +110,7 @@ interface Heartbeat {
109110
this.name = name;
110111
this.notify = params.getAlert();
111112
this.poolListener = params.getListener();
113+
this.connectionListener = params.getConnectionListener();
112114
this.autoCommit = params.isAutoCommit();
113115
this.readOnly = params.isReadOnly();
114116
this.failOnStart = params.isFailOnStart();
@@ -434,6 +436,9 @@ private void testConnection() {
434436
* Initializes the connection we got from the driver.
435437
*/
436438
private Connection initConnection(Connection conn) throws SQLException {
439+
if(connectionListener!=null) {
440+
connectionListener.onCreatedConnection(conn);
441+
}
437442
conn.setAutoCommit(autoCommit);
438443
// isolation level is set globally for all connections (at least for H2) and
439444
// you will need admin rights - so we do not change it, if it already matches.
@@ -470,6 +475,9 @@ private Connection initConnection(Connection conn) throws SQLException {
470475
}
471476
}
472477
}
478+
if(connectionListener!=null) {
479+
connectionListener.onAfterInitialized(conn);
480+
}
473481
return conn;
474482
}
475483

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package io.ebean.datasource.pool;
2+
3+
import io.ebean.datasource.DataSourceConfig;
4+
import io.ebean.datasource.DataSourcePoolNewConnectionListener;
5+
import org.junit.jupiter.api.AfterEach;
6+
import org.junit.jupiter.api.Test;
7+
8+
import java.sql.Connection;
9+
import java.util.HashMap;
10+
import static org.junit.jupiter.api.Assertions.*;
11+
12+
class ConnectionPoolNewConnectionListenerTest {
13+
private ConnectionPool pool;
14+
15+
private final HashMap<Connection, Integer> createdConnections = new HashMap<>();
16+
private final HashMap<Connection, Integer> afterConnections = new HashMap<>();
17+
18+
ConnectionPoolNewConnectionListenerTest() {
19+
pool = createPool();
20+
}
21+
22+
23+
private ConnectionPool createPool() {
24+
25+
DataSourceConfig config = new DataSourceConfig();
26+
config.setDriver("org.h2.Driver");
27+
config.setUrl("jdbc:h2:mem:tests");
28+
config.setUsername("sa");
29+
config.setPassword("");
30+
config.setMinConnections(1);
31+
config.setMaxConnections(5);
32+
config.connectionListener(new DataSourcePoolNewConnectionListener() {
33+
@Override
34+
public void onCreatedConnection(Connection connection) {
35+
synchronized (createdConnections) {
36+
createdConnections.put(connection, 1 + createdConnections.getOrDefault(connection, 0));
37+
createdConnections.notifyAll();
38+
}
39+
}
40+
41+
@Override
42+
public void onAfterInitialized(Connection connection) {
43+
synchronized (afterConnections) {
44+
afterConnections.put(connection, 1 + afterConnections.getOrDefault(connection, 0));
45+
afterConnections.notifyAll();
46+
}
47+
}
48+
});
49+
50+
return new ConnectionPool("initialize", config);
51+
}
52+
53+
@AfterEach
54+
public void after() {
55+
pool.shutdown();
56+
}
57+
58+
@Test
59+
public void initializeNewConnectionTest() {
60+
// Min connections is 1 so one should be created on pool initialization
61+
synchronized (createdConnections) {
62+
assertEquals(1, createdConnections.size());
63+
assertEquals(1, afterConnections.size());
64+
}
65+
66+
try (Connection connection = pool.getConnection()) {
67+
assertNotNull(connection);
68+
synchronized (createdConnections) {
69+
assertEquals(1, createdConnections.size());
70+
}
71+
synchronized (afterConnections) {
72+
assertEquals(1, afterConnections.size());
73+
}
74+
} catch (Exception e) {
75+
fail(e.getMessage());
76+
}
77+
78+
try (Connection connection = pool.getConnection()) {
79+
assertNotNull(connection);
80+
synchronized (createdConnections) {
81+
assertEquals(1, createdConnections.size());
82+
}
83+
synchronized (afterConnections) {
84+
assertEquals(1, afterConnections.size());
85+
}
86+
87+
try (Connection connection2 = pool.getConnection()) {
88+
assertNotNull(connection2);
89+
synchronized (createdConnections) {
90+
assertEquals(2, createdConnections.size());
91+
}
92+
synchronized (afterConnections) {
93+
assertEquals(2, afterConnections.size());
94+
}
95+
}
96+
} catch (Exception e) {
97+
fail(e.getMessage());
98+
}
99+
synchronized (createdConnections) {
100+
for (var entry : createdConnections.entrySet()) {
101+
// It should be always 1
102+
assertEquals(1, entry.getValue());
103+
}
104+
}
105+
synchronized (afterConnections) {
106+
for (var entry : afterConnections.entrySet()) {
107+
// It should be always 1
108+
assertEquals(1, entry.getValue());
109+
}
110+
}
111+
}
112+
}

0 commit comments

Comments
 (0)