Skip to content

Commit ee5fa26

Browse files
committed
Protect against null return value from DataSource.getConnection()
Issue: SPR-15641
1 parent bf66f45 commit ee5fa26

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/CannotGetJdbcConnectionException.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,20 @@
2525
* Fatal exception thrown when we can't connect to an RDBMS using JDBC.
2626
*
2727
* @author Rod Johnson
28+
* @author Juergen Hoeller
2829
*/
2930
@SuppressWarnings("serial")
3031
public class CannotGetJdbcConnectionException extends DataAccessResourceFailureException {
3132

33+
/**
34+
* Constructor for CannotGetJdbcConnectionException.
35+
* @param msg the detail message
36+
* @since 5.0
37+
*/
38+
public CannotGetJdbcConnectionException(String msg) {
39+
super(msg);
40+
}
41+
3242
/**
3343
* Constructor for CannotGetJdbcConnectionException.
3444
* @param msg the detail message

spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ public static Connection getConnection(DataSource dataSource) throws CannotGetJd
7878
return doGetConnection(dataSource);
7979
}
8080
catch (SQLException ex) {
81-
throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex);
81+
throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex);
82+
}
83+
catch (IllegalStateException ex) {
84+
throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + ex.getMessage());
8285
}
8386
}
8487

@@ -102,14 +105,14 @@ public static Connection doGetConnection(DataSource dataSource) throws SQLExcept
102105
conHolder.requested();
103106
if (!conHolder.hasConnection()) {
104107
logger.debug("Fetching resumed JDBC Connection from DataSource");
105-
conHolder.setConnection(dataSource.getConnection());
108+
conHolder.setConnection(fetchConnection(dataSource));
106109
}
107110
return conHolder.getConnection();
108111
}
109112
// Else we either got no holder or an empty thread-bound holder here.
110113

111114
logger.debug("Fetching JDBC Connection from DataSource");
112-
Connection con = dataSource.getConnection();
115+
Connection con = fetchConnection(dataSource);
113116

114117
if (TransactionSynchronizationManager.isSynchronizationActive()) {
115118
logger.debug("Registering transaction synchronization for JDBC Connection");
@@ -134,6 +137,24 @@ public static Connection doGetConnection(DataSource dataSource) throws SQLExcept
134137
return con;
135138
}
136139

140+
/**
141+
* Actually fetch a {@link Connection} from the given {@link DataSource},
142+
* defensively turning an unexpected {@code null} return value from
143+
* {@link DataSource#getConnection()} into an {@link IllegalStateException}.
144+
* @param dataSource the DataSource to obtain Connections from
145+
* @return a JDBC Connection from the given DataSource (never {@code null})
146+
* @throws SQLException if thrown by JDBC methods
147+
* @throws IllegalStateException if the DataSource returned a null value
148+
* @see DataSource#getConnection()
149+
*/
150+
private static Connection fetchConnection(DataSource dataSource) throws SQLException {
151+
Connection con = dataSource.getConnection();
152+
if (con == null) {
153+
throw new IllegalStateException("DataSource returned null from getConnection(): " + dataSource);
154+
}
155+
return con;
156+
}
157+
137158
/**
138159
* Prepare the given Connection with the given transaction semantics.
139160
* @param con the Connection to prepare

spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/AbstractEmbeddedDatabaseConfigurer.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2017 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.
@@ -40,7 +40,9 @@ public void shutdown(DataSource dataSource, String databaseName) {
4040
Connection con = null;
4141
try {
4242
con = dataSource.getConnection();
43-
con.createStatement().execute("SHUTDOWN");
43+
if (con != null) {
44+
con.createStatement().execute("SHUTDOWN");
45+
}
4446
}
4547
catch (SQLException ex) {
4648
logger.warn("Could not shut down embedded database", ex);

spring-jdbc/src/main/java/org/springframework/jdbc/support/DatabaseStartupValidator.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2017 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.
@@ -112,6 +112,10 @@ public void afterPropertiesSet() {
112112
Statement stmt = null;
113113
try {
114114
con = this.dataSource.getConnection();
115+
if (con == null) {
116+
throw new CannotGetJdbcConnectionException("Failed to execute validation query: " +
117+
"DataSource returned null from getConnection(): " + this.dataSource);
118+
}
115119
stmt = con.createStatement();
116120
stmt.execute(this.validationQuery);
117121
validated = true;

0 commit comments

Comments
 (0)