Consider the compare method of java.util.Comparator: int compare(T o1, T o2) throws ClassCastException What do you do if you implement Comparator, and you have an SQLException whilst performing the comparison? You cannot alter the signature of the Comparator interface's compare method. You are forced to either swallow the exception, or wrap it as a RuntimeException. Clearly, traditional advice for using checked exceptions falls apart when you are required to write code to play nicely with other people's interfaces. An ExceptionStrategy that addresses these issues and affords us ConsistencyOfApproach is described below. * We want to LetExceptionsPropagate so that problems we cannot deal with ourselves can be handled at a higher level. Frequently we do this to abort an operation or to rollback a transaction and log the problem. * We want to ensure that NoMethodShouldEverThrowAnExceptionThatIsImplementationSpecific. That means that we should never try to handle an implementation specific exception further up the call chain. Therefore we want to throw an exception that indicates a problem, without being specific about what that problem was. * We don't want to HomogenizeExceptions, because when code outside of our control calls us, we may have no choice as to the range of exceptions we throw. A common example is when we implement an interface, such as the java.util.Comparator interface, where when we implement the compare method we are only allowed to throw a ClassCastException, and not one of our own HomogenizedExceptions. * We want to throw our own CheckedException in order to indicate a specific failure that our caller may be able to act intelligently upon. Declaring a CheckedException has the benefit of forcing the caller to consider particular problem circumstances, and encourages clearer code documentation. * We should LetExceptionsPropagateOnlyAsUncheckedExceptions, UseCheckedExceptionsOnlyForSpecificActionableSituations and DontUseCheckedExceptionsToIndicateNonspecificFailure Thus, our strategy is: Class A { void methodA(...) throws Specific''''''CheckedException { /* * if we can throw an exception that the caller may * be able to act intelligently on, then do so */ if(...) throw new Specific''''''CheckedException(); try { doDatabaseThing(); } catch(SQLException e) { /* * if we need to simply indicate failure, then rethrow * it as a RuntimeException. The ExceptionAdapter ensures * that we don't wrap any exceptions that are already unchecked. */ throw ExceptionAdapter.toRuntimeException(e); } } } (See ExceptionAdapter) Summary: when writing a method: If a method that you call throws a checked exception, *always* catch it, and then either * i) take action - e.g. if you get a FileNotFoundException, load a default file instead and log the problem OR * ii) throw your own checked exception to explain the problem. Do this only if you can say something more intelligent than 'I have failed'. e.g. never have you own 'CannotCompleteMethodException', but do have your own 'CodecNotLoaded' exception so that the caller can try and load the necessary codec and retry. OR * iii) if you are thrown an exception by a method you have called and simply need to throw something to indicate that you've failed, wrap that exception as an unchecked RuntimeException and throw it. Note: this means that you *always* catch all checked exceptions thrown by any methods you call, and *never* let them 'pass through' your method because by luck the exceptions you have declared that you throw yourself happen to be the same as or a superset of the exceptions thrown by the methods you call. The whole reason that we want to let unchecked exceptions indicating general failures that we cannot act intelligently on propagate is so that we can abort an operation, abort and rollback a transaction, or log the issue at an appropriate level. Although this means we're not *forced* to try and catch unchecked exceptions by the compiler and we think we might forget, that's the same problem we face if a NullPointerException or other non-checked exception propagates up. We simply need to always remember to catch all checked and unchecked exceptions at the operation/transactional level as appropriate - which would be true whether or not we adopted this entire strategy and because we never know when a NullPointerException or RuntimeException generated by code outside of our control may come along and break our operation/transaction. -- AndreParrie I HaveThisPattern -- PhilippeDetournay ---- Further notes Another variation on this approach is, when creating your own exceptions, to always have them as subclasses of RuntimeException. Then we need not worry about having to wrap our own checked exceptions as RuntimeExceptions to let them propagate, and only need to worry about wrapping other people's checked exceptions. This results in cleaner code. As in C++, it is the responsibility of the programmer using your methods to check your javadoc for a list of exceptions that may be thrown. The thinking behind this approach is that although the programmer using such a method will not be forced to consider each exception that could be thrown, in many if not most cases they will not want to do anything with your exceptions other than to let them propagate. Sun understood this when they made the NullPointer exception a RuntimeException, because it would create too much messy and unnecessary error handling code. We simply apply the same principle here. Consider the propagation of exceptions generated within servlets. In order to propagate, they must either be wrapped inside a ServletException or must be a RuntimeException. The ServletException class adds no value. If the pattern of creating no-added-value exception wrappers were to be followed every time we needed a checked exception to propagate, every package we write would have its own exception wrapper, and exceptions could be wrapped and rewrapped dozens of times while 'bubbling' to the top. ---- ''Have you considered refactoring your code such that a simple comparator could never throw a SQLException? Seriously, while Exception propagation issues are real, I don't find them to be as strange as this. I would never put database code inside a comparator. Perhaps your issues with checked Exceptions are telling you something about your programming style.'' ---- ''Reply: The SQLException example was encountered when using a 3rd party persistence library which supported lazy loading of persistent object fields. Even though optimized code would ensure that those fields being compared were pre-loaded so that no actual additional database access would be required, the method call to retrieve the field still is declared as being capable of throwing one of several data access related exceptions. To assume that the pre-loading was successful and swallow all of these exceptions just to fit with the Comparator interface would be very bad practice, in my opinion.'' ''Good code will always try to allow exceptions to propagate as much as possible, as opposed to 'swallowing' them. I have encountered endless scenarios where I've needed exceptions to propagate even though the interfaces I'm writing code to adhere to does not allow me to throw them. This is a particularly acute problem when the exceptions I may need to propagate are implementation specific, meaning that it would be incorrect for the interface I'm implementing to allow me to throw those implementation specific exceptions.'' ''The best way in my opinion to allow an implementation specific exception to propagate upward is to make it unchecked. The alternatives are to HomogenizeExceptions (which only works within a particar package/module and not between them) or to use the same pattern that Sun used with the ServletException wrapper, which I think results in unnecessary extra code.'' Or even more evil. I would have thrown the SQLException via EvilThrow.ThrowThrowable. ---- See CheckedExceptionsAreOfDubiousValue JavaExceptionsAreParticularlyEvil ThrowDontCatch ---- CategoryException CategoryJava