Try-catch-finally and then again a try catch - java

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 ..

Related

Closing Resultset, statement and Connection [duplicate]

Consider the code:
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.createStatement(myQueryString);
rs = ps.executeQuery();
// process the results...
} catch (java.sql.SQLException e) {
log.error("an error!", e);
throw new MyAppException("I'm sorry. Your query did not work.");
} finally {
ps.close();
rs.close();
}
The above does not compile, because both PreparedStatement.close() and ResultSet.close() throw a java.sql.SQLException. So do I add a try/catch block to the finally clause? Or move the close statements into the try clause? Or just not bother calling close?
In Java 7, you should not close them explicitly, but use automatic resource management to ensure that resources are closed and exceptions are handled appropriately. Exception handling works like this:
Exception in try | Exception in close | Result
-----------------+--------------------+----------------------------------------
No | No | Continue normally
No | Yes | Throw the close() exception
Yes | No | Throw the exception from try block
Yes | Yes | Add close() exception to main exception
| | as "suppressed", throw main exception
Hopefully that makes sense. In allows pretty code, like this:
private void doEverythingInOneSillyMethod(String key)
throws MyAppException
{
try (Connection db = ds.getConnection()) {
db.setReadOnly(true);
...
try (PreparedStatement ps = db.prepareStatement(...)) {
ps.setString(1, key);
...
try (ResultSet rs = ps.executeQuery()) {
...
}
}
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
Prior to Java 7, it's best to use nested finally blocks, rather than testing references for null.
The example I'll show might look ugly with the deep nesting, but in practice, well-designed code probably isn't going to create a connection, statement, and results all in the same method; often, each level of nesting involves passing a resource to another method, which uses it as a factory for another resource. With this approach, exceptions from a close() will mask an exception from inside the try block. That can be overcome, but it results in even more messy code, and requires a custom exception class that provides the "suppressed" exception chaining present in Java 7.
Connection db = ds.getConnection();
try {
PreparedStatement ps = ...;
try {
ResultSet rs = ...
try {
...
}
finally {
rs.close();
}
}
finally {
ps.close();
}
}
finally {
db.close();
}
If you're really hand-rolling your own jdbc it definitely gets messy. The close() in the finally needs to get wrapped with its own try catch, which, at the very least, is ugly. You can't skip the close, although the resources will get cleared when the connection is closed (which might not be right away, if you're using a pool). Actually, one of the main selling points of using a framework (e.g. hibernate) to manage your db access is to manage the connection and result set handling so you don't forget to close.
You can do something simple like this, which at least hides the mess, and guarantees that you don't forget something.
public static void close(ResultSet rs, Statement ps, Connection conn)
{
if (rs!=null)
{
try
{
rs.close();
}
catch(SQLException e)
{
logger.error("The result set cannot be closed.", e);
}
}
if (ps != null)
{
try
{
ps.close();
} catch (SQLException e)
{
logger.error("The statement cannot be closed.", e);
}
}
if (conn != null)
{
try
{
conn.close();
} catch (SQLException e)
{
logger.error("The data source connection cannot be closed.", e);
}
}
}
and then,
finally {
close(rs, ps, null);
}
For file I/O, I generally add a try/catch to the finally block. However, you must be careful not to throw any exceptions from the finally block, since they will cause the original exception (if any) to be lost.
See this article for a more specific example of database connection closing.
Don't waste your time coding low-level exception management, use an higher-level API like Spring-JDBC, or a custom wrapper around connection/statement/rs objects, to hide the messy try-catch ridden code.
Also note:
"When a Statement object is closed, its current ResultSet object, if one exists, is also closed. "
http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Statement.html#close()
It should be sufficient to close only the PreparedStatement in a finally, and only if it is not already closed. If you want to be really particular though, close the ResultSet FIRST, not after closing the PreparedStatement (closing it after, like some of the examples here, should actually guarantee an exception, since it is already closed).
I usually have a utility method which can close things like this, including taking care not to try to do anything with a null reference.
Usually if close() throws an exception I don't actually care, so I just log the exception and swallow it - but another alternative would be to convert it into a RuntimeException. Either way, I recommend doing it in a utility method which is easy to call, as you may well need to do this in many places.
Note that your current solution won't close the ResultSet if closing the PreparedStatement fails - it's better to use nested finally blocks.
Building on #erickson's answer, why not just do it in one try block like this?
private void doEverythingInOneSillyMethod(String key) throws MyAppException
{
try (Connection db = ds.getConnection();
PreparedStatement ps = db.prepareStatement(...)) {
db.setReadOnly(true);
ps.setString(1, key);
ResultSet rs = ps.executeQuery()
...
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
Note that you don't need to create the ResultSet object inside the try block as ResultSet's are automatically closed when the PreparedStatement object is closed.
A ResultSet object is automatically closed when the Statement object
that generated it is closed, re-executed, or used to retrieve the next
result from a sequence of multiple results.
Reference: https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
If your are using Java 7 you can use the improvements in the exception handling mechanisms in those classes that implement AutoCloseable (i.e. PreparedStatement, Resultset)
You might also find this question interesting: Closing ResultSet in Java 7
I know this is an old question, but just in case someone is looking for the answer, java now has the try-with-resouce solution.
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
Do no omit calling close. It may cause problems.
I prefer adding try/catch block to the finally.
focus finally clause,
finally {
try {
rs.close();
ps.close();
} catch (Exception e) {
// Do something
}
}
I think you have to modify 2 points.
First, use try & catch again in fainlly clause.
Second, do rs.close() before doing ps.close().
fly1997#naver.com
Probably an old (though simple) way to do things, but it still works:
public class DatabaseTest {
private Connection conn;
private Statement st;
private ResultSet rs;
private PreparedStatement ps;
public DatabaseTest() {
// if needed
}
public String getSomethingFromDatabase(...) {
String something = null;
// code here
try {
// code here
} catch(SQLException se) {
se.printStackTrace();
} finally { // will always execute even after a return statement
closeDatabaseResources();
}
return something;
}
private void closeDatabaseResources() {
try {
if(conn != null) {
System.out.println("conn closed");
conn.close();
}
if(st != null) {
System.out.println("st closed");
st.close();
}
if(rs != null) {
System.out.println("rs closed");
rs.close();
}
if(ps != null) {
System.out.println("ps closed");
ps.close();
}
} catch(SQLException se) {
se.printStackTrace();
}
}
}
I use this..
finally
{
if (ps != null) ps.close();
if (rs != null) rs.close();
}

Try with resource how to use custom logic for closing connection

In the below example we are closing connection and prepared statement using try with resource. It will close connection and prepared statement.
And also we are using 2 try block as explained below
For closing connection and prepared statement
Closing result set
In future, if we have any file-related operation then we'll need to write another try with resource block
try (Connection con = ds.getConnection();
PreparedStatement ps = con.prepareStatement(sql);) {
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
list.add(rs.getInt("id"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
But if we are not using try with resource then we can rewrite above login in single try catch block as below
try {
Connection con = ds.getConnection();
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
list.add(rs.getInt("id"));
}
} catch (Exception e) {
// Closing RS
// Closing PS
// Closing Connection or Customized closing connection logic
}
Question: Even if we have any custom operation while closing connection, is it possible to use a try with resource block?
Also please suggest which one better solution in that case.
Try with resources is a better solution because it uses your connections only inside the "try" block. BUT :
catch (SQLException e)
is not the same thing with :
catch (Exception e)
The (Exception e) will catch SQLException and if you said that you want to do some file related operations, will catch maybe a FileNotFoundException or IOException too so this catch is not very suggestive. In my opinion you should first read the Single Responsibility Principle and then you'll see that the best option to handle your problem is to create 2 try blocks which will handle independently the operations like this:
public static List<Integer> getAllProducts() {
List<Integer> productIds = new ArrayList<>();
try (Connection con = ds.getConnection(); PreparedStatement ps = con.prepareStatement(sql);) {
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
productIds.add(rs.getInt("id"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return productIds;
}
public static void writeSomething(String fileName) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
writer.write("StackOverflow");
} catch (IOException e) {
e.printStackTrace();
}
}
I've had a similar issue a couple of weeks ago. You don't need to have multiple try-with-resources, you can only have one see this.
But in your second sample of code, you don't want to close your connection and all in the catch block. You must use the finally block.
In short you can use only one try-with-resources for the "normal" stuff, and create another try-catch-finally inside the latter (or use call to a custom method) to handle and close your customs operations.
try (Connection conn = datasource.getConnection();
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery(request); ) {
while (rs.next())
{
// Do your stuff.
}
try
{
// Do your stuff.
} catch (Whatever e) {
// Handle.
} finally {
// Close your custom stuff.
}
} catch (SQLException ex) {
// throw something.
}
Hope this helps.

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

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 1.6 java.sql try/catch/finally crazy coding

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.

Categories