I have a project having Exception handling written in the following way:
Parent class has all the exception handling logic. And the invoked class just throws exception and the invoker class handles with appropriate logic.
Now the problem that I am facing invoked class opens different stuffs for example, a file. These files are not getting closed at the time of exception.
so what should be the appropriate way of exception handling in this case.
class A
{
private void createAdminClient()
{
try
{
B b = new B();
b.getClinetHandler();
}
catch(CustomException1 e1)
{
}
catch(CustomException2 e1)
{
}
catch(CustomException3 e1)
{
}
catch(CustomException4 e1)
{
}
}
}
class B
{
................
................
getClinetHandler() throws Exception
{
--------------------------
---- open a file----------
--------------------------
----lines of code---------
--------------------------
Exceptions can happen in these lines of code.
And closing file may not be called
--------------------------
---- close those files----
--------------------------
}
}
You can wrap the code which may throw an exception in a try...finally block:
getClientHandler() throws Exception {
// Declare things which need to be closed here, setting them to null
try {
// Open things and do stuff which may throw exception
} finally {
// If the closable things aren't null close them
}
}
This way the exception still bubbles up to the exception handler but the finally block ensures that the closing code still gets called in the event of an exception.
use a finally block to complete the final tasks. for example
try
{
B b = new B();
b.getClinetHandler();
}
catch(CustomException1 e1)
{
}
finally{
// close files
}
From the doc
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.
This is how I do it
try {
//What to try
} catch (Exception e){
//Catch it
} finally {
//Do finally after you catch exception
try {
writer.close(); //<--Close file
} catch (Exception EX3) {}
}
Use a finally block to handle post-processing execution (regardless whether it succeeded or failed). Like so:
// Note: as Sean pointed out, the b variable is not visible to the finally if it
// is declared within the try block, therefore it will be set up before we enter
// the block.
B b = null;
try {
b = new B();
b.getClinetHandler();
}
catch(CustomException1 e1) {
} // and other catch blocks as necessary...
finally{
if(b != null)
b.closeFiles() // close files here
}
The finally block is always executed, regardless, even if you throw or return from the try or catch blocks.
This answer provides a very good explanation of how the finally block works in this situation, and when/how it is executed, and basically further illustrates what I just wrote.
Related
In the following code snippet, if ex1 is thrown, will be be caught by the second catch block, or will it be thrown back to the caller of the method?
And if it is thrown back to the caller, and then a second exception occurs in the finally block (ex2), does that mean 2 exceptions will be thrown back to the caller (ex1 and ex2)?
try {
// write to file
} catch (IOException ex1) {
throw ex1;
} finally {
try {
aBufferedWriter.close();
} catch (IOException ex2) {
throw ex2;
}
}
Both of those exceptions would be thrown back to the caller... although a single exception in any particular situation. If the body of the outer try block throws and then close throws as well, only the second exception would be seen by the caller.
However, having a catch block just to rethrow is pointless. Your code would be clearer as:
try {
// write to file
} finally {
aBufferedWriter.close();
}
In Java 7, a try-with-resources statement can do that automatically:
try (BufferedWriter writer = new BufferedWriter(...)) {
// Use the writer here
} // The writer is auto-closed here
That way you can also get at an exception on close separately from an exception in the main body, using Throwable.getSuppressed.
Depends on the design. You can also try
try{
try{
//write to file
}finally{
aBufferedWriter.close();
}
}catch(IOException e){
}
Also why catch the exception if you want to throw it.
Q. In the following code snippet, if ex1 is thrown, will be be caught by the second catch block, or will it be thrown back to the caller of the method?
No, it won't be caught by the catch block inside the finally, provided there is no exception in the finally block and thus the exception ex1 would be thrown back to the caller method.
Q. And if it is thrown back to the caller, and then a second exception occurs in the finally block (ex2), does that mean 2 exceptions will be thrown back to the caller (ex1 and ex2)?
In this case, since a exception gets thrown in the finally block, it'll overwrite the exception thrown in the outer catch block and resulting in the exception ex2 getting thrown back to the caller method.
Only either of the exceptions would be thrown back to the caller method for a single execution of this, not both. That being said, having a catch block just to throw back the exception which has been caught, is really pointless.
Before Java 7, the really accurate pattern was
public void writeToFile(String file) throws IOException {
IOException exception = null;
OutputStream out = new FileOutputStream(file);
try {
// TODO: write data to file
} catch (IOException ex) {
// store exception for later rethrow
exception = ex;
} finally {
try {
out.close();
} catch (IOException ex) {
// do NOT supress 'outer' exception:
if (exception == null) {
exception = ex;
}
}
}
if (exception != null) {
throw exception;
}
}
Looks crazy, but this covers every possibility and circumvents exception supressed exceptions (when an exception is thrown in the finally statement, it supresses the 'real' exception that happened in the try block - if any).
But maybe - for the sake of readability - you can live with suppressed exceptions and do it like that:
OutputStream out = new FileOutputStream(file);
try {
// TODO: write data to file
} finally {
out.close(); // if an exception is thrown here, it hides the original exception
}
See also http://tutorials.jenkov.com/java-exception-handling/exception-handling-templates.html
Since Java 7, you can do (almost) the same with a try-with-resource statement:
public void writeToFile(String file) throws IOException {
try (OutputStream out = new FileOutputStream(file)) {
// TODO: write data to file
}
}
Note that exceptions that are thrown when the resource is closed do NOT suppress the original exception. Instead this additional exceptions are added as 'suppressed exceptions' to the base exception. You can get them with baseException.getSuppressed() (Java 7 and above!).
See also http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
I am trying to put a while loop inside a try /catch block. To my curiosity finally of that try catch is not executed when the while loop exits. Can some explain what is happening actually?
I tried to google, but cnould not find any details.
I assume your code looks like this:
try
{
while (...)
{
// ...
}
}
catch (FooException ex)
{
// This only executes if a FooException is thrown.
}
finally
{
// This executes whether or not there is an exception.
}
The catch block is only executed if there is an exception. The finally block usually executes whether or not an exception was thrown. So you will probably find that your finally block is actually being executed. You can prove this to yourself by placing a line there that causes some output to the console.
However there are situations in which the finally block doesn't run. See here for more details:
Does a finally block always run?
It can happen only if your program exits either by using System.exit() or if an Error or Throwable were thrown (vs. Exception that will be caught).
Try the following:
public static void main(String[] args) {
try{
System.out.println("START!");
int i=0;
while(true){
i++;
if(i > 10){
System.exit(1);
}
}
}
catch (Exception e) {
// TODO: handle exception
}
finally{
System.out.println("this will not be printed!");
}
}
On a question for Java at the university, there was this snippet of code:
class MyExc1 extends Exception {}
class MyExc2 extends Exception {}
class MyExc3 extends MyExc2 {}
public class C1 {
public static void main(String[] args) throws Exception {
try {
System.out.print(1);
q();
}
catch (Exception i) {
throw new MyExc2();
}
finally {
System.out.print(2);
throw new MyExc1();
}
}
static void q() throws Exception {
try {
throw new MyExc1();
}
catch (Exception y) {
}
finally {
System.out.print(3);
throw new Exception();
}
}
}
I was asked to give its output. I answered 13Exception in thread main MyExc2, but the correct answer is 132Exception in thread main MyExc1. Why is it that? I just can't understand where does MyExc2 go.
Based on reading your answer and seeing how you likely came up with it, I believe you think an "exception-in-progress" has "precedence". Keep in mind:
When an new exception is thrown in a catch block or finally block that will propagate out of that block, then the current exception will be aborted (and forgotten) as the new exception is propagated outward. The new exception starts unwinding up the stack just like any other exception, aborting out of the current block (the catch or finally block) and subject to any applicable catch or finally blocks along the way.
Note that applicable catch or finally blocks includes:
When a new exception is thrown in a catch block, the new exception is still subject to that catch's finally block, if any.
Now retrace the execution remembering that, whenever you hit throw, you should abort tracing the current exception and start tracing the new exception.
Exceptions in the finally block supersede exceptions in the catch block.
Java Language Specification
If the catch block completes abruptly for reason R, then the finally
block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
This is what Wikipedia says about finally clause:
More common is a related clause
(finally, or ensure) that is executed
whether an exception occurred or not,
typically to release resources
acquired within the body of the
exception-handling block.
Let's dissect your program.
try {
System.out.print(1);
q();
}
So, 1 will be output into the screen, then q() is called. In q(), an exception is thrown. The exception is then caught by Exception y but it does nothing. A finally clause is then executed (it has to), so, 3 will be printed to screen. Because (in method q() there's an exception thrown in the finally clause, also q() method passes the exception to the parent stack (by the throws Exception in the method declaration) new Exception() will be thrown and caught by catch ( Exception i ), MyExc2 exception will be thrown (for now add it to the exception stack), but a finally in the main block will be executed first.
So in,
catch ( Exception i ) {
throw( new MyExc2() );
}
finally {
System.out.print(2);
throw( new MyExc1() );
}
A finally clause is called...(remember, we've just caught Exception i and thrown MyExc2) in essence, 2 is printed on screen...and after the 2 is printed on screen, a MyExc1 exception is thrown. MyExc1 is handled by the public static void main(...) method.
Output:
"132Exception in thread main MyExc1"
Lecturer is correct! :-)
In essence, if you have a finally in a try/catch clause, a finally will be executed (after catching the exception before throwing the caught exception out)
Finally clause is executed even when exception is thrown from anywhere in try/catch block.
Because it's the last to be executed in the main and it throws an exception, that's the exception that the callers see.
Hence the importance of making sure that the finally clause does not throw anything, because it can swallow exceptions from the try block.
A method can't throw two exceptions at the same time. It will always throw the last thrown exception, which in this case it will be always the one from the finally block.
When the first exception from method q() is thrown, it will catch'ed and then swallowed by the finally block thrown exception.
q() -> thrown new Exception -> main catch Exception -> throw new Exception -> finally throw a new exception (and the one from the catch is "lost")
class MyExc1 extends Exception {}
class MyExc2 extends Exception {}
class MyExc3 extends MyExc2 {}
public class C1 {
public static void main(String[] args) throws Exception {
try {
System.out.print("TryA L1\n");
q();
System.out.print("TryB L1\n");
}
catch (Exception i) {
System.out.print("Catch L1\n");
}
finally {
System.out.print("Finally L1\n");
throw new MyExc1();
}
}
static void q() throws Exception {
try {
System.out.print("TryA L2\n");
q2();
System.out.print("TryB L2\n");
}
catch (Exception y) {
System.out.print("Catch L2\n");
throw new MyExc2();
}
finally {
System.out.print("Finally L2\n");
throw new Exception();
}
}
static void q2() throws Exception {
throw new MyExc1();
}
}
Order:
TryA L1
TryA L2
Catch L2
Finally L2
Catch L1
Finally L1
Exception in thread "main" MyExc1 at C1.main(C1.java:30)
https://www.compilejava.net/
The logic is clear till finish printing out 13. Then the exception thrown in q() is caught by catch (Exception i) in main() and a new MyEx2() is ready to be thrown. However, before throwing the exception, the finally block have to be executed first. Then the output becomes 132 and finally asks to thrown another exception new MyEx1().
As a method cannot throw more than one Exception, it will always throw the latest Exception. In other words, if both catch and finally blocks try to throw Exception, then the Exception in catch is swallowed and only the exception in finally will be thrown.
Thus, in this program, Exception MyEx2 is swallowed and MyEx1 is thrown. This Exception is thrown out of main() and no longer caught, thus JVM stops and the final output is 132Exception in thread main MyExc1.
In essence, if you have a finally in a try/catch clause, a finally will be executed AFTER catching the exception, but BEFORE throwing any caught exception, and ONLY the lastest exception would be thrown in the end.
The easiest way to think of this is imagine that there is a variable global to the entire application that is holding the current exception.
Exception currentException = null;
As each exception is thrown, "currentException" is set to that exception. When the application ends, if currentException is != null, then the runtime reports the error.
Also, the finally blocks always run before the method exits. You could then requite the code snippet to:
public class C1 {
public static void main(String [] argv) throws Exception {
try {
System.out.print(1);
q();
}
catch ( Exception i ) {
// <-- currentException = Exception, as thrown by q()'s finally block
throw( new MyExc2() ); // <-- currentException = MyExc2
}
finally {
// <-- currentException = MyExc2, thrown from main()'s catch block
System.out.print(2);
throw( new MyExc1() ); // <-- currentException = MyExc1
}
} // <-- At application exit, currentException = MyExc1, from main()'s finally block. Java now dumps that to the console.
static void q() throws Exception {
try {
throw( new MyExc1() ); // <-- currentException = MyExc1
}
catch( Exception y ) {
// <-- currentException = null, because the exception is caught and not rethrown
}
finally {
System.out.print(3);
throw( new Exception() ); // <-- currentException = Exception
}
}
}
The order in which the application executes is:
main()
{
try
q()
{
try
catch
finally
}
catch
finally
}
It is well known that the finally block is executed after the the try and catch and is always executed....
But as you saw it's a little bit tricky sometimes check out those code snippet below and you will that
the return and throw statements don't always do what they should do in the order that we expect theme to.
Cheers.
/////////////Return dont always return///////
try{
return "In Try";
}
finally{
return "In Finally";
}
////////////////////////////////////////////
////////////////////////////////////////////
while(true) {
try {
return "In try";
}
finally{
break;
}
}
return "Out of try";
///////////////////////////////////////////
///////////////////////////////////////////////////
while (true) {
try {
return "In try";
}
finally {
continue;
}
}
//////////////////////////////////////////////////
/////////////////Throw dont always throw/////////
try {
throw new RuntimeException();
}
finally {
return "Ouuuups no throw!";
}
//////////////////////////////////////////////////
I think you just have to walk the finally blocks:
Print "1".
finally in q print "3".
finally in main print "2".
I think this solve the problem :
boolean allOk = false;
try{
q();
allOk = true;
} finally {
try {
is.close();
} catch (Exception e) {
if(allOk) {
throw new SomeException(e);
}
}
}
To handle this kind of situation i.e. handling the exception raised by finally block. You can surround the finally block by try block: Look at the below example in python:
try:
fh = open("testfile", "w")
try:
fh.write("This is my test file for exception handling!!")
finally:
print "Going to close the file"
fh.close()
except IOError:
print "Error: can\'t find file or read data"
I have a method that looks like this:
try {
doStuff();
} catch (Exception ex) {
logger.error(ex);
}
(I don't really use method names like doStuff - this is just to make things easy)
In doStuff I do a variety of things, among them is call a data access method (so, another method within doStuff) that ends with the following:
} catch (SQLException ex) {
logger.error(ex);
} finally {
try {
connection.close();
proc.close();
results.close();
} catch (Exception e) {
logger.error(e);
} //<--Exception thrown here. HUH?
}
return stuff;
When stepping through this code I get to the second to last curly brace (marked with a comment) and then jump up to the catch in the first code block with a NullPointer exception. The results.close() is what is being run right before it (results is not null). My IDE (NetBeans) doesn't provide a stack trace (it shows the stack trace is null) or any other information other than the name of the exception (from what I can tell).
This code was running fine previously. In fact while it was running, I changed the stored procedure that the data access method (where I'm getting this exception) was calling, and then this error started to occur (without the application having been stopped at all). I've since tried rebuilding and restarting but to no avail. I could change the sproc back but I really want to find out what this error is from since it makes no sense that the sproc would even be a part of this considering where in the code the exception is occurring.
your doStuff() method is throwing something other than a SQLException and it is not being caught. add a catch(Exception e) block and log that exception and see what happens.
this code sample exhibits the same behaviour you are describing:
public class TryCatchTest {
public static void main(String[] args) {
try {
System.out.println("foo");
throw new NullPointerException();
} finally {
try {
System.out.println("bar");
} catch (Exception e) {
e.printStackTrace();
}
} // exception thrown here
}
}
Close the resources in the reverse order in which they were obtained:
try
{
results.close();
proc.close();
connection.close();
}
catch (Exception e)
{
logger.error(e);
} //<--Exception thrown here. HUH?
I'd also recommend methods like these:
public class DatabaseUtils
{
// similar for ResultSet and Statement
public static void close(Connection c)
{
try
{
if (c != null)
{
c.close();
}
}
catch (SQLException e)
{
// log or print.
}
}
}
It could well be that logger is null.
Hard-to-pinpoint exceptions are often thrown in the exception handler itself.
NullPointerException can not be thrown in a line without a statement.
Check that the class file you are executing is of the same version as the source you view (I have had similar issues when an incorrectly configured classpath contained a class twice and the older version was found first in the classpath, or a recompiled class files for not correctly copied to the web container I used for testing).
Edit: As emh points out, it could also be that exception occured prior to entering the finally block.
I'm 99% sure this is happening in the JDBC driver. For starters, your close statements are backwards. You should close the resultset, the statement and the connection, in that order.
If you are running in an application server which is managing the transactions, then the attempt to commit the transaction may trigger the exception inside the JDBC driver.
It could also be something about how result sets are generated in the stored proceedure, such as accessing one, then accessing another, and then referring back to the first one.
As I said in a comment, never catch an exception that you don't want to deal with. In your code, assuming that it is complete, you are not doing anything interesting with the exception, and it is causing you confusion on where and why the exception is happening. If you really want to do more than log or printStackTrace(), like wrapping it with a domain-specific exception (like your.package.DataAccessException or something), then great.
Do something more like this:
ResultSet results = null;
CallableStatement proc = null;
Connection connection = null;
try {
connection = >
proc = connection.createCallableStatement(..);
results = proc.execute(..);
>
} finally {
try {
if ( results != null ) {
results.close();
}
} catch (Exception e) {
logger.error(e);
}
try {
if ( proc != null ) {
proc.close();
}
} catch (Exception e) {
logger.error(e);
}
try {
if ( connection != null ) {
connection.close();
}
} catch (Exception e) {
logger.error(e);
}
}
And then in the caller:
try {
doStuff();
} catch ( SQLException e ) {
throw new your.package.DataAccessException(e);
// or just let the SQLException propagate upward
} catch ( Exception e ) {
throw new your.package.AppException("omg, crazy pills!", e);
// or, once again, just let the exception
// propagate and don't catch anything
}
So, take-away:
don't log exception where they happen, just pass them on, nested in another exception. You don't want your process to not know whether or not the SQL action succeeded or not. You would rather stop and do something else.
Nest exceptions until the get to the end of the line, that way, you always have the complete trace in the place that you wanted to deal with the exception, not in five places scattered throughout your server log.
Nest exceptions (yes, I said that twice!) so that you don't care where the JVM actually throws the exception from, you have the next exception to follow, telling you it was actually a callable statement, or improper closing of your resources, etc.
Don't nest and throw exceptions from errors caught in your finally code, that will interfere with the original exception and that will be more interesting than the failure to close and statement that didn't get opened in the first place.
Set variables to null before you use them, and then check for null before close()ing them.
Catch each problem in the finally block individually, as you might not be able to close your ResultSet (because some execution error caused it not to open in the first place), but you should still try to close the CallableStatement and Connection, as it is probably unaffected and will still cause you to leak resources.
Hope that helps.
Is there an elegant way to handle exceptions that are thrown in finally block?
For example:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
How do you avoid the try/catch in the finally block?
I usually do it like this:
try {
// Use the resource.
} catch( Exception ex ) {
// Problem with the resource.
} finally {
// Put away the resource.
closeQuietly( resource );
}
Elsewhere:
protected void closeQuietly( Resource resource ) {
try {
if (resource != null) {
resource.close();
}
} catch( Exception ex ) {
log( "Exception during Resource.close()", ex );
}
}
I typically use one of the closeQuietly methods in org.apache.commons.io.IOUtils:
public static void closeQuietly(OutputStream output) {
try {
if (output != null) {
output.close();
}
} catch (IOException ioe) {
// ignore
}
}
If you're using Java 7, and resource implements AutoClosable, you can do this (using InputStream as an example):
try (InputStream resource = getInputStream()) {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
Arguably a bit over the top, but maybe useful if you're letting exceptions bubble up and you can't log anything from within your method (e.g. because it's a library and you'd rather let the calling code handle exceptions and logging):
Resource resource = null;
boolean isSuccess = false;
try {
resource = Resource.create();
resource.use();
// Following line will only run if nothing above threw an exception.
isSuccess = true;
} finally {
if (resource != null) {
if (isSuccess) {
// let close throw the exception so it isn't swallowed.
resource.close();
} else {
try {
resource.close();
} catch (ResourceException ignore) {
// Just swallow this one because you don't want it
// to replace the one that came first (thrown above).
}
}
}
}
UPDATE: I looked into this a bit more and found a great blog post from someone who has clearly thought about this more than me: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html He goes one step further and combines the two exceptions into one, which I could see being useful in some cases.
As of Java 7 you no longer need to explicitly close resources in a finally block instead you can use try-with-resources syntax. The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. 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.
Assume the following code:
try( Connection con = null;
Statement stmt = con.createStatement();
Result rs= stmt.executeQuery(QUERY);)
{
count = rs.getInt(1);
}
If any exception happens the close method will be called on each of these three resources in opposite order in which they were created. It means the close method would be called first for ResultSetm then the Statement and at the end for the Connection object.
It's also important to know that any exceptions that occur when the close methods is automatically called are suppressed. These suppressed exceptions can be retrieved by getsuppressed() method defined in the Throwable class.
Source: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Ignoring exceptions which occur in a 'finally' block is generally a bad idea unless one knows what those exceptions will be and what conditions they will represent. In the normal try/finally usage pattern, the try block places things into a state the outside code won't be expecting, and the finally block restores those things' state to what the outside code expects. Outside code which catches an exception will generally expect that, despite the exception, everything has been restored to a normal state. For example, suppose some code starts a transaction and then tries to add two records; the "finally" block performs a "rollback if not committed" operation. A caller might be prepared for an exception to occur during the execution of the second "add" operation, and may expect that if it catches such an exception, the database will be in the state it was before either operation was attempted. If, however, a second exception occurs during the rollback, bad things could happen if the caller makes any assumptions about the database state. The rollback failure represents a major crisis--one which should not be caught by code expecting a mere "Failed to add record" exception.
My personal inclination would be to have a finally method catch exceptions that occur and wrap them in a "CleanupFailedException", recognizing that such failure represents a major problem and such an exception should not be caught lightly.
One solution, if the two Exceptions are two different classes
try {
...
}
catch(package1.Exception err)
{
...
}
catch(package2.Exception err)
{
...
}
finally
{
}
But sometimes you cannot avoid this second try-catch. e.g. for closing a stream
InputStream in=null;
try
{
in= new FileInputStream("File.txt");
(..)// do something that might throw an exception during the analysis of the file, e.g. a SQL error
}
catch(SQLException err)
{
//handle exception
}
finally
{
//at the end, we close the file
if(in!=null) try { in.close();} catch(IOException err) { /* ignore */ }
}
Why do you want to avoid the additional block? Since the finally block contains "normal" operations which may throw an exception AND you want the finally block to run completely you HAVE to catch exceptions.
If you don't expect the finally block to throw an exception and you don't know how to handle the exception anyway (you would just dump stack trace) let the exception bubble up the call stack (remove the try-catch from the finally block).
If you want to reduce typing you could implement a "global" outer try-catch block, which will catch all exceptions thrown in finally blocks:
try {
try {
...
} catch (Exception ex) {
...
} finally {
...
}
try {
...
} catch (Exception ex) {
...
} finally {
...
}
try {
...
} catch (Exception ex) {
...
} finally {
...
}
} catch (Exception ex) {
...
}
After lots of consideration, I find the following code best:
MyResource resource = null;
try {
resource = new MyResource();
resource.doSomethingFancy();
resource.close();
resource = null;
} finally {
closeQuietly(resource)
}
void closeQuietly(MyResource a) {
if (a!=null)
try {
a.close();
} catch (Exception e) {
//ignore
}
}
That code guarantees following:
The resource is freed when the code finished
Exceptions thrown when closing the resource are not consumed without processing them.
The code does not try to close the resource twice, no unnecessary exception will be created.
If you can you should test to avoid the error condition to begin with.
try{...}
catch(NullArgumentException nae){...}
finally
{
//or if resource had some useful function that tells you its open use that
if (resource != null)
{
resource.Close();
resource = null;//just to be explicit about it was closed
}
}
Also you should probably only be catching exceptions that you can recover from, if you can't recover then let it propagate to the top level of your program. If you can't test for an error condition that you will have to surround your code with a try catch block like you already have done (although I would recommend still catching specific, expected errors).
You could refactor this into another method ...
public void RealDoSuff()
{
try
{ DoStuff(); }
catch
{ // resource.close failed or something really weird is going on
// like an OutOfMemoryException
}
}
private void DoStuff()
{
try
{}
catch
{
}
finally
{
if (resource != null)
{
resource.close();
}
}
}
I usually do this:
MyResource r = null;
try {
// use resource
} finally {
if( r != null ) try {
r.close();
} catch( ThatSpecificExceptionOnClose teoc ){}
}
Rationale: If I'm done with the resource and the only problem I have is closing it, there is not much I can do about it. It doesn't make sense either to kill the whole thread if I'm done with the resource anyway.
This is one of the cases when at least for me, it is safe to ignore that checked exception.
To this day I haven't had any problem using this idiom.
try {
final Resource resource = acquire();
try {
use(resource);
} finally {
resource.release();
}
} catch (ResourceException exx) {
... sensible code ...
}
Job done. No null tests. Single catch, include acquire and release exceptions. Of course you can use the Execute Around idiom and only have to write it once for each resource type.
Changing Resource from best answer to Closeable
Streams implements Closeable Thus you can reuse the method for all streams
protected void closeQuietly(Closeable resource) {
if (resource == null)
return;
try {
resource.close();
} catch (IOException e) {
//log the exception
}
}
I encountered a situation similar where I couldn't use try with resources but I also wanted to handle the exception coming from the close, not just log and ignore it like closeQuietly mechanism do. in my case I'm not actually dealing with an output stream, so the failure on close is of more interest than a simple stream.
IOException ioException = null;
try {
outputStream.write("Something");
outputStream.flush();
} catch (IOException e) {
throw new ExportException("Unable to write to response stream", e);
}
finally {
try {
outputStream.close();
} catch (IOException e) {
ioException = e;
}
}
if (ioException != null) {
throw new ExportException("Unable to close outputstream", ioException);
}