Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rescuing a swallowed Exception in Java

Some 3rd party library swallowed an Exception:

String getAnswer(){
    try{
        // do stuff, modify instance state, maybe throw some exceptions
        // ...
        return computeAnswer(); 
    }catch (SomeException e){
        return null;
    }
}

As much as I want to change it into:

String getAnswer() throws SomeException{
    // do stuff, modify instance state, maybe throw some exceptions
    // ...
    return computeAnswer();
}

I can't, because the library is already packaged into a jar. So, is there a way to bring the exception back?

I don't need to rethrow, a stacktrace with exception and message would work too.

I don't think reflection would help here, Unsafe perhaps?

Yes I know I can use a debugger to find out what's happening, but that wouldn't be very useful if I need the exception at runtime for logging and stuff like that

like image 518
tom91136 Avatar asked Sep 02 '15 16:09

tom91136


People also ask

What is swallowing exception in Java?

In computer programming, error hiding (or error swallowing) is the practice of catching an error or exception, and then continuing without logging, processing, or reporting the error to other parts of the software. Handling errors in this manner is considered bad practice and an anti-pattern in computer programming.

How do you fix an exception in Java?

The try-catch is the simplest method of handling exceptions. Put the code you want to run in the try block, and any Java exceptions that the code throws are caught by one or more catch blocks. This method will catch any type of Java exceptions that get thrown. This is the simplest mechanism for handling exceptions.

What happens if an exception is not caught in Java?

What happens if an exception is not caught? If an exception is not caught (with a catch block), the runtime system will abort the program (i.e. crash) and an exception message will print to the console.

What are the 3 types of exceptions?

There are three types of exception—the checked exception, the error and the runtime exception.


2 Answers

You can do it without reflection or AOP. The main idea is to throw another (unchecked) exception in the constructor of SomeException. There are some limitations (see at the end of this answer) but I hope it fits your needs.

You need to replace the SomeException with a new version (just create a SomeException.java file in the original package but in your src directory) with something like :

package com.3rdpartylibrary;

public class SomeException extends Exception {
    public static class SomeExceptionWrapperException extends RuntimeException {
        public SomeExceptionWrapperException(final SomeException ex) {
            super(ex.getMessage(), ex);
        }
    }

    public SomeException(final String message) {
        super(message);
        throw new SomeExceptionWrapperException(this); //<=== the key is here
    }
}

The SomeExceptionWrapperException has to be unchecked (inherit from RuntimeException or Error). It will be our wrapper to carry the SomeException accross the ugly 3rd party catch(...)

Then you can catch the SomeExceptionWrapperException in your code (and eventually rethrow the original SomeException:

//original, unmodifiable 3rdParty code, here as a example
public String getAnswer() {
    try {
        //some code
        throw new SomeException("a message");
    } catch (final SomeException e) {
        return null;
    }
}

//a wrapper to getAnswer to unwrapp the `SomeException`
public String getAnswerWrapped() throws SomeException {
    try {
        return getAnswer();
    } catch (final SomeExceptionWrapperException e) {
        throw (SomeException) e.getCause();
    }
}

@Test(expected = SomeException.class)
public void testThrow() throws SomeException {
    final String t = getAnswerWrapped();
}

The test will be green as the original SomeException, will be thrown.

Limitations:

This solution will not work if either :

  • if SomeException is in java.lang as you cannot replace java.lang classes (or see Replacing java class?)
  • if the 3rd party method has a catch(Throwable e) (which will be horrible and should motivate you to ignore the full 3rd party library)
like image 106
Benoît Avatar answered Oct 12 '22 23:10

Benoît


To solve this based on your constraints I would use aspects (something like AspectJ) and attach it to the creation of your exception, logging (or having it call some arbitrary) method then.

http://www.ibm.com/developerworks/library/j-aspectj/

like image 33
Nathan Dunn Avatar answered Oct 12 '22 23:10

Nathan Dunn