views:

123

answers:

4

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.

+1  A: 

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

Colin Hebert
What do you mean with "wrap it in another exception"? Why not just re-throw the original exception?
Pepijn
@Dennetik, in java you have to catch checked exceptions or declare them to be thrown. It inevitably leads to wrapping (or swallowing, which is a bad thing). Otherwise your throws list grows out of control or you bump into an interface that doesn't allow you to throw checked exceptions.
Yishai
Because sometime simply rethrowing the original exception doesn't makes sense, for example if you handle a connection to a database to get an entity, and it throws a SQLException, you don't really want to re-throw an SQLException, but rather one of your own exception, which makes sense in your code.
Colin Hebert
Rethrowing exceptions is a bad habit, either handle them or let them propagate.
rsp
Wrap the cause. This allows the original cause to show up in the final stack trace which may be all for the developer to see.
Thorbjørn Ravn Andersen
+4  A: 

Please check Best Practices for Exception Handling

stacker
A: 

Check this nice crisp article about exception design

http://littletutorials.com/2008/05/23/exceptional-java-exception-design-relativity/

pure.java
+4  A: 

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.
Vineet Reynolds
I don't agree that details are lost when an exception is rethrown.
Thorbjørn Ravn Andersen
@Thorbjorn, ah yes. Not enough caffeine :-) I've reworded the last section to reflect the actual intention.
Vineet Reynolds