STS/Eclipse showing Potential resource leak, why? - java

I have a service method which connects to MySQL and get data in ResultSet and in finally closed it's PreparedStatement, but STS showing a warning at return statement as
Potential resource leak: 'resultSet' may not be closed at this
location
Method:
public boolean checkData() {
Connection dbConnection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
boolean status = false;
try {
dbConnection = icrud.getConnection();
preparedStatement = dbConnection.prepareStatement("query on table");
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
status = resultSet.getBoolean("STATUS");
}
return status; //Potential resource leak warning shows here.
} catch (Exception e) {
LOGGER.error("Exception Occurred:: " , e);
} finally {
try {
if (preparedStatement != null) {
preparedStatement.close();
preparedStatement = null;
}
} catch (SQLException e) {
LOGGER.error("Exception Occured while Closing statement" , e);
}
try {
if (dbConnection != null) {
dbConnection.close();
dbConnection = null;
}
} catch (SQLException e) {
LOGGER.error("Exception Occured while closing connection" , e);
}
}
return status;
}
As per Doc,
When a Statement object is closed, its current ResultSet object, if
one exists, is also closed.
So I am closing Statement in finally though its showing warning. I have checked by closing result set in finally still warning doesn't go off.
Is it false positive? or Am I doing something wrong?

You are returning "status" without closing your connections. The "finally" clause isn't executed when you get to the return statement.

Related

Why are connections not getting closed?

I have a code where I am connecting to db using a resultset and then after getting the necessary values closing the connection in finally block.
But for some reason the query is still running and the connection pool is not release.
Can someone help here.
try {
rsU = dbAccess.query(FasoCommon.sqlUpdatable, params, true);
if (rsU.next()) {
updatable = rsU.getString("UpdatableFields");
logger.info("UpdatableFields:: "+updatable);
}
}
finally {
close(rsU, null, null);
}
private void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
rs=null;
//logger().info("ResultSet Closed : " + rs);
} catch (SQLException e) {
//logger().error("The result set cannot be closed.", e);
}
}
if (stmt != null) {
try {
stmt.close();
stmt=null;
//logger().info("Statement Closed : " + stmt);
} catch (SQLException e) {
//logger().error("The statement cannot be closed.", e);
}
}
if (conn != null) {
try {
conn.close();
conn=null;
//logger().info("Data Source Connection Closed : " + conn);
} catch (SQLException e) {
}
}
}
In finally block, Connection object is being passed as null and even Statement object is also being passed as null.
finally {
close(rsU, null, null);
}
Check them and pass these object references, if you have access to them and
non-null references, pass to that close() method and check.
there was an set object which was keeping the refence to the connection even after closing the connection.Fixing that part resolved the issue.

java.sql.SQLException: ORA-01000: maximum open cursors exceeded while truncating tables

I get this exception while truncating all table in a schema.
I truncate 3 schema in my Java code and first method get list of table names from given schema name and second method executes "TRUNCATE TABLE table_name" query.
I confused about my code always succesful while truncating first and third schema. But while executing on second schema I get ORA-01000 error.
My truncate code is
private void truncateTable(Connection conn, String tableName) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(Utility.TRUNCATE_TABLE + tableName);
ps.executeUpdate();
} catch (SQLException e) {
log.error("SQLException occured while getting table names from schema", e);
} finally {
Utility.free(ps, null, null);
}
}
private List<String> getAllTableNames(Connection conn) {
PreparedStatement ps = null;
ResultSet rs = null;
List<String> list = new ArrayList<String>();
try {
ps = conn.prepareStatement(Utility.SELECT_ALL_TABLE_NAMES);
rs = ps.executeQuery();
while (rs.next()) {
list.add(rs.getString("TABLE_NAME"));
}
} catch (SQLException e) {
log.error("SQLException occured while getting table names from schema", e);
} finally {
Utility.free(ps, rs, null);
}
return list;
}
public static void free(PreparedStatement ps, ResultSet rs, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
log.error("Error occurred while closing ResultSet",e);
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
log.error("Error occurred while closing PreparedStatement",e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
log.error("Error occurred while closing Connection",e);
}
}
}
What is the wrong about code or is it about schema configuraiton in Oracle?
How can I solve this?
If are you iterating over the List generated by getAllTableNames and calling truncateTable in a tight loop, your free calls in the finally block might just be delayed and stacking up to an extent that they aren't clearing fast enough for the next iterations - since you only know the finally will be called at some point, not necessarily immediately and before control is returned to the caller.
The schema size would make a difference to that, so it might make sense that a small schema succeeds and a large one fails. If that is what's happening then you should call free inside the try, as well as in the finally:
private void truncateTable(Connection conn, String tableName) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(Utility.TRUNCATE_TABLE + tableName);
ps.executeUpdate();
Utility.free(ps, null, null);
ps = null;
} catch (SQLException e) {
log.error("SQLException occured while getting table names from schema", e);
} finally {
if (ps != null) {
Utility.free(ps, null, null);
}
}
}
If Utility.free checks whether ps is null then that check in the finally block might be redundant, but without it, free would be called twice if there is no SQLException.
Check out the code and make sure you are closing the cursors after being used. If the problem still persists please set OPEN_CURSORS to some more value.

