Question

Is there a way to annotate a method so all exceptions thrown are converted to runtime exception automagically?

@MagicAnnotation
// no throws clause!
void foo()
{
  throw new Exception("bar")'
}
Was it helpful?

Solution

No way to do that, at least for now I use workaround like this (simplified):

@SuppressWarnings({"rawtypes", "unchecked"})
public class Unchecked {
    public static interface UncheckedDefinitions{
        InputStream openStream();
        String readLine();
            ...
    }

  private static Class proxyClass = Proxy.getProxyClass(Unchecked.class.getClassLoader(), UncheckedDefinitions.class);

    public static UncheckedDefinitions unchecked(final Object target){
        try{
            return (UncheckedDefinitions) proxyClass.getConstructor(InvocationHandler.class).newInstance(new InvocationHandler(){
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if (target instanceof Class){
                        return MethodUtils.invokeExactStaticMethod((Class) target, method.getName(), args);
                    }

                  return MethodUtils.invokeExactMethod(target, method.getName(), args);
                }
            });
        }
        catch(Exception e){
            throw new RuntimeException(e);
        }
    }
}

And the usage looks like:

import static ....Unchecked.*;

...

Writer w = ...;
unchecked(w).write(str, off, len);

The trick is that interface is "never finished" and everytime I need unchecked method somewhere, I'll wrap that object into unchecked and let IDE generate method signature in interface.

Implementation is then generic (reflective and "slow" but usually fast enough)

There are some code post-processors and bytecode-weavers but this was not possible (not even aop or other jvm based language) for my current project, so this was "invented".

OTHER TIPS

Project Lombok's @SneakyThrows is probably what you are looking for. Is not really wrapping your exception (because it can be a problem in a lot of cases), it just doesn't throw an error during compilation.

@SneakyThrows
void foo() {
    throw new Exception("bar")'
}

You can do this with AspectJ. You declare a joinpoint (in this case invocation of the method foo) and 'soften' the exception.

Edit To elaborate a bit on this:

Say you have the following class Bar:

public class Bar {

    public void foo() throws Exception {
    }
}

...and you have a test like this:

import junit.framework.TestCase;

public class BarTest extends TestCase {

    public void testTestFoo() {
        new Bar().foo();
    }
}

Then obviously the test is not going to compile. It will give an error:

Unhandled exception type Exception  BarTest.java(line 6)

Now to overcome this with AspectJ, you write a very simple aspect:

public aspect SoftenExceptionsInTestCode {

    pointcut inTestCode() : execution(void *Test.test*());

    declare soft : Exception : inTestCode();
}

The aspect basically says that any code from within a Test (i.e.: a method that starts with "test" in a class that ends in "Test" and returns 'void') that throws an exception should be accepted by the AspectJ compiler. If an exception occurs, it will be wrapped and thrown as a RuntimeException by the AspectJ compiler.

Indeed, if you run this test as part of an AspectJ project from within Eclipse (with AJDT installed) then the test will succeed, whereas without the aspect it won't even compile.

I think it is possible with bytecode re-engineering, customized compiler or perhaps aspect oriented programming1. In the contrary to Java, C# has only unchecked exceptions2.

May I ask why you want to suppress the checked exceptions?

1 according to Maarten Winkels this is possible.
2 and they are thinking about introducing checked ones, according to some Channel 9 videos.

Edit: For the question: It is possible in the sense that you can annotate your methods to flag them to be a candidate for checked exception suppression. Then you use some compile time or runtime trick to apply the actual suppression / wrapping.

However, as I don't see the environment around your case, wrapping an exception in these ways might confuse the clients of that method - they might not be prepared to deal with a RuntimeException. For example: the method throws an IOException and your clients catches it as FileNotFoundException to display an error dialog. However if you wrap your exception into a RuntimeException, the error dialog gets never shown and probably it kills the caller thread too. (IMHO).

The Checked exceptions are responsability of the method implementation. Take very very carefully this fact. if you can do not use workaround artifacts like that.

You can do this in any case via use of the fact that Class.newInstance does not wrap an Exception thrown by the no-arg constructor in an InvocationTargetException; rather it throws it silently:

class ExUtil {
  public static void throwSilent(Exception e) { //NOTICE NO THROWS CLAUSE
      tl.set(e);
      SilentThrower.class.newInstance(); //throws silently
  }

  private static ThreadLocal<Exception> tl = new ThreadLocal<Exception>();
  private static class SilentThrower {
      SilentThrower() throws Exception {
          Exception e = tl.get();
          tl.remove();
          throw e;
      }
  }
}

Then you can use this utility anywhere:

ExUtil.throwSilent(new Exception());
//or
try {
  ioMethod();
} catch (IOException e) { ExUtil.throwSilent(e); }

By the way, this is a really bad idea :-)

I use the completion / template system of Eclipse to wrap any block of code easily.

Here is my template :

try { // Wrapp exceptions

${line_selection}${cursor}

} catch (RuntimeException e) { // Forward runtime exception
throw e;
} catch (Exception e) { // Wrap into runtime exception
throw new RuntimeException(
    "Exception wrapped in #${enclosing_method}", 
    e); 
}

With Java 8 it's as easy as: soften(() -> methodThatMayThrow())

Read more at http://iirekm.blogspot.com/2014/05/fix-problems-with-java-checked.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top