Skip to content

Commit 482c60a

Browse files
committed
Refactored constructors in the ConnectionPool class
1 parent fde2066 commit 482c60a

File tree

1 file changed

+82
-46
lines changed

1 file changed

+82
-46
lines changed

src/javaxt/sql/ConnectionPool.java

Lines changed: 82 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package javaxt.sql;
22

3+
import java.util.Map;
4+
import java.util.HashMap;
35
import java.io.PrintWriter;
46
import java.sql.SQLException;
57
import javax.sql.ConnectionEvent;
@@ -45,93 +47,119 @@ public class ConnectionPool {
4547
private final ConcurrentLinkedQueue<PooledConnectionWrapper> recycledConnections = new ConcurrentLinkedQueue<>();
4648
private final ConcurrentHashMap<PooledConnection, PooledConnectionWrapper> connectionWrappers = new ConcurrentHashMap<>();
4749
private volatile PooledConnection connectionInTransition; // a PooledConnection which is currently within a PooledConnection.getConnection() call, or null
48-
private Database database;
4950

5051
// Validation caching for performance optimization
5152
private final ConcurrentHashMap<PooledConnection, Long> validationCache = new ConcurrentHashMap<>();
5253
private static final long VALIDATION_CACHE_TTL = 30000; // 30 seconds
5354

5455

56+
private Database database;
57+
58+
5559
/**
56-
* Thrown in {@link #getConnection()} or {@link #getValidConnection()} when no free connection becomes
60+
* Thrown in {@link #getConnection()} when no free connection becomes
5761
* available within <code>timeout</code> seconds.
5862
*/
5963
public static class TimeoutException extends RuntimeException {
60-
private static final long serialVersionUID = 1;
61-
public TimeoutException () {
62-
super("Timeout while waiting for a free database connection."); }
63-
public TimeoutException (String msg) {
64-
super(msg);
65-
}
64+
private static final long serialVersionUID = 1;
65+
public TimeoutException () { super("Timeout while waiting for a free database connection."); }
66+
public TimeoutException (String msg) { super(msg); }
6667
}
6768

6869

6970
//**************************************************************************
7071
//** Constructor
7172
//**************************************************************************
7273
public ConnectionPool(Database database, int maxConnections) throws SQLException {
73-
this(database == null ? null : database.getConnectionPoolDataSource(), maxConnections);
74-
if (database == null) throw new IllegalArgumentException("database is required");
75-
this.database = database;
74+
this(database, maxConnections, null);
7675
}
7776

7877

7978
//**************************************************************************
8079
//** Constructor
8180
//**************************************************************************
8281
public ConnectionPool(Database database, int maxConnections, int timeout) throws SQLException{
83-
this(database == null ? null : database.getConnectionPoolDataSource(), maxConnections, timeout);
84-
if (database == null) throw new IllegalArgumentException("database is required");
82+
this(database, maxConnections, new HashMap<String, Object>() {{
83+
put("timeout", timeout);
84+
}});
85+
}
86+
87+
88+
//**************************************************************************
89+
//** Constructor
90+
//**************************************************************************
91+
/** Used to instantiate the ConnectionPool using with a javaxt.sql.Database
92+
* @param database javaxt.sql.Database with database connection information
93+
* including a valid getConnectionPoolDataSource() response. The database
94+
* object provides additional run-time query optimizations (e.g. connection
95+
* metadata).
96+
* @param maxConnections Maximum number of database connections for the
97+
* connection pool.
98+
* @param options Additional pool configuration options including:
99+
* <ul>
100+
* <li>timeout: The maximum time to wait for a free connection, in seconds. Default is 20 seconds.</li>
101+
* <li>idleTimeout: Connection idle timeout in seconds. Default is 300 seconds (5 minutes).</li>
102+
* <li>maxAge: Maximum connection age in seconds. Default is 1800 seconds (30 minutes).</li>
103+
* <li>validationQuery: Query to validate connections. Default is "SELECT 1".</li>
104+
* <li>validationTimeout: Interval used to execute validation queries. Default is 5 seconds.</li>
105+
* </ul>
106+
*/
107+
public ConnectionPool(Database database, int maxConnections, Map<String, Object> options) throws SQLException {
108+
if (database==null) throw new IllegalArgumentException("Database is required");
85109
this.database = database;
110+
init(database.getConnectionPoolDataSource(), maxConnections, options);
86111
}
87112

88113

89114
//**************************************************************************
90115
//** Constructor
91116
//**************************************************************************
92117
public ConnectionPool(ConnectionPoolDataSource dataSource, int maxConnections) {
93-
this(dataSource, maxConnections, null);
118+
init(dataSource, maxConnections, null);
94119
}
95120

96121

97122
//**************************************************************************
98123
//** Constructor
99124
//**************************************************************************
100-
/** Constructs a ConnectionPool object.
101-
* @param dataSource JDBC ConnectionPoolDataSource for the connections.
102-
* @param maxConnections The maximum number of connections.
103-
* @param timeout The maximum time in seconds to wait for a free connection.
104-
* Defaults to 20 seconds
105-
*/
106125
public ConnectionPool(ConnectionPoolDataSource dataSource, int maxConnections, Integer timeout) {
107-
this(dataSource, maxConnections, timeout, null, null, null, null);
126+
init(dataSource, maxConnections, new HashMap<String, Object>() {{
127+
put("timeout", timeout);
128+
}});
108129
}
109130

110131

111132
//**************************************************************************
112133
//** Constructor
113134
//**************************************************************************
114-
/** Constructs a ConnectionPool object with health monitoring configuration.
115-
* @param dataSource JDBC ConnectionPoolDataSource for the connections.
116-
* @param maxConnections The maximum number of connections.
117-
* @param timeout The maximum time to wait for a free connection, in seconds. Default is 20 seconds.
118-
* @param idleTimeout Connection idle timeout in seconds. Default is 300 seconds (5 minutes).
119-
* @param maxAge Maximum connection age in seconds. Default is 1800 seconds (30 minutes).
120-
* @param validationQuery Query to validate connections. Default is "SELECT 1".
121-
* @param validationTimeout
122-
*/
123-
public ConnectionPool(ConnectionPoolDataSource dataSource, int maxConnections,
124-
Integer timeout, Integer idleTimeout, Integer maxAge,
125-
String validationQuery, Integer validationTimeout) {
135+
public ConnectionPool(ConnectionPoolDataSource dataSource, int maxConnections, Map<String, Object> options) throws SQLException {
136+
init(dataSource, maxConnections, options);
137+
}
126138

127139

140+
//**************************************************************************
141+
//** init
142+
//**************************************************************************
143+
private void init(ConnectionPoolDataSource dataSource, int maxConnections, Map<String, Object> options) {
144+
128145
if (dataSource==null) throw new IllegalArgumentException("dataSource is required");
129146
if (maxConnections<1) throw new IllegalArgumentException("Invalid maxConnections");
130-
if (timeout==null) timeout = 20; //20 seconds default
131-
if (timeout<0) throw new IllegalArgumentException("Invalid timeout: " + timeout);
147+
148+
149+
if (options==null) options = new HashMap<>();
150+
Integer timeout = new Value(options.get("timeout")).toInteger();
151+
if (timeout==null || timeout <= 0) timeout = 20; // 20 seconds default
152+
153+
Integer idleTimeout = new Value(options.get("idleTimeout")).toInteger();
132154
if (idleTimeout==null || idleTimeout <= 0) idleTimeout = 300; // 5 minutes default
155+
156+
Integer maxAge = new Value(options.get("maxAge")).toInteger();
133157
if (maxAge==null || maxAge <= 0) maxAge = 1800; // 30 minutes default
134-
if (validationTimeout==null || validationTimeout <= 0) validationTimeout = 5;
158+
159+
Integer validationTimeout = new Value(options.get("validationTimeout")).toInteger();
160+
if (validationTimeout==null || validationTimeout <= 0) validationTimeout = 5; // 5 seconds
161+
162+
String validationQuery = new Value(options.get("validationQuery")).toString();
135163
if (validationQuery == null || validationQuery.trim().isEmpty()) {
136164
validationQuery = "SELECT 1";
137165
}
@@ -193,7 +221,6 @@ public boolean isClosed() {
193221
}
194222

195223

196-
197224
//**************************************************************************
198225
//** getConnection
199226
//**************************************************************************
@@ -597,9 +624,17 @@ public int getTimeout(){
597624
return Math.round(timeoutMs/1000);
598625
}
599626

600-
/**
601-
* Returns the connection idle timeout in seconds.
602-
*/
627+
628+
//**************************************************************************
629+
//** getConnectionIdleTimeout
630+
//**************************************************************************
631+
/** Returns the connection idle timeout in seconds. Connections that remain
632+
* unused in the pool for more than the idle timeout are automatically
633+
* removed. This prevents accumulation of stale connections that may have
634+
* been closed by the database server. Note that this only affects
635+
* connections sitting idle in the pool, not active connections being used
636+
* by your application.
637+
*/
603638
public int getConnectionIdleTimeout() {
604639
return Math.round(connectionIdleTimeoutMs/1000);
605640
}
@@ -946,7 +981,7 @@ private void log (String msg) {
946981
String s = "ConnectionPool: "+msg;
947982
try {
948983
if (logWriter == null) {
949-
System.err.println(s);
984+
//System.err.println(s);
950985
}
951986
else {
952987
logWriter.println(s);
@@ -957,7 +992,6 @@ private void log (String msg) {
957992

958993
private void assertInnerState() {
959994
int active = activeConnections.get();
960-
int recycled = recycledConnections.size();
961995
int total = totalConnections.get();
962996

963997
if (active < 0) {
@@ -1015,7 +1049,6 @@ PooledConnectionWrapper markUsed() {
10151049
}
10161050

10171051

1018-
10191052
//**************************************************************************
10201053
//** getPoolStatistics
10211054
//**************************************************************************
@@ -1037,9 +1070,12 @@ public PoolStatistics getPoolStatistics() {
10371070
);
10381071
}
10391072

1040-
/**
1041-
* Pool statistics for monitoring connection pool health.
1042-
*/
1073+
1074+
//**************************************************************************
1075+
//** PoolStatistics Class
1076+
//**************************************************************************
1077+
/** Pool statistics for monitoring connection pool health.
1078+
*/
10431079
public static class PoolStatistics {
10441080
public final int activeConnections;
10451081
public final int recycledConnections;

0 commit comments

Comments
 (0)