Fail to cleanup java.sql.Statement on checked Exception

In my method show below find bug is specifying Fail to cleanup java.sql.Statement on checked Exception
public int updateSecurityCodeHistoryForMessage(String phone, String securityCodeHistoryId, String messageState, String messageId, String parentMessageId)
{
CaptivePortalLogger.appLog.error(MODULE+"Start : updateSecurityCodeHistoryForMessage::"+messageState);
int result=-1;
String query=null;
Connection con = null;
PreparedStatement pstmt =null;
try
{
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Available Connection : "+ CaptivePortalDBConnection.getNumIdleConnections());
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Active Connection : "+ CaptivePortalDBConnection.getNumActiveConnections() );
con = CaptivePortalDBConnection.getDataSource().getConnection();
CaptivePortalLogger.appLog.error(MODULE+" Before updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: ");
query="UPDATE tblsecuritycodehistory SET messagestate = ?,messageid = ? WHERE securitycodehistoryid = ? AND mobileno = ?";
CaptivePortalLogger.appLog.debug(MODULE + "for updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport Query : "+ query);
pstmt = con.prepareStatement(query);
pstmt.setString(1,messageState); //<b>line 556</b>
pstmt.setString(2,messageId);
pstmt.setString(3,securityCodeHistoryId);
pstmt.setString(4,phone);
result = pstmt.executeUpdate();
CaptivePortalLogger.appLog.error(MODULE+" After updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: result::"+result);
}
catch (Exception e) {
result = -1;
CaptivePortalLogger.traceLog.debug("Got an exception while updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport: ",e);
}
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try
{
if(pstmt!=null)
pstmt.close();
if(con !=null)
con.close();
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
catch(Exception e)
{
CaptivePortalLogger.traceLog.debug("Error in closing sqlReader.",e);
}
}
CaptivePortalLogger.appLog.error(MODULE+"End : updateSecurityCodeHistoryForMessage");
return result;
}
I find lots of links on stack but none of them able to solve my problem(may be i m not able to understand them properly). Any help will be appreciated.
Thanks in Advance..........
After updaing my finally block with a solution specfied by #Mark problem persists
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try {
if(pstmt!=null)
pstmt.close();
} catch (Exception ex) {
// Log, ignore, etc
}
try {
if(con !=null)
con.close();
} catch (Exception ex) {
// Log, ignore, etc
}
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
After using #Jon suggestion , my problem get resolved. finally resolved code is ::
public int updateSecurityCodeHistoryForMessage(String phone, String securityCodeHistoryId, String messageState, String messageId, String parentMessageId)
{
CaptivePortalLogger.appLog.error(MODULE+"Start : updateSecurityCodeHistoryForMessage::"+messageState);
int result=-1;
String query=null;
Connection con = null;
PreparedStatement pstmt =null;
try
{
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Available Connection : "+ CaptivePortalDBConnection.getNumIdleConnections());
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Active Connection : "+ CaptivePortalDBConnection.getNumActiveConnections() );
con = CaptivePortalDBConnection.getDataSource().getConnection();
CaptivePortalLogger.appLog.error(MODULE+" Before updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: ");
query="UPDATE tblsecuritycodehistory SET messagestate = ?,messageid = ? WHERE securitycodehistoryid = ? AND mobileno = ?";
CaptivePortalLogger.appLog.debug(MODULE + "for updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport Query : "+ query);
try
{
pstmt = con.prepareStatement(query);
pstmt.setString(1,messageState);
pstmt.setString(2,messageId);
pstmt.setString(3,securityCodeHistoryId);
pstmt.setString(4,phone);
result = pstmt.executeUpdate();
}
catch(SQLException e1)
{
CaptivePortalLogger.traceLog.debug("Error in closing sqlReader.",e1);
}
finally{
if(pstmt!=null)
pstmt.close();
}
CaptivePortalLogger.appLog.error(MODULE+" After updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: result::"+result);
}
catch (SQLException e2) {
result = -1;
CaptivePortalLogger.traceLog.debug("Got an exception while updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport: ",e2);
}
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try
{
if(con !=null)
con.close();
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
catch(SQLException e)
{
CaptivePortalLogger.traceLog.debug("Error in closing sqlReader.",e);
}
}
CaptivePortalLogger.appLog.error(MODULE+"End : updateSecurityCodeHistoryForMessage");
return result;
}
Look at this code:
if(pstmt!=null)
pstmt.close();
if(con !=null)
con.close();
Now consider that pstmt.close() can throw an exception... which means con.close() wouldn't be called.
If you're using Java 7, use a try-with-resources statement instead, but otherwise you should have a separate try/finally block for each resource.
try {
connection = ...;
try {
statement = ...;
} finally {
// Clean up statement
}
} finally {
// Clean up connection
}
I'd also strongly recommend against catching blanket Exception - it's better to catch specific exceptions which you can actually handle, and let other exceptions propagate up the stack. Also, you appear to be using integer values to signal success or failure of your method - that's not idiomatic Java; exceptions are preferred for error handling, in general.
The problem is that if pstmt.close() throws an Exception, then the connection is never closed.
Either do not close the statement in the finally (as drivers are required to close Statement objects if the Connection is closed), or put both in their own try..catch-block. Eg:
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try {
if(pstmt!=null)
pstmt.close();
} catch (Exception ex) {
// Log, ignore, etc
}
try {
if(con !=null)
con.close();
} catch (Exception ex) {
// Log, ignore, etc
}
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
Firebug is correct.
You should close all your SQL resources in a finally block, using individually wrapped calls to close methods.
You can do it with a utility class:
package persistence;
public class DatabaseUtils {
// similar methods for ResultSet and Connection
public static void close(Statement s) {
try {
if (s != null) {
s.close();
}
} catch (SQLException e) {
// Log the exception
}
}
}
Call the close method in a finally block in the method that created the resource.
Try to cleanup /close resource in separate try/catch/finally block otherwise if any one throw an exception then rest of will be remain unclosed.

