java.sql.SQLException: Invalid state, the CallableStatement object is closed - java

The code below generates this exception:
java.sql.SQLException: Invalid state, the CallableStatement object is closed.
at net.sourceforge.jtds.jdbc.JtdsCallableStatement.checkOpen(JtdsCallableStatement.java:120)
at net.sourceforge.jtds.jdbc.JtdsStatement.getConnection(JtdsStatement.java:1207)
at net.sourceforge.jtds.jdbc.JtdsResultSet.getConnection(JtdsResultSet.java:409)
at net.sourceforge.jtds.jdbc.JtdsResultSet.close(JtdsResultSet.java:470)
at org.apache.tomcat.dbcp.dbcp.DelegatingResultSet.close(DelegatingResultSet.java:152)
at
This code below sometimes generates the error above, but sometimes does not:
private void doRequest(HttpServletRequest request) throws IOException, ServletException {
CallableStatement stmt = null;
ResultSet rs = null;
String someString;
try {
this.connectDB();
stmt = this.conn.prepareCall("{call sp_SomeSP1(?)}");
stmt.setLong(1, someFunc());
rs = stmt.executeQuery();
while (rs.next()) {
if (rs.getInt(1)==someOtherFunc()) {
someString = rs.getString(2);
break;
}
}
stmt = conn.prepareCall("{call sp_someSP(?, ?)}");
stmt.setLong(1, someFunc());
stmt.setTimestamp(2, new Timestamp(getFrom().getTime()));
rs = stmt.executeQuery();
if (rs.next()) {
lastUpdated = rs.getTimestamp("LastUpdated");
}
request.setAttribute("lastUpdated", lastUpdated);
LOGGER.debug("Forwarding to view...");
getServletContext().getRequestDispatcher("/SomeJSP.jsp").forward(this.request, this.response);
} catch (NamingException e) {
LOGGER.error("Database connection lookup failed", e);
sendError("Server Error");
} catch (SQLException e) {
LOGGER.error("Query failed", e);
sendError("Server Error");
} catch (IllegalStateException e) {
LOGGER.error("View failed", e);
} finally {
try {
if (rs!=null) rs.close();
} catch (NullPointerException e) {
LOGGER.error("Result set closing failed", e);
} catch (SQLException e) {
LOGGER.error("Result set closing failed", e);
}
try {
if (stmt!=null) stmt.close();
} catch (NullPointerException e) {
LOGGER.error("Statement closing failed", e);
} catch (SQLException e) {
LOGGER.error("Statement closing failed", e);
}
try {
this.closeDB();
} catch (NullPointerException e) {
LOGGER.error("Database connection closing failed", e);
} catch (SQLException e) {
LOGGER.error("Database connection closing failed", e);
}
}
What this means is that doRequest() most of the time works properly, but sometimes we get HTTP error 500, and if we check tomcat logs we see:
java.sql.SQLException: Invalid state, the CallableStatement object is closed.

You seem to be using a member variable with a Servlet (the conn variable). however, Servlets can normally be called by multiple threads simultaneously. how are you ensuring that multiple threads are not accidentally using/closing the same Connection?

stmt.setLong(1, someFunc());
stmt.setTimestamp(3, new Timestamp(getFrom().getTime()));
It will be
stmt.setLong(1, someFunc());
stmt.setTimestamp(2, new Timestamp(getFrom().getTime()));

Seeing this error message org.apache.tomcat.dbcp.dbcp.DelegatingResultSet.close in the stack trace, it looks like you are getting error while closing the resultset.
I would advice you to change your resultset check if condition to check whether result set is still open before closing it as:
if (rs!=null && ! rs.isClosed()){
//resultset is there and not in closed state
rs.close();
}

Related

Try with resources Statement for JDBC in java

Useful piece of code for Hive JDBC:
Connection con = null;
Statement stmt = null
try {
Class.forName("org.apache.hive.jdbc.HiveDriver");
con = DriverManager.getConnection(connectionUri, userName, password);
stmt = con.createStatement();
stmt.executeUpdate(query);
} catch (ClassNotFoundException cex) {
cex.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
I want to remove try - catch in finally block.
So I tried The try-with-resources Statement.
try (Class.forName("org.apache.hive.jdbc.HiveDriver");
Connection con = DriverManager.getConnection(connectionUri, userName, password);
Statement stmt = con.createStatement();){
stmt.executeUpdate(query);
} catch (ClassNotFoundException cex) {
cex.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
I think this is not the right way.
Class.forName("org.apache.hive.jdbc.HiveDriver") should not be in try. Should I make a separate try-catch for this?
try {
Class.forName("org.apache.hive.jdbc.HiveDriver");
} catch (ClassNotFoundException cex) {
cex.printStackTrace();
}
try (Connection con = DriverManager.getConnection(connectionUri, userName, password);
Statement stmt = con.createStatement();){
stmt.executeUpdate(query);
} catch (SQLException e) {
e.printStackTrace();
}
Is this right way or am I missing any thing?
The idea behind try-with-ressource is to close an AutoCloseable class.
So every usage of a class which should be closed after using it (a Ressource) can be used with try-with-ressource (like Connection for example). You don't have to take care of closing it manually (in an finally block for example).
So yes, your idea is right:
try/catch for Class.forName("org.apache.hive.jdbc.HiveDriver"); - because this is not AutoCloseable
try-with-ressource for Connection con = DriverManager.getConnection(connectionUri, userName, password);
Statement stmt = con.createStatement();- because Connection and Statement implement AutoCloseable
Reference:
https://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html
When you're using Java 6 or better and the Apache Hive JDBC driver is JDBC 4 compliant or better* then you do not need the Class.forName("org.apache.hive.jdbc.HiveDriver") stuff at all.
Therefore you can just remove the entire try/catch block from your second solution and you're good to go with just:
try (Connection con = DriverManager.getConnection(connectionUri, userName, password);
Statement stmt = con.createStatement()) {
stmt.executeUpdate(query);
} catch (SQLException e) {
e.printStackTrace();
}
* Which is the case for version 1.2.0 or newer of the Hive JDBC driver

MySQL timing out? Can't tell what's going on, Java

i'm running this method to update an SQL using DBCP connection pooling:
After exactly 8 times, the method setValue stops doing so, and no data is sent.
public static void setValue(String user, Integer id){
Connection connection = null;
try {
try {
connection = DataSource.getInstance().getConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (PropertyVetoException e) {
e.printStackTrace();
}
ttl++;
PreparedStatement ps = connection.prepareStatement("REPLACE INTO " + "accounts"+ " (user,id) VALUES(?,?)");
ps.setString(1, user);
ps.setInt(2, id);
ps.executeUpdate();
ps.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
return;
}
I am not familiar with MySQL or connection pooling, i do not know what is going wrong here. Please help me troubleshoot this or provide any suggestions? Thank you so much!
Yes, you should be closing your connection, which will simply return it to the pool. Basically you should add this in a finally {} block in your method. Hope this helps.
public static void setValue(String user, Integer id){
Connection connection = null;
try {
try {
connection = DataSource.getInstance().getConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (PropertyVetoException e) {
e.printStackTrace();
}
ttl++;
PreparedStatement ps = connection.prepareStatement("REPLACE INTO " + "accounts"+ " (user,id) VALUES(?,?)");
ps.setString(1, user);
ps.setInt(2, id);
ps.executeUpdate();
ps.close();
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
if (connection != null) connection.close();
}
return;
}
My guess is that you are just using all the connections in your pool
try putting in a finally block
finally {
connection.close();
}
Even though you are using a connection pool you still have to close the connection - it's just that the connection pool doesn't actually close it, it just returns it to the pool so someone else can use it.
Use a try catch finally block, commit your connection in the try, close your prepared statement in the finally, and on exception rollback.
public static void setValue(String user, Integer id){
Connection connection = null;
try {
try {
connection = DataSource.getInstance().getConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (PropertyVetoException e) {
e.printStackTrace();
}
ttl++;
PreparedStatement ps = connection.prepareStatement("REPLACE INTO " + "accounts"+ " (user,id) VALUES(?,?)");
ps.setString(1, user);
ps.setInt(2, id);
ps.executeUpdate();
connection.commit();
} catch (SQLException ex) {
connection.rollback();
ex.printStackTrace();
}
finally {
ps.close();
}
return;
}

how to handle an exception occured in finally block

In the following code snippet,
try
{
Statement stmt = conect.getConnection();
stmt.executeUpdate(query);
}
catch(SQLException e)
{
//handle exception
}
finally
{
try{ stmt.close(); }
catch(SQLException ignore){}
}
what happens when an exception occurs in the finally block while executing stmt.close();.
Is there a better way to handle these kind of problems?
sometimes connections is not open because of some exception but finally block close that connection. To avoid this Exception check out following code.
try{
Statement stmt = conect.getConnection();
stmt.executeUpdate(query);
}catch(SQLException e){
//handle exception
}finally{
try{
if(stmt != null){
stmt.close();
}
}
catch(SQLException ignore){}
}
finally
{
if( stmt != null ) {
try {
stmt.close();
}
catch(SQLException ex ) {
ex.printStackTrace();
}
}
}
Problems which might occur is that a statement isn't closed and then you will get an error when trying to reuse it.
try:
Statement stmt = null;
try {
stmt = conect.getConnection();
stmt.executeUpdate(query);
}
catch(SQLException e) {
//handle exception
}
finally
{
try{ if(stmt!=null)stmt.close(); }
catch(SQLException ignore){}
}
Usually when an exception occur we wrap it over our User defined exception and throw.
Similarly u need to throw ur own exception, when an exception occurs in finally also.
try
{
Statement stmt = conect.getConnection();
stmt.executeUpdate(query);
}
catch(SQLException e)
{
//handle exception
throw MyOwnException(e,"My message");
}
finally
{
try{ stmt.close(); }
catch(SQLException ignore)
{
throw MyOwnException(ignore,"My message");
}
}

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;
}

java.sql.SQLException: General error

Getting java.sql.SQLException
java.sql.SQLException: General error
at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6986)
at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7114)
at sun.jdbc.odbc.JdbcOdbc.SQLExecDirect(JdbcOdbc.java:3110)
at sun.jdbc.odbc.JdbcOdbcStatement.execute(JdbcOdbcStatement.java:338)
at sun.jdbc.odbc.JdbcOdbcStatement.executeQuery(JdbcOdbcStatement.java:253)
at com.test.Temp.main(Temp.java:29)
I am using following code
Connection con=null;
ResultSet rs=null;
Statement stmt=null;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con=DriverManager.getConnection("jdbc:odbc:locator","locator","locator");
stmt=con.createStatement();
System.out.println("Before query");
String query=null;
query="select * from user_location_table";
System.out.println("after query12");
rs=stmt.executeQuery(query);
//perform certain operation....
rs.close();
stmt.close();
con.close();
} catch(Exception e) {
e.printStackTrace();
}
The exception is thrown at stmt.executeQuery(query).
user_location_table contains following fields
user_id:number not null,
latitude:number,
longitude:number,
update_time:timestamp(6)
Thanks in advance
I get it.
The error is thrown due to the use of datatype timestamp(6) in update_time.The exception is thrown whenever we try to execute the select statement containing a column with timestamp as the datatype.
Instead of the previous code we can use the following code for selecting
query="select latitude,longitude,to_char(update_time,'HH24:MI:SS'),to_char(update,time,'DD-MON-YY') from user_location_table";
This works fine,I have tested it.
Cheers!!
A couple of thoughts. If it's only happening on the first execute, it may be that there is something invalid in the db and it's being compiled. Secondly, you may have something leaking because you aren't closing your connection and statement in a finally block. So if you get an exception, you aren't closing the connections and potentially you're creating a lock on your DB.
Add a finally block and move your close statements there checking for null:
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con=DriverManager.getConnection("jdbc:odbc:locator","locator","locator");
stmt=con.createStatement();
System.out.println("Before query");
String query=null;
query="select * from user_location_table";
System.out.println("after query12");
rs=stmt.executeQuery(query);
//perform certain operation....
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (rs!=null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (stm!=null)
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con!=null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

Categories