Guidelines on Exception propagation (in Java) - java

Are there any guidelines on exception propagation in Java?
When do you add an exception to the method signature?
For example: if an exception is only thrown when an essential program resource is missing, and can only be handled at the top level, do I propagate it through all methods using this exception through all the methods using the erring method?
Are there any good practices? Any bad practices?
I'm sorry if I'm being vague, but I'm just looking for some (general) advice on programming style concerning exceptions.

Guidelines that have helped me in the past include:
Throw exceptions when the method cannot handle the exception, and more importantly, should be handled by the caller. A good example of this happens to present in the Servlet API - doGet() and doPost() throw ServletException or IOException in certain circumstances where the request could not be read correctly. Neither of these methods are in a position to handle the exception, but the container is (which results in the 50x error page in most cases).
Bubble the exception if the method cannot handle it. This is a corollary of the above, but applicable to methods that must catch the exception. If the caught exception cannot be handled correctly by the method, then it is preferable to bubble it.
Throw the exception right away. This might sound vague, but if an exception scenario is encountered, then it is a good practice to throw an exception indicating the original point of failure, instead of attempting to handle the failure via error codes, until a point deemed suitable for throwing the exception. In other words, attempt to minimize mixing exception handling with error handling.
Either log the exception or bubble it, but don't do both. Logging an exception often indicates that the exception stack has been completely unwound, indicating that no further bubbling of the exception has occurred. Hence, it is not recommended to do both at the same time, as it often leads to a frustrating experience in debugging.
Use subclasses of java.lang.Exception (checked exceptions), when you except the caller to handle the exception. This results in the compiler throwing an error message if the caller does not handle the exception. Beware though, this usually results in developers "swallowing" exceptions in code.
Use subclasses of java.lang.RuntimeException (unchecked exceptions) to signal programming errors. The exception classes that are recommended here include IllegalStateException, IllegalArgumentException, UnsupportedOperationException etc. Again, one must be careful about using exception classes like NullPointerException (almost always a bad practice to throw one).
Use exception class hierarchies for communicating information about exceptions across various tiers. By implementing a hierarchy, you could generalize the exception handling behavior in the caller. For example, you could use a root exception like DomainException which has several subclasses like InvalidCustomerException, InvalidProductException etc. The caveat here is that your exception hierarchy can explode very quickly if you represent each separate exceptional scenario as a separate exception.
Avoid catching exceptions you cannot handle. Pretty obvious, but a lot of developers attempt to catch java.lang.Exception or java.lang.Throwable. Since all subclassed exceptions can be caught, the runtime behavior of the application can often be vague when "global" exception classes are caught. After all, one wouldn't want to catch OutOfMemoryError - how should one handle such an exception?
Wrap exceptions with care. Rethrowing an exception resets the exception stack. Unless the original cause has been provided to the new exception object, it is lost forever. In order to preserve the exception stack, one will have to provide the original exception object to the new exception's constructor.
Convert checked exceptions into unchecked ones only when required. When wrapping an exception, it is possible to wrap a checked exception and throw an unchecked one. This is useful in certain cases, especially when the intention is to abort the currently executing thread. However, in other scenarios this can cause a bit of pain, for the compiler checks are not performed. Therefore, adapting a checked exception as an unchecked one is not meant to be done blindly.

You should handle the method as soon as possible, but it must make sense. If the exception doesn't make sense to be thrown by your method, but you can't handle it, wrap it into another exception and throw this new exception.
A bad practice about exception is to catch them all (it's not pokemon, it's java !) so avoid catch(Exception e) or worse catch(Throwable t).

Related

When is throwing/catching general exception acceptable

