Idiom to let a specific exception bypass a broad catch block? - java

Often, when implementing a template method or interface method, you can only throw one specific type of exception defined by the method. But your implementation may make class to API's that throw an incompatible exception type, or many different exception types.
Naturally you need to catch them and wrap the exceptions into the type suitable for the implemented method signature. Lets assume we want to implement this interface:
public interface SomeDataGetter {
public long getSomeData() throws IOException;
}
Our implementation makes use of some other API product to implement this, and the API method we are calling may have this signature:
public long loadFromDBOrCache(Object ... params) throws SQLException, IOException, ObjectNotFoundException, RuntimeException, FridayException, NotWeekendException, NumberIs42Exception;
I made this up to demonstrate the case where you can't exactly enumerate all the possibly thrown exceptions by concrete type. Do note that IOException is a type we are allowed to throw from our implementation.
Now I can go the lazy route when implementing this and wrap anything to fit my signature:
#Override
public long getSomeData() throws IOException {
try {
return loadFromDB(...);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
This will obviously wrap any exception into an IOException (even an IOException) and it works out ok. But I'd like to not wrap IOExceptions, since I am allowed to throw those without wrapping them:
#Override
public long getSomeData() throws IOException {
try {
return loadFromDB(...);
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
You can imagine this gets cumbersome quickly if there are multiple possible exception in the implementation and multiple exceptions you are allowed from the implementation. I need an extra catch for each exception I want to pass throgh.
Whats the best idiom to keep that readable (also, I'm lazy, and don't want to write all these extra catches) and still avoid unneccessary exception nesting? Or shoud I not bother and just wrap everything?

One approach would be making a method that wraps all "prohibited" exceptions in an allowed one, while returning all the allowed ones unwrapped, like this:
private static void throwIoException(Exception e)
throws IOException // <<= Add other "allowed" exceptions here
{
if (e instanceof IOException) {
throw (IOException)e;
}
... // <<= Add checks for other "allowed" exceptions here
throw new IOException(e.getMessage(), e);
}
Now you can use a single catch block, and do the wrapping as needed:
try {
return loadFromDB(...);
} catch (Exception e) {
throwIoException(e);
}
One unpleasant consequence of this is that the stack trace shows the utility method at the top of the newly created IOException, but that's not important, because the real exception is the wrapped one, not the IOException wrapper. If the exception that you caught happens to be IOException, the correct stack trace should remain in place.

I would consider the lazy route of wrapping all exceptions you get into IOExceptions (or another checked exception) to be a bad practice. Instead I would consider wrapping the exceptions in runtime exceptions, thereby bypassing the catch or specify requirement. E.g.
#Override
public long getSomeData() throws IOException {
try {
return loadFromDB(...);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
The reason why this is better is that checked exceptions carry a certian meaning. If you catch for instance a ParseException in your code and rethrow that as a IOException you are lying. As a user of your code I might be able to do something about certain types of checked exceptions, but if you obfuscate the true cause of an exception it will be more difficult to debug the code when an error occurs.
In general I think you should minimize the use of checked exceptions since it litters error handling code throughout your application. Also if you are using someone else's code you have no guarantee that a RuntimeException won't be thrown anyway (unless you carefully read through it all). Therefore you have to consider that possibility anyway and handle it somewhere so your application don't crash. The virtues of unchecked exception vs checked exceptions has been discussed quite a lot elsewhere here and here for instance.

Related

Try/Catch everything and rethrow Business Exceptions

Imagine some code:
public void doSomething(Object object){
try {
if (object == null)
throw new BusinessException("Object was null");
try {
// do logic actions
} catch (Exception e) {
throw new BusinessException("Something went wrong doing logic", e)
}
try {
// do some IO actions
} catch (Exception e) {
throw new BusinessException("Something went wrong doing IO.", e)
}
} catch(Exception e){
throw new BusinessException("Something went wrong in doSomething.", e)
}
}
The BusinessException is an extension of RuntimeException. I'm told by my manager and another senior engineer that BusinessException is the only exception that should ever get thrown and every method should be designed like the above method to ensure that. Anytime something goes wrong they want the same BusinessException thrown.
They idea is that they want to "abstract" away logical exceptions from the user and only provide "business exceptions" to the user. My manager does not want us to only catch specific exceptions, e.g. IOException They want to always catch(Exception) to make sure nothing is missed.
I don't understand this "abstraction" they are talking about. I'm pretty sure nothing is being "abstracted" away, an exception is just being encapsulated (or masked) in a new exception.
Semantics aside, I find this truly bizarre and I'm struggling to understand the value they think this verbose exception handling provides. It is not hard for me to imagine how this can make debugging more difficult. If any business exception gets thrown it immediately gets caught by another catch block and re-wrapped into a new exception, complicating the stack trace and potential debugging efforts.
It also seems like a performance issue to have so much exception instantiation.
Further, this is a spring boot application and we already have a ResponseEntityExceptionHandler
#ControllerAdvice
public class MyAppResponseEntityExceptionHandler extends ResponseEntityExceptionHandler{
#ExceptionHandler(value = { IllegalArgumentException.class })
protected ResponseEntity<Object> handleConflict(IllegalArgumentException ex, WebRequest request) {
String bodyOfResponse = "Check the arguments";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}
// Several more for different exception types...
}
Is this just a "to each their own" situation or is this objectively a problem?
First of all, it's never recommended to have a generic catch block that catches and instance of Throwable or Exception, unless it exists in a chain of catch blocks, for example:
public void doSomething() {
try {
// do some database stuff
} catch (SQLException e) {
throw new BusinessException("something went wrong with database", e);
}
try {
// do some IO stuff
} catch (IOException e) {
throw new BusinessException("something went wrong with IO");
}
}
Now anything other than those two exceptions shouldn't be caught, since it's not the responsibility of this particular function, function should only complain about errors that are relative to what they do.
as a caller I might do something like this:
SomethingDoer s = new SomethingDoer();
s.doSomething();
now if I'm worried that an exception might get thrown unexpectedly, it's my responsibility as a caller to handle it, so the API deligates the uncaught exception for the caller to handle, like so:
SomethingDoer s = new SomethingDoer();
try {
s.doSomething();
} catch ( BusinessException e) {
LOGGER.error(e.message) // prod logging
LOGGER.debug(e) // debug logging with stacktrace
// hypothetical error listener
errorListener.onError(e);
//handle or log, but not rethrow.
} catch (Exception e) { // cringe..
LOGGER.error("something went wrong, unexpectedly"); // prod logs
LOGGER.debug("something went wrong, unexpectedly", e); // debug logs with stacktrace
/* logged AND rethrown since up till this point all expected
exceptions should be wrapped and rethrown or logged,
so if we get here its a fatal error, and you need to interrupt the application*/
throw e;
The latter - cringe looking - catch( Exception e) block is also not recommended and the exception should be propagated up the stack to the main thread, Checked Exceptions are usually handled that way.
So language specific exceptions - internal - should be caught and wrapped in a BusinessException even before reaching the ControllerAdvice handler and this handler - since it is relatively close to the view layer of the app should only handle business specific exceptions and not internal exceptions.
Your manager and senior engineer may be considering Effective Java. From the third edition, Item 73: Throw exceptions appropriate to the abstraction.
It is disconcerting when a method throws an exception that has no apparent connection to the task that it performs. This often happens when a method propagates an exception thrown by a lower-level abstraction. Not only is it disconcerting, but it pollutes the API of the higher layer with implementation details. If the implementation of the higher layer changes in a later release, the exceptions it throws will change too, potentially breaking existing client programs.
To avoid this problem, higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction. This idiom is known as exception translation.
Perhaps your manager is being overzealous with this bit of advice. Effective Java goes on to caution,
While exception translation is superior to mindless propagation of exceptions from lower layers, it should not be overused.
You may be justified in pointing out this overuse to your manager, but I suspect persuasion will be difficult. You can take some solace in Item 72: Favor the use of standard exceptions. I personally prefer that advice, and tend to avoid creating custom exceptions, but certainly other developers feel differently.
It is like, the end user doesn't know what to do with exception so a generic exception will be better.
You can write diff custom exceptions for diff type of operations, like Database calls, api calls and return only one type of exception to the caller.
i.e You can define you custom exception like this.
public class BusinessException extends RuntimeException {
private final ErrorCodes errorCode;
private final Object body;
public BusinessException(String message, ErrorCodes errorCode) {
super(message);
this.errorCode = errorCode;
this.body = null;
}
public BusinessException(String message, ErrorCodes errorCode, Object body) {
super(message);
this.errorCode = errorCode;
this.body = body;
}
}
Where ErrorCodes is the enum that will be having the ErrorCodes like InternalError, EntityNotFound, Unauthorised.
Now you can use this custom exception, you will catch any exception in the application and throw this exception with proper error message and error code.
Something like this.
throw new BusinessException("Error while fetching some api data.", INTERNAL_SERVER_ERROR);
or
throw new ServiceException("User is not authorised to perform operation.", UNAUTHORIZED);

Java: Using Catch and throws in the one block?

What is the point of catching and then also throwing an Exception like below? Is it bad practice to do both?
try{
//something
} catch (Exception e){
throw new RuntimeException("reason for exception");
}
Usually, such code is used to re-wrap exceptions, that means transforming the type of the exception. Typically, you do this when you are limited in what exceptions are allowed out of your method, but internally other types of exceptions can happen. For example:
class MyServiceImplementaiton implements MyService {
void myService() throws MyServiceException { // cannot change the throws clause here
try {
.... // Do something
} catch(IOException e) {
// re-wrap the received IOException as MyServiceException
throw new MyServiceException(e);
}
}
}
This idiom enables to keep propagating exceptions to the caller, while conforming to the throws clause in the interface and hide the details of the internals (the fact that IOExceptions can happen).
In practice, this is always better than just calling e.printStackTrace() which will actually "swallow" the error condition and let the rest of the program run as if nothing had happened. In this respect, behaviour of Eclipse is quite bad as it tends to auto-write such bad-practice constructs if the developer is not careful.
This is called rethrowing an exception, and it is a common pattern.
It allows you to change the class of the exception (such as in this case), or to add more information (also the case here, as long as that error string is meaningful).
It is often a good idea to attach the original exception:
throw new RuntimeException("cause of the problem", e);
Rethrowing as an unchecked exception (a RuntimeException) is sometimes necessary when you still want to throw an exception, but the API of your method does not allow a checked exception.
In your example, an Exception is caught and a RuntimeException is thrown, which effectively replaces a (potentially) checked exception with an unchecked exception that doesn't have to be handled by the caller, nor declared by the throwing method in a throws clause.
Some examples :
This code passes compilation :
public void SomeMethod ()
{
try {
//something
} catch (Exception e){
throw new RuntimeException("reason for exception");
}
}
This code doesn't pass compilation (assuming "something" may throw a checked exception) :
public void SomeMethod ()
{
//something
}
An alternative to catching the Exception and throwing an unchecked exception (i.e. RuntimeException) is to add a throws clause :
public void SomeMethod () throws Exception
{
//something
}
This is one use case of catching one type of exception and throwing another. Another use case is to catch one type of exception and throw another type of checked exception (that your method declares in its throws clause). It is sometimes done in order to group multiple exceptions that may be thrown inside a method, and only throw one type of exception to the caller of the method (which makes it easier for them to write the exception handling code, and makes sense if all those exceptions should be handled in the same manner).

Is it possible to ignore an exception?

In Java, is it possible to make a method that has a throws statement to be not checked.
For example:
public class TestClass {
public static void throwAnException() throws Exception {
throw new Exception();
}
public static void makeNullPointer() {
Object o = null;
o.equals(0);//NullPointerException
}
public static void exceptionTest() {
makeNullPointer(); //The compiler allows me not to check this
throwAnException(); //I'm forced to handle the exception, but I don't want to
}
}
You can try and do nothing about it:
public static void exceptionTest() {
makeNullPointer(); //The compiler allows me not to check this
try {
throwAnException(); //I'm forced to handle the exception, but I don't want to
} catch (Exception e) { /* do nothing */ }
}
Bear in mind, in real life this is extemely ill-advised. That can hide an error and keep you searching for dogs a whole week while the problem was really a cat(ch). (Come on, put at least a System.err.println() there - Logging is the best practice here, as suggested by #BaileyS.)
Unchecked exceptions in Java extend the RuntimeException class. Throwing them will not demand a catch from their clients:
// notice there's no "throws RuntimeException" at the signature of this method
public static void someMethodThatThrowsRuntimeException() /* no need for throws here */ {
throw new RuntimeException();
}
Classes that extend RuntimeException won't require a throws declaration as well.
And a word from Oracle about it:
Here's the bottom line guideline: 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.
There are 3 things you can do :
Throw a RuntimeException (or something extending a RuntimeException, like NullPointerException, IllegalArgumentException,...), you don't have to catch these as they are unchecked exceptions.
Catch the exception and do nothing (not recommended) :
public static void exceptionTest() {
makeNullPointer(); //The compiler allows me not to check this
try {
throwAnException(); //I'm forced to handle the exception, but I don't want to
} catch (Exception e) {
// Do nothing
}
}
Change exceptionTest () declaration to say that it throws an Exception, and let the method calling it catch the Exception and do what is appropriate :
public static void exceptionTest() throws Exception {
makeNullPointer(); //The compiler allows me not to check this
throwAnException(); //I'm no more forced to handle the exception
}
In Java there is two kinds of Exceptions, Checked Exceptions and Unchecked Exceptions.
Exception is a checked exception, must caught or thrown.
NullPointerException is a RuntimeException, (the compiler doesn’t forces them to be declared in the throws claus) you can ignore it, ,but it still may occur in the Runtime, and your application will crash.
From Exception documentation:
The class Exception and any subclasses that are not also subclasses of
RuntimeException are checked exceptions. Checked exceptions need to be
declared in a method or constructor's throws clause if they can be
thrown by the execution of the method or constructor and propagate
outside the method or constructor boundary.
From the RuntimeException documentation:
RuntimeException is the superclass of those exceptions that can be
thrown during the normal operation of the Java Virtual Machine.
RuntimeException and its subclasses are unchecked exceptions.
Unchecked exceptions do not need to be declared in a method or
constructor's throws clause if they can be thrown by the execution of
the method or constructor and propagate outside the method or
constructor boundary.
No, it raises a compiler error. Being a checked exception, you must either catch it or propagate it by declaring your method as potentially throwing it.
Check this and this.
Throw a RuntimeException or an exception which is derived from RuntimeException. Then the compiler will not force you to catch it.
The other answers are right, in that they correctly tell you what you should do, but it is actually possible to throw a undeclared checked exception. There are a few ways this can be done; the simplest is:
public void methodThatSecretlyThrowsAnException() {
Thread.currentThread().stop(new Exception());
}
or if your goal is to wrap an existing method that does declare its exception
public void methodThatSecretlyThrowsAnException() {
try {
methodThatAdmitsItThrowsAnException();
} catch(final Exception e) {
Thread.currentThread().stop(e);
}
}
(Needless to say, you should never do this.)
Just catch an exception and dont do any thing with it, leave it as it is and catch the generic exception in case you are not aware of the specific exception
try{
//Your logic goes here
}
catch(Exception e)//Exception is generic
{
//do nothing
}
AS I know, it's impossible in the case. Only unchecked exception, compiler can skip to check. such as RuntimeException.
You can use a loophole in the Java Compiler. Add the following code:
public RuntimeException hideThrow(Throwable e) {
if (e == null)
throw new NullPointerException("e");
this.<RuntimeException>hideThrow0(e);
return null;
}
#SuppressWarnings("unchecked")
private <GenericThrowable extends Throwable> void hideThrow0(Throwable e) throws GenericThrowable {
throw (GenericThrowable) e;
}
You can catch the exception, then invoke hideThrow with the exception to throw it without the compiler noticing. This works because of type erasure. At compile time, GenericThrowable represents RuntimeException because that is what we are passing. At run time, GenericThrowable represents Throwable because that is the basic type in the type parameter specification.
It is not advisable to avoid an exception with an empty catch block even though you are completely sure that is not going to fail under any circumstance. Sometimes, we are not aware of the human factor.
If you are sure that an exception is very unlikely to happen (if not impossible) you should create your own Exception and and wrap the unexpected exception in it.
For example:
private class UnlikelyException extends RuntimeException {
public UnlikelyException (Exception e){
super (e);
}
}
Then wrap your code with a try-catch block and throw your exception, which you don't have to catch
try {
// Your code
} catch (Exception e) {
throw new UnlikelyException(e);
}

Rethrowing checked exceptions

public void foo() {
begin();
try {
...
commit();
} catch (Exception e) {
rollback();
throw e;
}
}
In the sample above, there is an error because foo has no throws Exception. Adding that wouldn't make do the method's usability a lot of good either.
What's the best way to do this? How do you do something if an error occurs without really "handling" the error?
Since Java 8 we use
/**
* Cast a CheckedException as an unchecked one.
*
* #param throwable to cast
* #param <T> the type of the Throwable
* #return this method will never return a Throwable instance, it will just throw it.
* #throws T the throwable as an unchecked throwable
*/
#SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
throw (T) throwable; // rely on vacuous cast
}
You can rethrow a checked exception, but only by avoiding the compilers checked exception validation.
public void foo() throws MyCheckedException {
begin();
try {
...
commit();
} catch (Exception e) {
rollback();
// same as throwing an exception without the compiler knowing.
Thread.currentThread().stop(e);
}
}
Before you use stop() you should read http://download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Thread.currentThread().stop(e) .. is behaviorally identical to Java's throw operation, but circumvents the compiler's attempts to guarantee that the calling method has declared all of the checked exceptions that it may throw:
At least two approaches come to mind, which are usually going to be combined depending on what you want foo to do:
1. Catch and rethrow only the relevant exceptions
There are only so many exceptions the code in your main flow can throw (probably mostly SqlExceptions). So only catch and rethrow those, and declare that you're doing so. More to the point, rethrow only the ones you're not actually handling (in your simplified sample code, you're not handling any, but your real life code is probably more subtle).
Mind you, some of the exceptions may be runtime exceptions, and so you may want to combine this with the below.
2. Don't catch the exception at all
Like this:
// Signature changes to include any exceptions that really can be thrown
public void foo() throws XYZException, ABCException {
// A flag indicating that the commit succeeded
boolean done = false;
begin();
try {
// Don't have any `return` statements in here (or if you do,
// set `done` to `true` first)
...
commit();
done = true; // Commit didn't throw an exception, we're done
} finally {
// finally clause always happens regardless
if (!done) {
// We must be processing an exception; rollback
try {
rollback();
} catch (Exception e) {
// quash it (e.g., leave this block empty), we don't want
// to mask the real exception by throwing a different one
}
}
}
}
Naturally your signature needs to include any exceptions that may be thrown in the main flow, but that's what you're trying to do, if I'm understanding you correctly.
Again, you may well combine these two approaches, because you may want to handle some exceptions and not others.
Wrap it with some RuntimeException which is unchecked.
Adding that wouldn't make do the method's usability a lot of good either.
No. It will be good at documentation, also caller will take care handling it.
Also See
exception-thrown-inside-catch-block-will-it-be-caught-again
throws-or-try-catch
I'd say that in this case rolling back is handling the exception appropriately. It's one of the few cases where it's legitimate to catch and re-throw.
Simply catching and logging an exception is not what I would consider handling. Rather than rethrowing, in that case I'd rather see checked exceptions added to the method signature and let it bubble up.
you may throw a subclass of RuntimeException - they don't require a catch()
the key point is, why should you throw a new Exception from a catch block.
if you use catch then handle your exception there in your catch. If you have to inform the caller method with an exception, then don't catch the exception with try-catch, instead, sign your method with throws and let the caller catch the e xception.
or throw a RuntimeException, i find this idea less useful because of lack of readability, then you don't need to sign your method with throws.
Here you've chanced on one of the biggest religious schisms in the Java, ( if not wider ) , world. It boils down to those that feel, as TJ seems to, and I do too, that checked exceptions are valuable for many reasons, VS the Rod Johnson/Spring school that in the design of Java, checked exceptions were used in many instances where they shouldn't, say closing a resultset or socket, so because it was wrongly used in many cases, it makes them useless so all exceptions should be unchecked. There are many classes in the Spring framework that are very thin wrappers around standard Java objects, but convert checked exceptions to unchecked. It drives me berserk!
Anyway, put me down as strongly agreeing with everything TJ has said, but know that you'll probably never find a "right" answer.
It's worth mentioning some advances in this area.
First, in Java 7, it's possible to catch and throw generic exceptions, as long as what's declared inside the try block is caught or declared in the outer block. So this would compile:
void test() throws SQLException {
try {
conn.commit();
} catch (Throwable t) {
// do something
throw t;
}
}
This is well explained here : http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
Another way is described here : http://blog.jooq.org/2012/09/14/throw-checked-exceptions-like-runtime-exceptions-in-java/
The reason you may want to use that has often to do with lambdas, or throwing exceptions from some generic methods. I ran into this when I wanted to replace repeating constructs of:
try {
do_operation
flag_success
} catch (Throwable e) {
flag_error
throw e;
}
With using a method of:
public static void wrapExec(RunnableT s) {
try {
s.run();
flag_success
} catch (Throwable t) {
flag_error
doThrow(t);
}
}
and therefore replacing the whole try/catch block with just
wrapExec(()->{do_operation})

Java casting an exception (not class cast exception)

When an exception is caught in java is there a use case for casting the exception to a new type? Or is the standard
throw new DiffException(e)
The only way to do it. I apologize if I'm overlooking something but the only search results I get are for "ClassCastExceptions" Which is obviously not what I'm looking for
I believe you meant 'exception wrapping'.
There's no other way to do it - you create a new instance of Exception using a constructor which takes another exception as cause. This works thanks to 1-arg constructor of java.lang.Exception. The typical implementation of custom exception type (like your DiffException) declares such 1-arg constructor too.
Well, if the exception caught (e in your case I suppose) is a subtype of DiffException, you could of course cast it like
throw (DiffException) e;
but I doubt that's what you want to do, since it doesn't make a difference (the e will still have the same runtime type, even in the receiving end).
So the answer is most likely, no, there is no other, equivalent way, of doing
throw new DiffException(e);
than doing just that.
It should be noted however, that doing new DiffException(e) is not called casting but, wrapping, or chaining the exception.
If I understand you correctly here is the use case I am thinking about.
expression:
new FileInputStream("the path");
may throw FileNotFoundException if the file does not exist. FileNotFoundException extends IOException, so you could write code like:
public void readFromFile(String path) {
InputStream in = new FileInputStream(path);
// do something....
}
Now you can call this method as following:
try {
readFromFile("myFile");
} catch (IOException e) {
if (e instanceof FileNotFoundException) {
FileNotFoundException fnfe = (FileNotFoundException)e;
// do something
}
// do something else
}
But I'd recommend you create separate catch blocks for FileNotFoundException and for IOException (at least for this use-case):
try {
readFromFile("myFile");
} catch (FileNotFoundException e) {
// do something with FileNotFoundException
} catch (IOException e) {
// do something with IOException
}
This code does not contain instanceof, casting and other ugly stuff.
Since you mentioned use cases, the common one in Java is wrapping a checked exception as unchecked; this is appropriate when there's no way the checked exception can occur, such as here:
public static Reader getUTF8Reader(InputStream is) {
try {
return new InputStreamReader(inputStream, "UTF-8");
} catch(UnsupportedEncodingException e) {
// should never happen since UTF-8 is guaranteed to be available as per
// http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html
throw new RuntimeException("UTF-8 not available", e);
}
}
Without wrapping the exception, you'd either have to swallow it (which feels wrong) or declare the method as throws UnsupportedEncodingException which forces anyone using it to catch the exception that will never be thrown. Wrapping it, there's no onus on the caller to handle unlikely cases, yet we're protected in the unlikely event that UTF-8 isn't available on some obscure platform in the future.

Categories