Writing catch block with cleanup operations in Java - java

I was not able to find any advice on catch blocks in Java that involve some cleanup operations which themselves could throw exceptions.
The classic example is that of stream.close() which we usually call in the finally clause and if that throws an exception, we either ignore it by calling it in a try-catch block or declare it to be rethrown.
But in general, how do I handle cases like:
public void doIt() throws ApiException { //ApiException is my "higher level" exception
try {
doLower();
} catch(Exception le) {
doCleanup(); //this throws exception too which I can't communicate to caller
throw new ApiException(le);
}
}
I could do:
catch(Exception le) {
try {
doCleanup();
} catch(Exception le1) {
//ignore?
//log?
}
throw new ApiException(le); //I must throw le
}
But that means I will have to do some log analysis to understand why cleanup failed.
If I did:
catch(Exception le) {
try {
doCleanup();
} catch(Exception le1) {
throw new ApiException(le1);
}
It results in losing the le that got me here in the catch block in the fist place.
What are some of the idioms people use here?
Declare the lower level exceptions in throws clause?
Ignore the exceptions during cleanup operation?

First, decide if you actually need to throw from the finally block - think carefully on that - in the case of a failed close() call... well, logging it is fine - but what can a higher layer of your API really do about the problem? So for 99% of the cases, you will log the secondary then re-throw the primary.
Next, if you do need to throw the secondary, decide if the various causes of the secondary exception are important. It will be rare that they are. So set the cause of the secondary to be the primary (either using an appropriate constructor, or initCause() ).
Finally, if you've must throw the secondary, and retain the full stack trace of the secondary and the primary - then you are in to creating a custom Exception to handle the situation. It's ugly, because you will probably want to derive from different parent classes. If this does arise, I suggest creating a helper class that is capable of filling the stack trace of a target exception in such a way that it produces a meaningful trace based on both exceptions (Be sure to use indentation for the secondary so nested exceptions are easy to pull apart).
But mostly, I suggest that you use the log-and-rethrow-primary paradigm. Focus on fixing the primary, and the secondary issues generally take care of themselves (the classic example here is an IO exception that munges things up so badly that the call to close() can't succeed either).

Use a finally block. If you are worried about swallowing the stack trace do the following:
Exception ex = new Exception(le.stackTrace());

Related

How am I supposed to let an Unchecked Exception bubble up and log?

So quoting from this page, which is titled: Exception-Handling Antipatterns Blog and seems to be written (or at least to be approved) by Oracle..
An unchecked exception probably shouldn't be retried, and the correct response is usually to do nothing, and let it bubble up out of your method and through the execution stack. This is why it doesn't need to be declared in a throws clause. Eventually, at a high level of execution, the exception should probably be logged.
I am not sure if I understand this. How can I log an unchecked exception? If I have something like:
public static void main(String args) {
foo();
// How do I know what to log here? The method I am calling
// is not throwing an Exception.
// Do I just blindly catch(Exception ex)?
}
static void foo() {
bar();
}
static void bar() {
baz();
}
static void baz() {
// I will do nothing as Oracle suggests and let this exception bubble up.. I wonder who is going to catch it and how this is going to be logged though!
throw new NullPointerException();
}
Can you help me understand what Oracle is suggesting here? I do not see any direct (or clear) way to catch runtime exceptions (I do not understand why it is not just called unchecked exceptions..) in higher levels and I am not sure how this suggested practice is useful. To me it would make more sense if it were talking about checked exceptions. Something like..
If a checked exception is thrown in a method that is not reasonable to be re-tried, the correct response is to let it bubble up and log..
You can also register a global ExceptionHandler that will handle the Exceptions that were not caught by your code:
Thread.setDefaultUncaughtExceptionHandler
This exception handle could then log whatever occured.
First of all, this is a general advice and it depends on the context. The idea behind it is that when a runtime exception occurs (ex. NullPointerException), the system is usually in an indeterministic state, meaning the rest of the code is not be guaranteed to execute as expected, so it's better to stop everything.
In most cases, your code will run in a separate thread and the exception will only stop the current thread, while the rest of the program keeps running.
This is not the case in your example, because everything is executed in a single thread, so the uncaught exception will effectively stop the whole program. In this scenario you might want to catch the exception and handle it.
public static void main(String args) {
try {
foo();
catch(Throwable t) {
t.printStackTrace(); // log exception
// handle the failure
}
}
You can also catch the exception earlier on, log and rethrow it further.
static void bar() {
try {
baz();
catch (Throwable t) { // catch
t.printStackTrace(); // log
throw t; // rethrow further
}
}
Edit: catch Throwable instead of Exception, will also catch Error
Note: Catching throwable is usually a bad idea, and should only be done with a specific purpose, not in general case. See #RC.'s comment.
As I understand it the documentation is suggesting that you have a generic handler at a high level of your code that logs such 'unexpected' (unrecoverable?) exceptions just as the comments in your main method suggest. So it might look something like this
public static void main(String args) {
try {
foo();
}
catch (ArithmeticException aex) { //if it's arithmetic log differently
log("arith issue! "+aex.getMessage());
}
catch (Exception ex) { //Otherwise do the best we can
log("unknown issue! "+ex.getMessage())
}
}
So there is still no path to recovery but at least before the process ends you get a chance to log the issue. You can also use the methods of Exception (or throwable) to get the stack trace and first causal exceptions in many case - so there is is a lot of extra useful information that might be logged.
There is a very straightforward way to catch unchecked exceptions, since they are all subclasses of RuntimeException or Error:
public static void main(String[] args) {
try {
// your code
} catch (RuntimeException | Error e) {
// handle uncaught exceptions, e.g.
e.printStackTrace();
}
}
How do I know what to log here? The method I am calling is not throwing an Exception.
As Joshua Bloch recommends in the Effective Java
Use the Javadoc #throws tag to document each unchecked exception that
a method can throw, but do not use the throws keyword to include
unchecked exceptions in the method declaration
And if you are using method wrapping in multilayered app i can recommend use exception translation:
Higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction
See Effective Java item 61
So i think for your example actually you should use something like:
try {
bar();
} catch(NullPointerException e) {
throw new HigherLevelException(...);
}
The most important guideline regarding exceptions is that a method that couldn't sucessfully complete its task should throw an exception.
Only if you can guarantee successful completion of your method's task, you should catch an exception inside your method (without re-throwing this or another exception). From my experience that's only true in very specific situations, e.g. if you have an alternative way to try if some first attempt fails, or if you really really understand all possible causes of this specific Exception class that you are about to catch.
Speaking about RuntimeExceptions, there are so many different types of RuntimeException that you can hardly justify an assertion like "When such an exception arises in my code or a method called from inside my code, that won't affect the outcome of my method - I can continue just as if nothing happened." So, you should signal to your caller that you failed to fulfill your task, and the clearest way to do that is to let the exception ripple through, without try/catch block or throws declaration, just relying on Java's default behaviour.
In my opinion, the same reasoning applies to nearly all kinds of exceptions, not only RuntimeExceptions.
The difference with checked exceptions is that you have to declare them in the throws clause of your method. Then you have two choices: list the exception in the throws clause of your method (and all parent methods as well!) or catch the exception, wrap it in a new RuntimeException(ex), and throw that from your method.
With e.g. a typical GUI application, your users will be grateful if a problem in one menu function won't crash the whole application - probably other menu items might still work as expected. So, top-level commands or menu items are typically the places where to catch exceptions, tell the user something like "Oops!", log the exception to some file for later inspection, and allow the user to continue with another action.
In your main/foo/bar/baz application, I don't see a place where continuing after an exception makes sense. So the whole program should be aborted (which happens automatically in your case). If you want some error logging to a file, then establish an uncaught exception handler or wrap the body of main() in a try / catch(Throwable t) block. You'll probably want every exception logged, whatever type it is, so catch them all, and that's why I'm suggesting Throwable.
public static void main(String[] args) {
try {
foo();
}
catch(NullPointerException e){
System.out.println("NullPointerException in main.");
}
}
static void foo() {
bar();
}
static void bar() {
baz();
}
static void baz() {
// I will do nothing as Oracle suggests and let this exception bubble up.. I wonder who is going to catch it and how this is going to be logged though!
throw new NullPointerException();
}
OUTPUT :
NullPointerException in main.
Basically the error is expected at a higher level, so there is no need to catch it on the baz() method level. If I understood correctly.
You can catch them just like any other exception with try-catch block. But the benefit is that you don't have to.
Use cases can vary. To my mind, the most popular is when it doesn't make sense to catch the exception right in that place or the appropriate handling should be implemented several levels (in terms of methods) higher than the method, calling the one throwing the exception (sorry, if that is not clear enough).
For example, the typical web application layout in java is as follows: you have a layer of controllers, a layer of services and a layer of dao. First one is responsible for dispatching requests, the second one is for managing business logic and the last one makes actual calls to db. So here for example it often doesn't make much sense to catch the exception in service layer if something goes wrong on the dao level. Here unchecked exceptions can be used. You log an exception and throw an unchecked exception so it could be handled some levels above for a user to get valuable feedback of work of the application.
If in this case you throw a checked exception you will have to rethrow it every level above just to bubble up it to the place of the actual handling. So here the unchecked exception is better to use in order not to copy and paste all that ugly try-catch block, rethrowing an exception and add the throws clause to the method.

Does catching and rethrowing the exact same exception mean anything?

Lately, I have been seeing a lot of (commercial) code that throws and catches the exact same exception, similar to the code below:
public class Foo {
public void bar() throws AnException {
// do something (1)
try {
// do something (2) -- able to throw AnException
} catch (AnException ex) {
throw ex;
}
// do something (3)
}
}
Contrast this to:
public class Foo {
public void bar() throws AnException {
// do something (1)
// do something (2) -- able to throw AnException
// do something (3)
}
}
Does the former actually accomplish anything, in either behavior or semantics or else? Will it have any effect on code performance (time and space) or does it help readability?
P.S. this question is very different from this question.
EDIT: The catch block in the former doesn't do anything else other than rethrowing the caught exception.
This is a violation of a basic rule:
The code should catch only the exceptions that it knows how to handle.
Oracle's guidelines suggests that each time you throw an exception, you should supply something useful for the code that catches your exception (see page 3 of Effective Java Exceptions). Catching an exception simply to re-throw it serves no practical purpose, because there is no additional information added to it for the code above it in the invocation chain, and no information extracted by the method itself.
It makes no sense for sure assuming code you provided.
Rethrowing exceptions makes sense when you want to handle this exception somehow (e.g. log it) but want it to be handled further in a stack trace.
Regarding commercial code, maybe the reason you saw it was that there was some handling logic initially that was removed but exceptions rethrowing wasn't removed. I saw such situations several times.
There's no reason for the try/catch in the code you posted. As with #nickolay.laptev's answer, I believe that if you find this in commercial code, it's probably left over cruft from something that used to be meaningful.
Aside from some sort of partial error handling, there's another use case for simply catching and rethrowing an exception. This would be to prevent the exception from being caught by a subsequent, more general, catch clause. So, for instance, if you wanted to handle every exception other than instances of AnException, you would either have to do a type check:
try {
// stuff
} catch (Exception ex) {
if (ex instanceof AnException) {
throw ex; // rethrow since we're not handling it
} else {
// handle all other exceptions
}
}
or use something like this (which, in my view, is cleaner and more readable):
try {
// stuff
} catch (AnException) {
throw ex;
} catch (Exception ex) {
// handle all other exceptions
}
Then if you later decided to not handle all those other exceptions, you'd delete the second catch clause and end up with the code you posted.

Exception composition in Java when both first strategy and recovery strategy failed

Suppose i have a method that may fail with a checked exception (checked because it is recoverable, according to Sun's recommendations).
This method fails and it triggers a recovery strategy.
But both the initial method and the recovery strategy failed.
In some cases i may want to have both stacktraces so that i know why both the initial and recovery strategies failed, and not only the last one.
What can i do?
Should i create a CompositeException type or something like that? Is it a good practice?
Java 7 has introduced the concept of a suppressed exception. For instance, the try-with-resources statement is specified by:
Resources are closed in the reverse order from that in which they were initialized. A resource is closed only if it initialized to a non-null value. An exception from the closing of one resource does not prevent the closing of other resources. Such an exception is suppressed if an exception was thrown previously by an initializer, the try block, or the closing of a resource.
and
If the initialization of the resource completes normally, and the try block completes abruptly because of a throw of a value V, then:
If the automatic closing of the resource completes abruptly because of a throw of a value V2, then the try-with-resources statement completes abruptly because of a throw of value V with V2 added to the suppressed exception list of V.
This uses java.lang.Throwable.addSuppressedException, whose javadoc reads:
Appends the specified exception to the exceptions that were suppressed in order to deliver this exception. This method is thread-safe and typically called (automatically and implicitly) by the try-with-resources statement.
The suppression behavior is enabled unless disabled via a constructor. When suppression is disabled, this method does nothing other than to validate its argument.
Note that when one exception causes another exception, the first exception is usually caught and then the second exception is thrown in response. In other words, there is a causal connection between the two exceptions. In contrast, there are situations where two independent exceptions can be thrown in sibling code blocks, in particular in the try block of a try-with-resources statement and the compiler-generated finally block which closes the resource. In these situations, only one of the thrown exceptions can be propagated. In the try-with-resources statement, when there are two such exceptions, the exception originating from the try block is propagated and the exception from the finally block is added to the list of exceptions suppressed by the exception from the try block. As an exception unwinds the stack, it can accumulate multiple suppressed exceptions.
An exception may have suppressed exceptions while also being caused by another exception. Whether or not an exception has a cause is semantically known at the time of its creation, unlike whether or not an exception will suppress other exceptions which is typically only determined after an exception is thrown.
Note that programmer written code is also able to take advantage of calling this method in situations where there are multiple sibling exceptions and only one can be propagated.
That last paragraph seems to apply to your situation. So you could do:
public static void main(String[] args) throws Exception {
try {
throw new RuntimeException("Not now!");
} catch (Exception e) {
try {
tryAgain();
} catch (Exception e2) {
e.addSuppressed(e2);
throw e;
}
}
}
Then, the stack trace will contain both exceptions:
Exception in thread "main" java.lang.RuntimeException: Not now!
at tools.Test.main(Test.java:12)
Suppressed: java.lang.RuntimeException: I'm on holiday.
at tools.Test.tryAgain(Test.java:7)
at tools.Test.main(Test.java:15)
but only the primary exception can be caught by the caller.
I would consider an exception for when the initial method fails and another for when the recovery strategy fails.
You may want to do something like try the recovery strategy multiple times before throwing a exception that recovery failed (e.g. retry and fail when timeout occurs).
It seems like keeping the initial method and recovery strategy exceptions separated makes sense, as they represent two different scenarios.
Unfortunately, a Java Exception only has one cause, so a CompositeException may be your best option. However, you can override the printStackTrace methods to print the stack traces of your composite exceptions:
public class CompositeException extends Exception {
private final List<Throwable> causes = new ArrayList<Throwable>();
public CompositeException(Throwable... causes) {
this.causes.addAll(Arrays.asList(causes));
}
// Other constructors you want
#Override
public void printStackTrace() {
if (causes.isEmpty()) {
super.printStackTrace();
return;
}
for (Throwable cause : causes) {
cause.printStackTrace();
}
}
#Override
public void printStackTrace(PrintStream s) {
if (causes.isEmpty()) {
super.printStackTrace(s);
return;
}
for (Throwable cause : causes) {
cause.printStackTrace(s);
}
}
#Override
public void printStackTrace(PrintWriter s) {
if (causes.isEmpty()) {
super.printStackTrace(s);
return;
}
for (Throwable cause : causes) {
cause.printStackTrace(s);
}
}
}
This is about all you can do to have multiple cause exceptions in one exception. To use it:
CompositeException ce = new CompositeException(ex1, ex2, ex3);
Then ce.printStackTrace() will print all 3 exceptions' stack traces.
What do you exactly mean with "I may want to have both stacktraces"? What I use to do is log both, since they're "things that should not happen". It allows you to check the log and trace what is wrong. If you do "CompositeException" you'll soon explode on combinatory issues: what if "CompositeExceptionHandler" also fails?
I would...
Trace the first exception and act if you can. Otherwise and raise a custom exception.
Catch the second one and act accordingly.
That way you improve coupling. You handle both levels independently

Which exception should I throw when building cache fail?

I have a class that contains a cache (Set), and the cache is built on instantiation. I'm confused which exception/error should I throw if building cache fail (cannot connect to database or some).
class Provider {
public Provider() {
buildCache();
}
private void buildCache() {
try {
this.cache = getDataFromDb();
} catch (Exception ex) {
throw new ???
}
}
}
One exception comes in my mind is ExceptionInInitializerError, but javadoc says it is thrown on initialize static members.
Should I throw an IllegalStateException cause the cache isn't built so this class is useless?
Clearly I can create my own ErrorOnBuildingCache and throw it but I wonder if any exception in Java library suits this circumstance.
If you're in doubt as to which exception should be thrown, then so will users of your code. So define your own exception type (e.g. FailedToInitializeCacheException) and throw that. No ambiguity that way.
IllegalStateException would be a reasonable fallback position, but you should never, ever use ExceptionInInitializerError (or anything ending in Error) - that's low-level classloader stuff, don't mess with that.
Clearly I can create my own
ErrorOnBuildingCache and throw it but
I wonder if any exception in Java
library suits this circumstance.
This is exactly what you should do. Do not try to use an existing exception, but instead make one of your own. So you know when it is throwed that it is related to your cache and not a static field instanciation error or something.
On a side note, you shouldn't catch exception excepted in very specific cases. Catching exception will catch everything like null pointer exceptions, divide by zero, IO errors, security exception.
What I would do is:
Include the cause when rethrowing the
exception to allow better
investigation
Catch exceptions that could occurs
due to IO/Network problems but
associate them with the right error
message. In you case this is DB exceptions.
Do not catch exception that are due
to programming bugs (like null
pointers), let them popup so you
directly know the real error cause.

Handle exception or throw exception in Java

Like such Java code snippet:
public void func() throws XXXException { // throw exception to outer body ------ (2)
try {
......
} catch(XXXException ex) {
// handle exception ------ (1)
}
}
In this condition, how you decide to choose (1) or (2)? Is there any principles in Java exception handling?
If the code that calls the method that throws the exception can properly deal with the exception then it should catch it. If it cannot deal with the exception then it should throw it up.
For instance, if "func" is low-level networking code it should probably throws the exception rather than catch it. The code that ultimatly catches it should display an error message to the user (or whatever else makes sense). If instead "func" is part of the GUI layer it probably would catch the exception and display an error message to the user (or whatever else makes sense).
If you can handle it you handle it. For example, if you are loading a properties file and you get a FileNotFoundException perhaps you can use some default properties. In this case you handle the exception.
If you can't handle it but you think someone else might be able to down the road then you should throw the exception. For example, perhaps you are writing a general utility for reading in property files. In this case you might rethrow the exception so that whoever is using your general utility can then go ahead and load defaults.
If you can't handle it and you don't want to introduce the complexity of throwing the exception then you should send the exception to an exception handling service that you can configure at runtime. This way when unit testing the exception handling service can take that exception and rethrow it as a runtime exception which will crash the test immediately. However, in production code the exception handling service might just log the exception and try and restart the program somehow.
You choose (1) if you want to do something about the exception (e.g. log it, extract info from it). It's also common to throw the exception in the catch block after you are done with it (i.e. throw ex;)
You choose (2) if you want the users of your method to handle it (e.g. Java's String.matches method)
In a nut shell, choose to throw exception to outer body, unless you have a specific reason to catch the exception.
There's an excellent article at the O'Reilly java site about this topic. It goes into some detail about when you should catch versus throw, as well as other stuff, like checked versus unchecked exceptions.
Exceptions represent error conditions. When an error condition occurs, some method in the call chain knows how to handle that error in the context of the application i.e. what to do - ignore, retry, abort, etc. If this is that method that knows how to handle this exception, then you handle it here. If not, you throw it so that the method one level up the call chain receives it and acts on it.
Sometimes, you may want to do both (1) and (2). You may handle the exception, do some intermediate processing and then rethrow it.
public void func() throws XXXException {
try {
......
} catch(XXXException ex) {
logger.log(ex);
throw ex;
}
}
Or you may catch one exception and throw another, for example when you want to wrap a third party exception into an application exception.
public void func() throws YYYException {
try {
......
} catch(XXXException ex) {
throw new YYYException(ex);
}
}
In both cases, this is not the method that fully handles the exception and only does some processing along the way as the exception percolates to the top.

Categories

Resources