One of the projects I inherited is riddled with tons of try/catch blocks catching the general Exception. I've been slowly but surely refactoring this, but there are so many, such that I have been contemplating bringing this up as a concern in a meeting. This got me to thinking...Is there ever really a case where catching the general exception is justified in a production environment? I could not think of a case where I NEEDED to catch the general exception, but I'm also a fairly recent grad and I'm sure there's tons that I don't know. I did a little research, and I can find lot's of reasons why NOT to catch the general exception, but nothing concrete on when this practice is justified. Obviously if you're calling a method that already throws Exception you have to catch it. But is there ever a reason some method could throw Exception and it should not be refactored to throw the specific exception.?
Throw Exception only if you need to throw Exception, specifically. If you throw too-general an exception, you are effectively just shouting "there is a problem", without giving specific information as to what that problem is.
Catch Exception only if Exception is thrown, specifically. If you catch too general an exception, you're losing the opportunity to handle specific exceptions in the correct way.
Throwing Exception is the equivalent of returning Object instead of a more-specific type which would be useful to the caller; catching Exception is the equivalent of assigning a return value to an Object variable, rather than a more specific type that you could do useful things with. Basically: you are discarding available type information.
Sometimes you have to throw Exception, because you are writing a general framework. For example, Callable.call throws Exception, because you don't know what code will be executed there, so allowing it to throw Exception means that you don't constrain users of the class. And consequently, if you're calling a Callable, you need to catch Exception; but you need to do it with care.
The vast majority of people aren't (or shouldn't be) writing frameworks, and so you shouldn't be throwing or catching Exception.
There is good advice on this in Effective Java, Item 61, " Throw exceptions appropriate to the abstraction" (this is the number in 2nd Ed; don't know about 3rd Ed). Basically: you almost certainly don't want to throw Exception, but you might want to throw IOException rather than FileNotFoundException, if the fact that you're reading from a file isn't relevant to your API.
Catching general Exception isn't best practice, because if you are catching exception you are telling that you can handle it and recover from that exception state, but if you can't recover then it might be better to fail than to keep working with very unpredictable state.
Another thing that can happen is to catch exception that is supposed to be handled at higher level which can again lead to dangerous state.
There is possibility that code was written before Java 7 when multi-catch was introduced so they used Exception instead of writing each separately, or that developer wasn't familiar with this.
Only case in which catching Exception is justified, in my opinion at least, is at top of the application(main) - catch all exceptions that are not handled at lower levels, log them and exit for safety reasons, and crash nicely and show reasonable message to end user.
This brings us to another thing, and that is throwing Exception, same as with catching one you shouldn't throw Exception, that is same like returning Object from every method, you lose identity.
If this two things are very common in project you are working on maybe you should consider mentioning that to senior developer.

Re-throwing RuntimeExceptions after catching Checked Exceptions [duplicate]

This question already has answers here:
What issues may ensue by throwing a checked exception as a RuntimeException?
(6 answers)
Closed 9 years ago.
In Java it is observed that there is a convention of re-throwing a RuntimeException just after handling a Checked Exception.
This way has both good and bad consequences. When the compiler forces something to be handled via a Checked Exception, the developer can just get rid of it by catching it and re-throwing it as a RuntimeException.
Can someone explain if this scenario can be considered as a good practice? If so, would this approach be less error prone or would it make the code base unstable?
Actually it is the incompetent attempts at handling checked exceptions which result in an unstable code base. Typically, you'll have this:
try {
//stuff
} catch (IOException e) {
log.error("Failed to do stuff", e);
throw e;
}
and then next level up you'll have to deal with it again, typically logging it all over and making a mess of the log files. It will be even worse if you don't rethrow:
try {
// do stuff
} catch (IOException e) {
return null;
}
Now the calling code has no idea something went wrong, let alone what. Compared to those attempts, this actually accomplishes exactly what the application logic needs:
try {
// do stuff
} catch (IOException e) {
throw new RuntimeException(e);
}
Now the exception can freely propagate up the call stack until it reaches the well-defined exception barrier, where it:
aborts the current unit of work;
gets logged at a single, unified spot.
In a nutshell, to decide whether to catch-and-handle or catch-and-rethrow, just ask yourself this question:
Must the occurrence of this exception abort the current unit of work?
if yes: rethrow an unchecked exception;
if no: provide meaningful recovery code in the catch-block. (No, logging is not recovery).
From many years of real-life experience I can tell you that more than 90% of all possible checked exceptions are of the "aborting" type and need no handling at the place of occurrence.
Argument against the language feature of checked exceptions
Today, checked exceptions are widely recognized as a failed experiment in language design, and here's the key argument in a nutshell:
It is not up to the API creator to decide on the semantics of its exceptions in the client code.
Java's reasoning is that exceptions can be divided into
exceptions resulting from programming errors (unchecked);
exceptions due to circumstances outside of programmer's control (checked).
While this division may be real to some extent, it can be defined only from the perspective of client code. More to the point, it is not a very relevant division in practice: what truly matters is at what point the exception must be handled. If it is to be handled late, at the exception barrier, nothing is gained by the exception being checked. If handled early, then only sometimes there is a mild gain from checked exceptions.
Practice has confirmed that any gains afforded by checked exceptions are dwarfed by real-life damage done to real-life projects, as witnessed by every Java professional. Eclipse and other IDEs are to blame as well, suggesting inexperienced developers to wrap code in try-catch and then wonder what to write in the catch-block.
Whenever you encounter a method which throws Exception, you have found yet another living proof of the deficiency of checked exceptions.
The idea of checked exceptions is "Java only" - as far as I know, no language after Java adopted this idea.
There are too many checked exceptions which are caught ... and silently ignored.
If you look at Scala, they dropped it as well - it's only there for Java compatibility.
In this tutorial on Oracle's web site, you will find this definition:
If a client can reasonably be expected to recover from an exception, make it a checked exception.
If a client cannot do anything to recover from the exception, make it an unchecked exception.
This notion has been adopted in Scala as well, and it works fine.
Technically speaking your proposal works. Discipline and code reviews are required in either way.
The term "can just get rid of it" is not totally correct in this case. This is getting rid of exceptions:
try {
} catch (Exception e){
e.printStacktrace();
}
This is the most common bad practice among the try-catch use. You are catching the exception and then, just printing it. In this case, the catch block catches the exception and just prints it, while the program continues after the catch block, as if nothing had happened.
When you decide to catch a block instead of throwing an exception, you must be able to manage the exception. Sometimes exceptions are not manageable and they must be thrown.
This is something you should remember:
If the client can take some alternate action to recover from the
exception, make it a checked exception. If the client cannot do
anything useful, then make the exception unchecked. By useful, I mean
taking steps to recover from the exception and not just logging the
exception.
If you are not going to do something useful, then don't catch the exception. Re-throwing it as a RuntimeException has a reason: as stated before, the program just cannot continue as nothing happened. This way, a good practice would be:
try {
} catch (Exception e){
//try to do something useful
throw new RuntimeException(e);
}
This means: you just caught an Exception (like an SQLException) from which you can't recover without stopping and resetting the thread. You catch it, you try to make something in between (like resetting something, closing open sockets, etc...) and then you throw a RuntimeException().
The RuntimeException will suspend the whole thread, avoiding the program continue as if nothing have happened. Furthermore, you were able to manage the other exception without just printing it.
It may or may not be okay, depending on the context, but it probably is not.
As a rule of thumb RuntimeExceptions should only be used to indicate programming errors (examples include IllegalArgumentException and IllegalStateException). They don't have to be checked exceptions because you generally assume your program is correct until proven otherwise and you cannot handle these exceptions in a meaningful manner (you have to release an updated version of the program).
Another valid use of runtime exceptions is when you use a framework that will catch and handle the exception for you. In such a scenario it would only be burdensome to having to declare the exception in every method when you are not going to handle it anyway.
So generally speaking I would say re-throwing a checked exception as a runtime exception is very bad practice unless you have a framework that will handle it properly.
The general rule is: you throw a checked exception when the caller might be able to do some kind of recovery when informed about it. Otherwise, throw an unchecked exception.
This rule applies when an exception is first thrown.
But this also applies when you catch an exception and are wondering whether to throw a checked or unchecked exception. So there is no convention to throw a RunTimeException after catching a checked one. It is decided in a case-by-case basis.
One small tip: if you are going to just re-throw an checked exception after catching one and do nothing else, most of the time it is alright to just not catch the exception and add it to the exceptions thrown by the method.

difference between errors and unchecked exceptions in java?

As we know if any error or any unchecked exception occurs then our program will halt, then what are the differences between those?
In short:
You can, and probably should, recover from an exception.
You can, but should not, recover from an error.
From the Error Javadoc:
An Error is a subclass of Throwable
that indicates serious problems that a
reasonable application should not try
to catch. Most such errors are
abnormal conditions. The ThreadDeath
error, though a "normal" condition, is
also a subclass of Error because most
applications should not try to catch
it.
Versus the Exception Javadoc
The class Exception and its subclasses
are a form of Throwable that indicates
conditions that a reasonable
application might want to catch.
So, even though an unchecked exception is not required to be caught, you may want to. An error, you don't want to catch.
Unchecked Exception:
The classes that extend RuntimeException are known as unchecked exceptions
Unchecked exceptions are not checked at compile-time rather they are checked at runtime.And thats why they are also called "Runtime Exception"
They are also programmatically recoverable problems but unlike checked exception they are caused by faults in code flow or configuration.
Example: ArithmeticException,NullPointerException, ArrayIndexOutOfBoundsException etc
Since they are programming error, they can be avoided by nicely/wisely coding. For example "dividing by zero" occurs ArithmeticEceeption. We can avoid them by a simple if condition - if(divisor!=0). Similarly we can avoid NullPointerException by simply checking the references - if(object!=null) or using even better techniques
Error:
Error refers irrecoverable situation that are not being handled by try/catch
Example: OutOfMemoryError, VirtualMachineError, AssertionError etc.
This question may also be helpful in this context - Runtime/Checked/Unchecked/Error-Exception
From the JavaDoc:
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.
RuntimeException is the superclass of those exceptions that can be thrown during the normal operation of the Java Virtual Machine.
So, the only difference technically is that they are two different classes. You will only catch both if you declare
catch (Throwable e) { }
But there is a big difference in how they are intended to be used. Unchecked exceptions (RuntimeExceptions) are intended to deal with programming errors and other unexpected problems, but should be caught and handled in the application. Errors are intended to represent problems that the program cannot deal with, such as running out of memory.
Just as checked exceptions are useful for signaling when your methods cannot fulfill their contract, there are other errors outside of your control that can occur that prevent the Java virtual machine from fulfilling its specification, such as when memory is exhausted. Since you can't plan for such errors ahead of time, you would have to catch them everywhere, which defeats the principle of maintaining uncluttered code. Therefore, these errors are unchecked exceptions, meaning exceptions that you don't have to include in a throws clause. You are welcome to catch them (well, some of them), but the compiler won't make you do it.
Unchecked exceptions fall into two categories: those that extend RuntimeException, and those that extend Error. I realize that I said earlier that classes inheriting from class Exception are checked exceptions, but that's only half true: the whole truth is that classes in the Exception hierarchy other than those in the RuntimeException sub-hierarchy are checked exceptions.
Exceptions that extend RuntimeException represent errors that you may want to handle, although you're not required to.
As I stated above, RuntimeExceptions are not checked because making you advertise them would have no effect on establishing the correctness of your methods, and would unnecessarily clutter your otherwise very readable code. Exceptions derived from the Error class, on the other hand, are unchecked because you never want to catch them! Error exceptions are severe errors that require shutting down the virtual machine. InternalError, which I used above, extends VirtualMachineError, which is an Error subclass. OutOfMemoryError is another obvious severe error, but there are others, like StackOverflowError, and various LinkageErrors. A linkage error means something has gone amiss when the class loader tried to load a class for execution, and commonly occurs either because some external source has introduced malicious code in an attempt to circumvent Java's security mechanism, or it came from an out-of-spec byte code generator.
Difference between errors and unchecked exceptions in java?
Unchecked exceptions = class RuntimeException and its subclasses + class Error and its subclasses
There fore the error are part of unchecked exception. Unchecked exception also contains RuntimeException and its subclasses.
The term «reasonable» is relative. As it is, also, the term «application»
As middleware developer, I'm used to deal with unchecked exceptions thrown, or simply ignored, by application developers
What is reasonable to be catched by an application is is a subset of what is reasonable to be catched by its underlying infrastructure (that is, itself, a kind of application)
That's where unchecked exceptions are different from errors. An unchecked can be catched by the infrastructure (i.e. to be registered in a.database) but ignored by an application
Registering an error could be impossible because there could be no JVM to run the registering code (or even the catching code), that's why it's not reasonable to catch them
As an aside, checked exceptions are IMHO overused. Catching them to promote to runtime exceptions is too much usual

Unchecked exceptions in Java: Inherit from Error or RuntimeException?

I would like to handle errors with (unchecked) exceptions. I heared that for each kind of exception I should create a subclass of either Error or RuntimeException.
What's the difference?
Errors should identify programmatically unrecoverable problems (e.g. out of memory). Exceptions should identify programmatically recoverable problems which are caused by unexpected conditions outside control of code (e.g. database down). RuntimeExceptions should identify programmatically recoverable problems which are caused by faults in code flow (read: developer's faults such as null pointer, illegal argument, etc).
In your case you want to inherit from RuntimeException.
I think the JavaDocs kind of say it all:
An Error is a subclass of
Throwable * that
indicates serious problems that a
reasonable application * should not
try to catch. Most such errors are
abnormal conditions. * The
ThreadDeath error, though
a "normal" condition, * is also a
subclass of Error because
most applications * should not try to
catch it.
These are things like stackoverflow, out of memory... you want to extend RuntimeException.
RuntimeException is a special kind of Exception, Exceptions that compiler will not catch. Error is something that is thrown when there is some severe system problem. There is not a close relation between Error and RuntimeException. Yours seem closer to RuntimeException.
Always use RuntimeException--I've virtually never seen a case for Error.
I've heard the same thing about creating your own exception though and I don't really understand it. Often it's useful, but I use InvalidArgumentException ALL THE TIME.

Re-throwing exceptions in Java

In java there is a possibility of re-throwing the exception but there is any advantage in it?
One example of when you want to rethrow an exception is when you don't really know how to handle it yourself, but you'd like to log that the exception was thrown. Rethrowing it allows you to both capture the stack information that you need to log, and pass the exception up the call stack for the caller to handle.
Sure. If you need to perform some special processing (logging, clean up, etc) for the exception, but can't "handle" it completely, it is common to do the processing and then rethrow the exception. Note, that in many cases (especially cleaning up resources) you probably want a finally clause rather than a catch/rethrow.
Sometimes, you want a specific type of Exception to be thrown by a method, but there are rare instances that cause other Exceptions to be thrown within the method. I often wrap the causal Exception with my desired Exception and then rethrow the desired Exception.
This is really useful when you can't determine that the Exception has caused your operation to fail until control is passed to the calling method (or one of its ancestors), since if the process does eventually fail, I can trace back in the stacktrace to see why.
I haven't done Java in years, but from what I remember it's just like other languages with exceptions and OO. Exceptions can be subclassed, and often, you'll want to catch a base class of many exceptions, but might not be able to handle all of them. So say you're handling a remote file transfer, and want to catch all IOErrors, because you handle most of them, but not DiskFull. You can rethrow that, and let someone else deal with it further up the chain, but deal with the other issues, like TransmissionFailed, by re-doing the transmit.
If you can somehow justify that you need to re-throw the same exception that you caught, I'd argue that there is something wrong with your design.
Catching one exception and re-throwing another makes perfect sense. For instance, you may want to add detailed information that the original exception did not have.
Real World Cases
Here are some real world situations in which I needed to rethrow java exceptions:
When doing JDBC call, I would catch a SQLException. However, postgres would throw a PSQLException with additional data and status. In testing edge cases we were able to corrupt the database and we wanted the logger to have very specific data on the exception and state. We would wrap the original exception in a new exception with more data regarding the server state and rethrow.
When implementing a text parser, I would want to catch a number of runtime parsing exceptions such as NumberFormatException and pass them up the stack with additional data on what text caused and the source of the text that caused the parsing exception.
My coworker told me of a project in which he worked where every exception was wrapped in another exception of one of two types - RetryableException and FatalException. In the case of a Retryable exception, the application would wait and retry the operation after a fixed period of time. I'm not exactly sure about how I feel about this design, but I can see it as a stop-gap for dealing with some transactional issues.
In some cases I would be using an existing API that had a throws defined for a high-level exception and I would be doing an operation that would throw an unrelated exception (that I felt really belonged as a RuntimeException) - I then would rethrow the exception as the cause of the more general exception.
The most pure case that I can think of in which you may want to rethrow an exception is when you want to add additional data to it. For example:
public bizMethod() throws CoolBizLogicException {
int policyId = getPolicyId("bar");
try {
coolBizLogic(foobar); // this throws an exception
}
catch (CoolBizLogicException cble) {
cble.setPolicyId(policyId);
throw cble;
}
}
I don't think so. If you can't handle it, don't catch it.

Categories

Resources