CRITICAL
Rule Definition
A frequent issue when dealing with database resource is resource leak. This mainly comes from an incorrect code that miss to close the connection in any cases. Incorrect resource management is a common source of failures in production applications, with the usual pitfalls being database connections and file descriptors remaining opened after an exception has occurred somewhere else in the code. This leads to application servers being frequently restarted when resource exhaustion occurs, because operating systems and server applications generally have an upper-bound limit for resources.
Remediation
You can:
- close the resource in a finally block (only explicit closing is considered valid)
- or annotate this resource with @Cleanup annotation (lombok.Cleanup)
- or use the try with resource to declare the resource that must be closed (available in java 7)
- or use Spring JDBC Template that open and close the connection for you (http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/jdbc.html)
- or use CDI with @Dispose annotation
Violation Code Sample
String connectionURL = 'jdbc:mysql://localhost:3306/myDB';
Connection connection = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName('com.mysql.jdbc.Driver').newInstance();
connection = DriverManager.getConnection(connectionURL, 'root', 'admin');
st = connection.createStatement();
rs = st.executeQuery('Select * from EMPLOYEE_SALARIES');
while (rs.next()) {
System.out.println('EMPLOYEE_NAME/EMPLOYEE_SALARY');
System.out.println(rs.getString(1) + '/' + rs.getString(2));
}
rs.close();
st.close();
connection.close();
} catch (Exception ex) {
ex.printStackTrace();
} // VIOLATION, rs, st and connection must be closed in a finally
Fixed Code Sample
with finally
~~~~~~~~~~~~
String connectionURL = 'jdbc:mysql://localhost:3306/myDB';
Connection connection = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName('com.mysql.jdbc.Driver').newInstance();
connection = DriverManager.getConnection(connectionURL, 'root', 'admin');
st = connection.createStatement();
rs = st.executeQuery('Select * from EMPLOYEE_SALARIES');
while (rs.next()) {
System.out.println('EMPLOYEE_NAME/EMPLOYEE_SALARY');
System.out.println(rs.getString(1) + '/' + rs.getString(2));
}
} catch (Exception ex) {
ex.printStackTrace();
} finally { // FIX
try {
if (rs != null && !rs.isClosed()) {
rs.close();
}
if (st != null && !st.isClosed()) {
st.close();
}
if (connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
with Java 7
~~~~~~~~~~~~~~
String connectionURL = 'jdbc:mysql://localhost:3306/myDB';
try ( // FIX
Connection connection =
DriverManager.getConnection(connectionURL, 'root', 'admin');
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery('Select * from EMPLOYEE_SALARIES');
) {
Class.forName('com.mysql.jdbc.Driver').newInstance();
while (rs.next())
{
System.out.println('EMPLOYEE_NAME/EMPLOYEE_SALARY');
System.out.println(rs.getString(1) + '/' + rs.getString(2));
}
}
with annotation @Cleanup
~~~~~~~~~~~~~~~~~~~~~~~~
String connectionURL = 'jdbc:mysql://localhost:3306/myDB';
@Cleanup Connection connection = null; // FIX
@Cleanup Statement st = null; // FIX
@Cleanup ResultSet rs = null; // FIX
Class.forName('com.mysql.jdbc.Driver').newInstance();
connection = DriverManager.getConnection(connectionURL, 'root', 'admin');
st = connection.createStatement();
rs = st.executeQuery('Select * from EMPLOYEE_SALARIES');
while (rs.next()) {
System.out.println('EMPLOYEE_NAME/EMPLOYEE_SALARY');
System.out.println(rs.getString(1) + '/' + rs.getString(2));
}
with CDI annotation
~~~~~~~~~~~~~~~~~~~~
@Produces @RequestScoped
Connection connect(User) {
return createConnection(user.getId(), user.getPassword())
}
void close (@Disposes Connection connection) {
connection.close();
}
Reference
http://www.java7developer.com/blog/?p=24
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/jdbc.html
http://projectlombok.org/features/Cleanup.html
Related Technologies
JEE
Technical Criterion
Efficiency - Memory, Network and Disk Space Management
About CAST Appmarq
CAST Appmarq is by far the biggest repository of data about real IT systems. It's built on thousands of analyzed applications, made of 35 different technologies, by over 300 business organizations across major verticals. It provides IT Leaders with factual key analytics to let them know if their applications are on track.