Handling all exceptions when executing SQL in Java

There are many steps involved in executing one SQL statement in Java:
Create connection
Create statement
Execute statement, create resultset
Close resultset
Close statement
Close connection
At each of these steps SQLException can be thrown. If we to handle all exception and release all the resources correctly, the code will will look like this with 4 levels of TRY stacked on the top of each other.
try {
Connection connection = dataSource.getConnection();
try {
PreparedStatement statement = connection.prepareStatement("SELECT 1 FROM myTable");
try {
ResultSet result = statement.executeQuery();
try {
if (result.next()) {
Integer theOne = result.getInt(1);
}
}
finally {
result.close();
}
}
finally {
statement.close();
}
}
finally {
connection.close();
}
}
catch (SQLException e) {
// Handle exception
}
Can you propose a better (shorter) way to execute a statement while still release all the consumed resources?
If you are using Java 7, the try with resources statement will shorten this quite a bit, and make it more maintainable:
try (Connection conn = ds.getConnection(); PreparedStatement ps = conn.prepareStatement(queryString); ResultSet rs = ps.execute()) {
} catch (SQLException e) {
//Log the error somehow
}
Note that closing the connection closes all associated Statements and ResultSets.
Check out Apache Commons DbUtils, and in particular the closeQuietly() method. It will handle the connection/statement/result set closing correctly, including the cases where one or more are null.
An alternative is Spring JdbcTemplate, which abstracts a lot of work away from you, and you handle your database queries in a much more functional fashion. You simply provide a class as a callback to be called on for every row of a ResultSet. It'll handle iteration, exception handling and the correct closing of resources.
I create a utility class with static methods I can call:
package persistence;
// add imports.
public final class DatabaseUtils {
// similar for the others Connection and Statement
public static void close(ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (Exception e) {
LOGGER.error("Failed to close ResultSet", e);
}
}
}
So your code would be:
Integer theOne = null;
Connection connection = null;
PreparedStatement statment = null;
ResultSet result = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
while (result.next()) {
theOne = result.getInt(1);
}
} catch (SQLException e) {
// do something
} finally {
DatabaseUtils.close(result);
DatabaseUtils.close(statement);
DatabaseUtils.close(connection);
}
return theOne;
I'd recommend instantiating the Connection outside this method and passing it in. You can handle transactions better that way.
Connection connection = null;
PreparedStatement statement = null;
ResultSet result = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
if (result.next()) {
Integer theOne = result.getInt(1);
}
}
catch (SQLException e) { /* log error */ }
finally {
if (result != null) try { result.close(); } catch (Exception e) {/*log error or ignore*/}
if (statement != null) try { statement.close(); } catch (Exception e) {/*log error or ignore*/}
if (connection != null) try { connection.close(); } catch (Exception e) {/*log error or ignore*/}
}
Just close the Connection, this releases all resources*. You don't need to close Statement and ResultSet.
*just make sure you don't have any active transactions.
Your code can be shortened and written in this way...
Connection connection = dataSource.getConnection();
PreparedStatement statement = null;
ResultSet result = null;
try {
statement= connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
if (result.next()) {
Integer theOne = result.getInt(1);
}
} catch (SQLException e) {
// Handle exception
} finally {
if(result != null) result.close();
if(statement != null) statement.close();
if(connection != null) connection.close();
}

