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.
Related
I'm having a problem with Resultset during while loop. It's giving me an error java.sql.SQLException: Operation not allowed after ResultSet closed and I can't figure this out. Can anyone help me out? Thanks!
public static void CandidatesPartyList_JComboBox() {
try {
conn1 = VotingSystem.con();
ps = conn1.prepareStatement("SELECT * FROM partylist WHERE p_status = 'Active' ORDER BY p_name ASC");
rs = ps.executeQuery();
candidates_filter_partylist.removeAllItems();
candidates_filter_partylist.addItem("- Select PartyList -");
while (rs.next()) { **<< The problem is coming from here**
candidates_filter_partylist.addItem(rs.getString("p_name"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn1 != null) {
try {
conn1.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
You've got static variables named conn1, ps, and rs. Static means there is only one variable for the entire virtual machine.
Clearly then, CandidatesPartyList_JComboBox is called twice by different threads and thus the variables are overwritten.
The solution is: None of those things should be fields. They should be local variables, and you should be using try-with-resources, which makes this code less than half the size and fixes the problem. Let's also fix the bad error handling ('print the stack trace' is not handling things, so never write that and update your IDE templates).
public static void CandidatesPartyList_JComboBox() {
try (Connection c = VotingSystem.con();
PreparedStatement ps = c.prepareStatement("SELECT * FROM partylist WHERE p_status = 'Active' ORDER BY p_name ASC");
ResultSet rs = ps.executeQuery()) {
candidates_filter_partylist.removeAllItems();
candidates_filter_partylist.addItem("- Select PartyList -");
while (rs.next()) {
candidates_filter_partylist.addItem(rs.getString("p_name"));
}
} catch (SQLException e) {
throw new RuntimeException("Unhandled", e);
}
}
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.
I have a function like this:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
Connection conn = null; // connection object
Statement stmt = null; // statement object
ResultSet rs = null; // result set object
DatabaseMetaData metadata = null;
try {
conn = getConnection(); // without Connection, cannot do much
metadata = conn.getMetaData();
rs = metadata.getTables(null, null, "%", null);
if (checkDefaultTables(rs)) {
lStatus.setText("Message: Please insert 2 tables recommend");
}
} catch(ClassNotFoundException ce) {
// if the driver class not found, then we will be here
System.out.println(ce.getMessage());
} catch(SQLException e) {
// something went wrong, we are handling the exception here
if (conn != null) {
conn.rollback();
conn.setAutoCommit(true);
}
System.out.println("--- SQLException Caught ---");
// iterate and get all of the errors as much as possible
while (e != null) {
System.out.println("Message: " + e.getMessage());
System.out.println("SQLState: " + e.getSQLState());
System.out.println("ErrorCode: " + e.getErrorCode());
System.out.println("---");
e = e.getNextException();
}
} finally {
// close the db resources
try {
rs.close();
stmt.close();
conn.close();
} catch(Exception e) {
//System.out.println("Exception: " + e.getMessage());
}
}
}
I get a error is exception required in lines conn = getConnection(), conn.rollback(), and conn.setAutoCommit(true). I try to add throws SQLException, Exception after private void formWindowOpened(java.awt.event.WindowEvent evt) but I can't edit this line.
How do I add exceptions for this situation?
P/S: I'm using NetBean IDE and I'm a newbie.
Why can't you edit the signature?
Is it coming from a superclass? Do you have access to it? You should consult the author of the API to include your needs there. There is no option to extend the exception list of method in a subclass (though can be omitted though).
OTOH, you can throw unmanaged exceptions (subclasses of RuntimeException). They neither have to be declared nor handled (like NumberFormatException, IndexOutOfBoundsException).
Take a look on the Exceptions chapter of the official Java Tutorial to clarify the base concepts of the language.
I have a servlet deployed on a Jetty 9 server that connects to a MySQL 5.6.17 server using the Connector/J JDBC driver from http://dev.mysql.com/downloads/connector/j/5.0.html.
This particular servlet fires a SQL statement inside a for loop that iterates around 10 times. I have to include the
DriverManager.getConnection(DB_URL, USER, PASSWORD);
line within this loop because the connection closes automatically after the SQL statement has been executed in every iteration of the loop.
Is there a way to keep the connection open, so that getConnection() need be executed only once before the loop starts and then i can manually close it in the finally block.
I have found many posts on this particular issue, but all refer to the connection pooling concept as the solution. But i am just interested in avoiding the connection being closed automatically after each query execution. Shouldn't this be a simple parameter? I am not facing any particular performance problem right now, but it just seems to be a waste of processor and network cycles.
Servlet Code :
public class CheckPhoneNumberRegistrationServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException {
System.err.println("started CheckPhoneNumberRegistrationServlet");
// define database connection details
final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
final String DB_URL = DatabaseParameters.SlappDbURL;
final String USER = DatabaseParameters.DbServer_Username;
final String PASSWORD = DatabaseParameters.DbServer_Password;
PreparedStatement prpd_stmt = null;
Connection conn = null;
ResultSet rs = null;
int resultValue;
// open a connection
/*try {
conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
} catch (SQLException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}*/
JsonParser jsparser;
JsonElement jselement;
JsonArray jsrequestarray;
JsonArray jsresponsearray = new JsonArray();
StringBuffer jb = new StringBuffer();
String line = null;
try {
BufferedReader reader = req.getReader();
while ((line = reader.readLine()) != null)
jb.append(line);
} catch (Exception e) {
e.printStackTrace();
}
try {
jsparser = new JsonParser();
jselement = (JsonElement) jsparser.parse(jb.toString());
jsrequestarray = jselement.getAsJsonArray();
for (int i = 0; i < jsrequestarray.size(); i++) {
// System.err.println("i : " + i +
// jsrequestarray.get(i).toString());
try {
conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
prpd_stmt = conn
.prepareStatement("select slappdb.isPhoneNumberRegistered(?)");
prpd_stmt.setString(1, jsrequestarray.get(i).toString()
.replace("\"", ""));
rs = prpd_stmt.executeQuery();
if (rs.first()) {
//System.err.println("result sert from sql server : " + rs.getString(1));
//slappdb.isPhoneNumberRegistered() actually returns Boolean
//But converting the result value to int here as there is no appropriate into to Boolean conversion function available.
resultValue = Integer.parseInt(rs.getString(1));
if(resultValue == 1)
jsresponsearray.add(jsparser.parse("Y"));
else if(resultValue == 0)
jsresponsearray.add(jsparser.parse("N"));
else throw new SQLException("The value returned from the MySQL Server for slappdb.isPhoneNumberRegistered(" + jsrequestarray.get(i).toString().replace("\"", "") + ") was unexpected : " + rs.getString(1) + ".\n");
// System.err.println("y");
}
else throw new SQLException("Unexpected empty result set returned from the MySQL Server for slappdb.isPhoneNumberRegistered(" + jsrequestarray.get(i).toString().replace("\"", "") + ").\n");
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (prpd_stmt != null)
prpd_stmt.close();
} catch (SQLException e1) {
}
try {
if (conn != null)
conn.close();
} catch (SQLException e1) {
}
}
}
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("text/plain");
// resp.setContentLength(1024);
resp.getWriter().write(jsresponsearray.toString());
System.err.println(jsresponsearray.toString());
} catch (Exception e) {
// crash and burn
System.err.println(e);
}
The problem is that you're closing the connection inside the for loop. Just move both statements: connection opening and connection close, outside the loop.
conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
for (int i = 0; i < jsrequestarray.size(); i++) {
try {
//current code...
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (prpd_stmt != null)
prpd_stmt.close();
} catch (SQLException e1) {
}
}
}
try {
if (conn != null)
conn.close();
} catch (SQLException e1) {
}
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();
}