1

Short version: How do I catch all java.lang.Error thrown in a particular section of code in order to log them, and also allow them to propogate up the call stack as if I hadn't caught them at all?

Long version...

In a section of code I want to catch all java.lang.Error in order to log them. But I also want to let the Error continue to work its way up the call stack so the behaviour would be the same as if I hadn't caught it at all.

Additionally, I want to catch and log all java.lang.Exceptions and then let them ALSO propogate up the call stack.

I tried this...

    } catch (Throwable e) {
        e.printStackTrace();
        throw e;
    } 

...but the problem with that is I have to modify every method higher up in the call stack to throw Throwable, and some of those methods aren't mine to modify (my method is called by a method in a third party framework).

I would be happy with some kind of wrapping technique, whereby I would put the Throwable in something else and throw that, but I would much prefer to let any java.lang.Errors propogate upward in their natural fashion, as if I hadn't caught them at all.

Suggestions?

EDIT: It was asked "Why do I want to do this?". I think that's a good question which I will clarify: This is a framework for use in my company. It depends on other frameworks contained in jars, that the system admin might have forgotten to include. In that case there is a NoClassDefFoundError in certain places in the code. But only the user sees this Error in the browser, it is not found in the server logs. I want to log it so the system admin can know that this Error has occurred, as he will have instructions for dealing with it.

John Fitzpatrick
  • 3,857
  • 4
  • 44
  • 69
  • 1
    Why do you want to do this? – ddmps Mar 03 '13 at 20:01
  • 1
    First of all, you usually [don't want to catch errors](http://stackoverflow.com/questions/352780/when-to-catch-java-lang-error), only exceptions. Second of all, this should work. Errors are not "checked," a property reserved for Exceptions that don't extend RuntimeException, so methods can throw Errors without declaring explicitly that they throw them. – Alexis King Mar 03 '13 at 20:03
  • @Pescis: In order to log the Error. If only the user sees the Error in a stack trace in the client, I have no troubleshooting capabilities for that Error. – John Fitzpatrick Mar 03 '13 at 20:04
  • @Jake King: Do you mean I can do this: `catch (Error e) { e.printStackTrace(); throw e;}` without declaring that my method throws `Error`? – John Fitzpatrick Mar 03 '13 at 20:08
  • @Pescis: A bit of elaboration on "why". This is a framework for use in my company. It depends on other frameworks contained in jars, that the system admin might have forgotten to include. In that case there is a NoClassDefFoundError in certain places in the code. But only the user sees this Error in the browser, it is not found in the server logs. I want to log it so the system admin can know that this Error has occurred, as he will have instructions for dealing with it. – John Fitzpatrick Mar 03 '13 at 20:19
  • @JohnFitzpatrick Yes, you can throw an Error without having the method throw it. – ddmps Mar 03 '13 at 20:25
  • What I don't understand is why you want to catch it at every level if you're only going to log it at the top level. Even if you don't catch them they're still getting thrown upwards in the stack trace as normally, so you can only catch it at that level and log it there. – ddmps Mar 03 '13 at 20:26
  • 2
    If the problem is that a class might not be found, try calling `Class.forName` and catching ClassNotFoundException, in order to prevent the code from ever executing which might try to access a missing class. – VGR Mar 03 '13 at 20:30
  • Any server-side application that doesn't have a proper *exception barrier*, which consists of a `catch (Throwable t) { log.error("Error occurred",t); }` plus any other cleanup code, is a broken application. I would fix that first---and then no other fixing that you suggest would be necessary, or even advised due to double logging that would result. – Marko Topolnik Mar 03 '13 at 20:48
  • @VGR: I like that suggestion. I will use it. – John Fitzpatrick Mar 03 '13 at 21:02

1 Answers1

6

You said: "I tried this..."

    } catch (Throwable e) {
        e.printStackTrace();
        throw e;
    } 

You should try instead:

    } catch (Error e) {
        e.printStackTrace();
        throw e;
    } 

Errors are not checked exceptions. You don't have to declare them in any method signature. Just put that in your outermost method and it will do what you want.

Edit:

If you want to also catch and rethrow Exception, let's think about it. You have three kinds of Throwable: Error, Exception and RuntimeException. Error and RuntimeException are not checked, but Exception which are not RuntimeException are.

So, you can do the same thing for RuntimeException as we do for Error:

    } catch (RuntimeException e) {
        e.printStackTrace();
        throw e;
    } catch (Error e) {
        e.printStackTrace();
        throw e;
    } 

And what about Exception who are not RuntimeException? The thing to understand is that these are checked exceptions and if they are not declared in the methods that the code is calling, then they will not be thrown. So you don't need to catch/rethrow them. If some of the methods called actually throw such an exception, then you will have to catch/rethrow it and mark your method as throwing that exception, but you would have to do that anyway since they are coming from methods the outer method is calling.

Community
  • 1
  • 1
Cyrille Ka
  • 14,374
  • 5
  • 35
  • 58