Is that the best way to release SQLite connection in Java?

I need a good way to close SQLIte connections in Java. After a few suggestion by other users I decided to add to my code a finally block to be sure that closing operation are always executed.
public static boolean executeQuery(String query)
{
Connection conn = null;
Statement stmt = null;
try
{
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection(Global.dbPath);
stmt = conn.createStatement();
stmt.execute(query);
return true;
}
catch(ClassNotFoundException e)
{
System.out.println(e);
return false;
}
catch(SQLException e)
{
System.out.println(e);
return false;
}
finally
{
try
{
stmt.close();
conn.close();
return true;
}
catch (SQLException ex)
{
System.out.println ("Errore closing connections");
return false;
}
}
}
I'm not sure that this is the best solution.
How can I optimize this for readability?
A few comments; nutshells:
Separate the SQL exceptions from the reflection exception.
Are your SQL exceptions recoverable? If not, throw an app-specific RuntimeException.
Wrap up the connection and statement close exceptions in a utility method, yours or a 3rd party's.
Don't short-change exception handling; dump the stack trace.
This leads to the following:
public static boolean executeQuery(String query) {
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
throw new DbException("Could not find JDBC driver", e);
}
Connection conn = null;
Statement stmt = null;
try {
conn = DriverManager.getConnection(Global.dbPath);
stmt = conn.createStatement();
stmt.execute(query);
return true;
} catch(SQLException e) {
throw new DbException("Exception during statement execution", e);
} finally {
DbUtils.closeQuietly(conn);
DbUtils.closeQuietly(stmt);
}
}
(I'm using Apache Commons' DbUtils for its closeQuietly, it checks for null (yours didn't). Your own version might throw an app-specific exception as I do here with DbException. This wraps up all your DB-related exceptions into a single exception class, which may or may not be what you need.
If you want to make sure a command is executed you have to put it alone into a try catch block:
try {
stmt.close();
}
catch (Exception ex) {
}
try {
conn.close();
}
catch (Exception ex) {
System.out.println ("Error closing connections");
return false;
}

Categories