Java 1.6 java.sql try/catch/finally crazy coding - java

I'm currently creating a lot of classes that will access database using a connection pool.
So I get a connection, create a statement and get the result set. (I can't use Java 1.7 and the fantastic Automatic Resource Management)
When finishing my method I must finish with a finally block:
if (rs != null) {
try {
rs.close();
} catch (SQLException sqle) {
logger.error("Couldn't close result set", sqle);
}
}
if (st != null) {
try {
st.close();
} catch (SQLException sqle) {
logger.error("Couldn't close statement", sqle);
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException sqle) {
logger.error("Couldn't close connection", sqle);
}
}
I'm already seeing the nightmare it will be for XX classes having 4/5 methods each.
Would it be good practice to make an helper class which would got a special close method for each object type like :
public static void closeResource(Connection connection) {
if (connection != null) {
try {
connection.close();
} catch (SQLException sqle) {
logger.error("Couldn't close connection", sqle);
}
}
And then just doing my usual finally with xx.close(connection);xx.close(statement);xx.close(rs);
Or in the same thinking (I know at this point I'll shock some people as I myself find that a bit ackward), having a method like public static void closeResources(Object... obj) {} with an awful list of instanceof ?
Or in your experience, coding the whole thing everywhere is better ?

Use Apache commons project : http://commons.apache.org/dbutils/apidocs/org/apache/commons/dbutils/DbUtils.html
DbUtils.closeQuietly() is probably what you need

Use overloading.
private void close(ResultSet rSet) throws SQLException {
if (rSet != null) {
rSet.close();
}
}
private void close(Statement statement) throws SQLException {
if (statement != null) {
statement.close();
}
}
private void close(Connection conn) throws SQLException {
if (conn != null) {
conn.close();
}
}
Usage will be much cleaner now:
try {
// do db stuff
} catch (Exception e) {
logger.error("log it", e);
} finally {
close(rs);
close(cs);
close(conn);
}

Just one more example. Suitable for simple small projects.
Object doRequest() throws SQLException {
PreparedStatement ps = ... // initialize statement
try {
ResultSet rs = ps.executeQuery();
try {
// use ResultSet
return someResult;
} finally {
rs.close();
}
} finally {
ps.close();
}
}
Although it is not pretends to be complete solution (many nested try-finally are quite unreadable), there are several advantages:
Method itself not deals with exception handling. Often only caller may decide what to do with exception.
As follows, method always returns correct result or throws exception. No magic "error values" required.
Resources closed only if they were initialized. No need to check for null berode close().

You could also exploit the fact that for every class you want to close, the close method has no args, and make a reflective helper method like this:
public static final void tryClose(Object o){
if(o != null){
Method[] m = o.getClass().getMethods();
for (Method method : m) {
if("close".equals(method.getName())){
if(!method.isAccessible()) method.setAccessible(true);
try {
method.invoke(o);
} catch (Exception e) {
System.err.println(e);
}
break;
}
}
}
}
EDIT: Tested with FileWriter, works fine in my machine.

Related

Cancel SQL Statement with JDBC

I am stuck with this problem here. I am running an application on my Tomcat Application Server. As a frontend I am using an HTML site with javascript in it, in the backend i am using Java.
When the user clicks on a button several sql queries are made, one after another. Now I want to provide the ability to cancel this query if the user wants to.
I already checked if my jdbc driver and the database are compatible for the cancel() method and this is just fine.
Here is my code :
PreparedStatement stmt = null;
public void runQuery(String query) {
Connection con = getConnection();
try {
stmt = con.prepareStatement(query);
stmt.execute();
} catch(SQLException e) {
e.printStackTrace();
} finally {
if(stmt != null && !stmt.isClosed()) {
stmt.close();
}
if(con != null) {
con.close();
}
}
}
public void cancelQuery() {
try {
if(stmt != null && !stmt.isClosed()) {
stmt.cancel();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
So the user clicks the run button => runQuery is executed and stmt is initialized/overriden with the query which needs to execute.
Then the user clicks the cancel button => cancelQuery is executed.
Unfortunately I sometimes get a NullPointerException because stmt is null. But it should not even call cancelQuery if the stmt is null ?!
Here is the stacktrace:
Stacktrace:] with root cause
java.lang.NullPointerException
at com.sybase.jdbc3.jdbc.SybStatement.doCancel(SybStatement.java:646)
at com.sybase.jdbc3.jdbc.SybStatement.cancel(SybStatement.java:614)
at org.apache.tomcat.dbcp.dbcp2.DelegatingStatement.cancel(DelegatingStatement.java:269)
at org.apache.tomcat.dbcp.dbcp2.DelegatingStatement.cancel(DelegatingStatement.java:269)
at de.package.util.DBHelper.cancelQuery(DBHelper.java:82)
.....
Any idea why this keeps producing an exception ? How can I cancel the statement the right way ?
EDIT:
I had allook at the link in the comments and now running the cancel() method from a different thread. However the NullPointer still happens. This is how i call the cancel() method now:
public void cancelQuery() {
Thread thread = new Thread(new SQLCancelRunnable(stmt));
thread.start();
}
public class SQLCancelRunnable implements Runnable {
PreparedStatement stmt;
public SQLCancelRunnable(PreparedStatement stmt) {
this.stmt = stmt;
}
#Override
public void run() {
if(stmt != null) {
try {
System.out.println(stmt);
System.out.println(stmt.toString());
stmt.cancel();
System.out.println("canceled");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
EDIT2
Found my answer the problem was the finally block of the runQuery() method. Because I closed statement & connection the NullPointer was thrown.
I now removed this block but this, of course, leads to huge resource leaking. Anyone who can guide me in the right direction how to close my resources properly ?
PreparedStatement stmt = null;
public void runQuery(String query) {
Connection con = getConnection();
try {
stmt = con.prepareStatement(query);
stmt.execute();
}
catch(SQLException e) {
e.printStackTrace();
}
finally {
if(stmt != null && !stmt.isClosed()) {
stmt.close();
}
if(con != null) {
con.close();
}
}
}
public void cancelQuery() {
try {
if(stmt != null && !stmt.isClosed()) {
stmt.cancel();
}
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
Try this. I have added a Generic Exception just after the SQLException.
Cannot say this is a very clean solution but it will ignore the null pointer exception which is possiblly raised by stmt.close() statement.
You'll need to synchronize statement closing:
public void runQuery(String query) {
...
try {
stmt = con.prepareStatement(query);
stmt.execute();
...
finally {
synchronized(this) {
if(stmt != null && !stmt.isClosed()) {
stmt.close();
}
}
}
}
public void cancelQuery() {
synchronized(this) {
if(stmt != null && !stmt.isClosed()) {
stmt.cancel();
}
}
}
between every statement another thread may execute some kind of code, so a simple if is not sufficient to be sure the state of the world is as you expect it to be.
Synchronizing on this may not be the best option, but as the stmt may be null we can't use this object.
Edit: If the code starting the query is asynchronous you'll also have to be prepared for calls to cancelQuery even before your statement is prepared.
You can use Statement.cancel()
As Java Docs Says
void cancel()
throws SQLException
Cancels this Statement object if both the DBMS and driver support
aborting an SQL statement. This method can be used by one thread to
cancel a statement that is being executed by another thread.
You can also set setQueryTimeout if query execution passes a threshhold time
java.sql.Statement.setQueryTimeout(seconds)
Update
Don't forget to Rollback the transation
Anyone who can guide me in the right direction how to close my
resources properly ?
this is what for finally block was invented
finally{
//Release All Resources
}
The finally block always executes when the try block exits. This
ensures that the finally block is executed even if an unexpected
exception occurs. But finally is useful for more than just exception
handling — it allows the programmer to avoid having cleanup code
accidentally bypassed by a return, continue, or break. Putting cleanup
code in a finally block is always a good practice, even when no
exceptions are anticipated.
You should take a look at Apache DB-Utils it makes this kind of problems disappear and you can simply write something like:
} finally {
DbUtils.closeQuietly(resutlSet);
DbUtils.closeQuietly(preparedStatement);
DbUtils.closeQuietly(connection);
}

Close connection and statement finally

Which is better for finally block:
finally {
try {
con.close();
stat.close();
} catch (SQLException sqlee) {
sqlee.printStackTrace();
}
}
Or:
finally {
try {
if (con != null) {
con.close();
}
if (stat != null) {
stat.close();
}
} catch (SQLException sqlee) {
sqlee.printStackTrace();
}
}
Better way to use is the 2nd one, because if an exception is thrown while initializing con or stat, they won't be initialized, and might be left initialized to null. In that case, using the 1st code will throw NullPointerException.
Also, if you are already on Java 7, you should consider using try-with-resources, which automatically closes the resources. From the linked tutorial:
The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
As of Java 7, you don't need any more use the finallyl block to close a Connection or Statement object. Instead you can make use of the new features called 'try-with-resources'.
First you declare a Connection and Statament objects by using the new syntax for a try-catch block as follows:
try(Connection con = DriverManager.getConnection(database-url, user, password); Statement st = conn.createStatement()) {
//your stuffs here
} catch (SQLException e) {
e.printStackTrace();
}
Doing so, you won't need to worry to close explicitly the linkage with the database in a finally block because the jvm will do it for you.
Have nice coding....
None of them are good enough. Use this:
public static void closeQuietly(AutoCloseable ... closeables) {
for (AutoCloseable c : closeables) {
if (c != null) {
try {
c.close();
} catch (Exception e) {
// log or ignore, we can't do anything about it really
}
}
}
}
And call it like closeQuietly(stat, con);
Or use java 7's try-with-resource:
List<String> results = new ArrayList<>();
try (Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery(query)) {
int numberOfColumns = getColumnCount(rs);
while (rs.next()) {
int i = 1;
while (i <= numberOfColumns) {
results.add(rs.getString(i++));
}
}
}
If there is a possibility either is null, you must check that. If the possibility does not exist, there is no valid reason to check for it.
Also, you can make your code slightly better readable by omitting some single-statement brackets:
finally {
try {
if (con != null)
con.close();
if (stat != null)
stat.close();
} catch (SQLException sqlee) {
sqlee.printStackTrace();
}
}
I would go with the second option, but adding a second nested finally block, just to make sure that both con and stat objects are marked for garbage collection:
finally {
try {
if(con != null)
con.close();
if(stat != null)
stat.close();
} catch(SQLException sqlee) {
sqlee.printStackTrace();
} finally { // Just to make sure that both con and stat are "garbage collected"
con = null;
stat = null;
}
}

finding DB connections that are not closed properly

There have been some leaks found in the code of a large project where DB connections are opened yet not closed.
The DB is DB2 and the connections are opened in a java program and not properly closed in a try catch, finally..
Is there any way to search in java for all methods which open a connection yet don't close it?
I'm trying to avoid manually looking through each method that opens a connection to see if it's closed properly.
any help with this tedious task would be cool.
Both FindBugs and PMD (open-source static code checkers) support detecting unclosed DB connections. They could be integrated into your build process and / or IDE.
PMD, in particular, can be noisy by default, but it can be tuned down using a custom ruleset or via other means.
The first thing that comes to my mind is implementing a tool utilizing abstract syntax trees (e.g. as an eclipse plugin). You could write a tool that goes through your methods, checks the nodes for connection initialization commands, and also checks for closing commands.
See:
- http://en.wikipedia.org/wiki/Abstract_syntax_tree see:
- http://www.eclipse.org/articles/Article-JavaCodeManipulation_AST/index.html
Otherwise, I think also some kind of custom parser could be used that checks there is an equivalent .close() statement within the same level as the equivalent database open statement.
You would have to check how many levels in you are (utilizing "{" and "}" characters.
See: Write a custom syntax interpreter in java?
In relation to your question you could also implement a class with methods that ensure you to close connections. Under I have posted an example.
public class Cleaner {
private String dbName = "";
private Connection connection;
public static void CloseResSet(ResultSet res) {
try {
if (res != null) {
res.close();
}
} catch (SQLException e) {
writeMessage(e, "CloseResSet()");
}
}
public static void closeStatement(Statement stm) {
try {
if (stm != null) {
stm.close();
}
} catch (SQLException e) {
writeMessage(e, "closeStatement()");
}
}
public static void closeConnection(Connection connection) {
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
writeMessage(e, "closeConnection()");
}
}
public static void rollBack(Connection connection) {
try {
if (connection != null && !connection.getAutoCommit()) {
connection.rollback();
}
} catch (SQLException e) {
writeMessage(e, "rollBack()");
}
}
public static void setAutoCommit(Connection connection) {
try {
if (connection != null && !connection.getAutoCommit()) {
connection.setAutoCommit(true);
}
} catch (SQLException e) {
writeMessage(e, "setAutoCommit()");
}
}
public static void writeMessage(Exception e, String message) {
System.err.println("*** Error: " + message + ". ***");
e.printStackTrace(System.err);
}
private void OpenConnection() {
try {
connection = DriverManager.getConnection(dbName);
System.out.println("Databaseconnection established");
} catch (SQLException e) {
Cleaner.writeMessage(e, "Constructor");
Cleaner.closeConnection(connection);
}
}
private void closeConnection() {
System.out.println("Closes databaseconnection");
Cleaner.closeConnection(connection);
}
public static void main(String[] args){
}
}

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

Try-catch-finally and then again a try catch

I have often come across situations like :-
try{
...
stmts
...
}
catch(Exception ex) {
...
stmts
...
} finally {
connection.close // throws an exception
}
which still needs a try - catch block inside finally.
What is the best practice to overcome this?
Write a SQLUtils class that contains static closeQuietly methods that catch and log such exceptions, then use as appropriate.
You'll end up with something that reads like this:
public class SQLUtils
{
private static Log log = LogFactory.getLog(SQLUtils.class);
public static void closeQuietly(Connection connection)
{
try
{
if (connection != null)
{
connection.close();
}
}
catch (SQLExcetpion e)
{
log.error("An error occurred closing connection.", e);
}
}
public static void closeQuietly(Statement statement)
{
try
{
if (statement!= null)
{
statement.close();
}
}
catch (SQLExcetpion e)
{
log.error("An error occurred closing statement.", e);
}
}
public static void closeQuietly(ResultSet resultSet)
{
try
{
if (resultSet!= null)
{
resultSet.close();
}
}
catch (SQLExcetpion e)
{
log.error("An error occurred closing result set.", e);
}
}
}
And your client code will be something like:
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try
{
connection = getConnection();
statement = connection.prepareStatement(...);
resultSet = statement.executeQuery();
...
}
finally
{
SQLUtils.closeQuietly(resultSet);
SQLUtils.closeQuietly(statment);
SQLUtils.closeQuietly(connection);
}
Update: since Java 7, the various JDBC interfaces extend java.lang.AutoCloseable and while the above code answers the original question, if you're writing code directly against the JDBC API, it can now be structured:
try (
Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement(...);
ResultSet resultSet = statement.executeQuery()
)
{
...
}
As others have mentioned, a static closeQuietly utility is the way to go. One thing to add - if you are in the world of java.io rather than java.sql then there is a useful interface for exactly this purpose - java.io.Closeable
All the data sources and sinks in java.io implement this interface - all streams, channels, writers and readers. That way you can create a single utility to cope with the same "exception on close()" issue without requiring many overloaded versions.
e.g.
public class IoUtils {
public static closeQuietly (Closeable closeable) {
try {
closeable.close();
} catch (IOException logAndContinue) {
...
}
}
}
I usually did it this way:
try {
try {
..
stmts
...
}
finally {
connection.close():
}
} catch (Exception ex) {
..
stmts
..
}
I usually only used this when I wasn't using a library that took care of this plumbing for me.
As Imagist points out, this isn't technically the same as the finally will run before the catch but I think it solves the problem you were trying to solve.
Commons-io also has closeQuietly() for in and output streams. I'm using it all the time. It makes your code much more readable.
In Java 10 you can write:
public void java10() throws SQLException {
try (var connection = Connections.openConnection();
var callableStatement = connection.prepareCall("my_call");
var resultSet = callableStatement.executeQuery()) {
while (resultSet.next()) {
var value = resultSet.getString(1);
System.out.println(value);
}
}
}
In Java 7, 8 and 9 you can write:
public void java7() throws SQLException {
try (Connection connection = Connections.openConnection();
CallableStatement callableStatement = connection.prepareCall("my_call");
ResultSet resultSet = callableStatement.executeQuery()) {
while (resultSet.next()) {
String value = resultSet.getString(1);
System.out.println(value);
}
}
}
In Java 6 you need to write all these lines:
public void java6() throws SQLException {
Connection connection = Connections.openConnection();
try {
CallableStatement callableStatement = connection.prepareCall("my_call");
try {
ResultSet resultSet = callableStatement.executeQuery();
try {
while (resultSet.next()) {
String value = resultSet.getString(1);
System.out.println(value);
}
} finally {
try {
resultSet.close();
} catch (Exception ignored) {
}
}
} finally {
try {
callableStatement.close();
} catch (Exception ignored) {
}
}
} finally {
try {
connection.close();
} catch (Exception ignored) {
}
}
}
Don't hesitate use one more try ... catch inside finally.
Generally you don't want to do anything more than log an exception which happens when closing a resource, so it should really go in its own try/catch. However, this is generic code that will happen often, so Don't Repeat Yourself, and put the close in a static method (as Nick Holt suggests) that way you won't have the two try/catch items in the same method, making the code easier to read and follow.
There is also handy Closeables#closeQuitely method in Google Guava library - it can be used for any Closeable
Can we have try block followed by finally bock and catch block later to that?
just remember .. finally always get execute either with try or catch ..

Categories