'java: can't rethrow exception: Unhandled exception type Exception

I'd like to catch an exception, log it, set a flag, and the rethrow the same exception

I have this code:

public Boolean doJobWithResult() {
    boolean result = true;
    final Feed feed = Feed.findById(feedId);
    try {
        feed.fetchContents();
    } catch (Exception ex) {
        result = false;
        Logger.info("fetching feed(%d) failed", feedId);
        throw ex;
    }
    return result;
}

But eclipse complains at throw ex, telling that "Unhandled exception type Exception", and suggests me to add a try-catch block around it.

In fact, I want the process calling this method to handle the exception, and not handle it myself... I just want to return true if everything goes ok, and log it if there's an exception

On the other hand, I can wrap the exception inside another exception, but I can't throw the same one..

any idea?



Solution 1:[1]

Your doJobWithResult method needs to declare that it can throw Exception:

public Boolean doJobWithResult() {

becomes

public Boolean doJobWithResult() throws Exception {

Solution 2:[2]

You can throw the same exception if you add throws Exception to your method signature. Otherwise you can throw a RuntimeException.

public Boolean doJobWithResult() { 
    boolean result = true; 
    final Feed feed = Feed.findById(feedId); 
    try { 
        feed.fetchContents(); 
    } catch (Exception ex) { 
        result = false; 
        Logger.info("fetching feed(%d) failed", feedId); 
        throw new RuntimeException(ex); 
    } 
    return result; 
} 

In such a case, you won't need to indicate that public Boolean doJobWithResult() throws something but make sure you handle it properly later on (catch or expect your thread to stop... it's a RuntimeException afterall).

Solution 3:[3]

Since Exception is checked, an alternative to catching the Exception is to declare your method as throwing it:

public Boolean doJobWithResult() throws Exception {
    // ...
}

Solution 4:[4]

If doJobWithResult doesn't have to handle the exception, then remove the catch block and add "throws Exception" to the method signature. The exception logging can be done in the class/method that have to deal with the Exception in a corresponding try/catch block.

Solution 5:[5]

There is no need to set the result as false in the catch block, as the value won't be returned(as we are throwing an exception).

Your method should also declare that it throws an exception and so the client will be forced to handle it.

Also consider using a more specific exception which will be thrown in this particular case.

Solution 6:[6]

Add throws Exception to your method. You also don't need to add result = false; in your catch block.

Solution 7:[7]

I think the way you handle this exception is really appropriate if any failure of feed.fetchContents() method cannot be recovered. (Idea is better to halt rather than continuing) Apart from that I would suggest you to use more specific exception hierarchy.

And another thing I got from effective java book is if you write such a method you must document with @throw (in comments) with the reason.

Solution 8:[8]

You could throw an unchecked exception

 Logger.info("fetching feed(%d) failed", feedId);
 throw new RuntimeException(ex);

Solution 9:[9]

I spent the last hour looking for it since not even the Complete Reference book mentions this explicitly: unhandled throw ThrowableInstance works only with unchecked exceptions.. And only runtime exceptions are unchecked. By unhandled I mean something like this:

class ThrowDemo {
  static void demoproc() {
    try {
      throw new NullPointerException("demo");
    } catch(NullPointerException e) {
      System.out.println("Caught inside demoproc.");
      throw e; // re-throw the exception
    }
  }

  public static void main(String args[]) {
    try {
      demoproc();
    } catch(NullPointerException e) {
      System.out.println("Recaught: " + e);
    }
  }
}

This example is taken verbatim from the Complete Reference book (9th edition).

The first throw statement i.e throw new NullPointerException("demo"); is handled by the following catch block, but the second throw statement i.e. throw e; is unhandled by the demoproc() method. Now this works here and the above code compiles successfully because NullPointerException is a runtime/ unchecked exception. If the e instance were a checked exception or even an Exception class instance then you'd get an error saying the exception e is unhandled and you'd either have to handle it within demoproc() or you'd have to explicitly declare that demoproc() throws an exception using throws in the method signature.