I am using a third party REST API in which every single API call is defined as throws IOException. I am wrapping the REST API in a Repository-style class. However, given the API interface, I am forced to either declare every method in my repository as throws IOException, or wrap every single call and rethrow it as a runtime exception.
Is there any clean way of wrapping the entire API to catch/rethrow as my own custom RuntimeException instead? I know I can wrap the calls using AspectJ and intercept the IOException, but my signature for the method won't change.
Are there any tricks I can use to convert an Exception to a RuntimeException?
For example:
APIWrapper interface has method:
public String getAppBuilds(String report_changed_since, String only_latest, String include_in_progress) throws IOException
In my repo, I would like to be able to call APIWrapper.getAppBuilds() without needing to catch the IOException.
The only possibility is to catch the Exception and convert it to a RuntimeException exactly as library like SpringJDBC do.
Basically something like that
public class OriginalLibrary {
public void method1() throws IOException {
...
}
}
public class LibraryWithoutException {
private OriginalLibrary original;
public LibraryWithoutException(OriginalLibrary original) {
this.original = original;
}
public void method1() {
try {
original.method1();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}
Note: it will be better to create a custom RuntimeException instead of using the standard class.
Or with your api:
public class APIWrapperNoException {
private APIWrapper api;
public APIWrapperNoException(APIWrapper api) {
this.api = api;
}
public String getAppBuilds(String report_changed_since,
String only_latest,
String include_in_progress) {
try {
return api.getAppBuilds(report_changed_since,
only_latest, include_in_progress);
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}
You could use project Lombok #SneakyThrows annotation (see here). This annotation allows you to hide throws in the signature at compile time.
Related
Consider the following java code:
public void write(FrameConsumer fc) throws FFmpegFrameRecorder.Exception{
frameStream.forEach(n -> fc.consume(n));
}
In this case "frameStream" is a Stream of Objects that can be passed to the "consume" method, and fc is a class containing the "consume" method. Another important note is that the "consume" method throws a "FFmpegFrameRecorder.Exception", which I would like to pass on to whatever method calls "write" in the future.
However the above code does not compile, because: "Unhandled exception type FFmpegFrameRecorder.Exception Java(16777384)". Why is that?
Best regards,
CCI
EDIT:
Puting a try_catch block inside the lambda expression does not solve the problem either, hence:
public void write(FrameConsumer fc) throws FFmpegFrameRecorder.Exception{
frameStream.forEach(n -> {
try {
fc.consume(n);
} catch (FFmpegFrameRecorder.Exception e) {
throw e; //**this part does not compile**
}
});
}
(As provided by #Soumya Manna) does not compile either. The compiler still wants for the program to handle the "FFmpegFrameRecorder.Exception e" as it is thrown.
You cannot do this in lambda. You may simple write for loop and throw it or use try-catch block in lambda and throw Runtime exception there.
You could wrap the exception in a RuntimeException and then unwrap it:
public class ExceptionWrapper extends RuntimeException {
public ExceptionWrapper(Throwable cause) {
super(cause);
}
}
// ...
public void write(FrameConsumer fc) throws FFmpegFrameRecorder.Exception {
try {
frameStream.forEach(n -> {
try {
fc.consume(n));
} catch(FFmpegFrameRecorder.Exception e) {
throw new ExceptionWrapper(e);
}
});
} catch(ExceptionWrapper e) {
throw (FFmpegFrameRecorder.Exception) e.getCause();
}
}
The reason the lambda can't throw a checked exception is that java.lang.Stream#forEach's parameter (action) is of type java.util.function.Consumer, whose only non-default method, accept, does not declare any exceptions.
See also: https://docs.oracle.com/javase/tutorial/essential/exceptions/catchOrDeclare.html
I always tested my exceptions with annotations.
#Test (expected = Exception.class)
public void test1() {
methodToTest() // throws an exception
}
I finally switched to Java 8, and I came across lambda Expressions. Now there is another option to get the desired result.
#Test
public void test2() {
assertThrows(Exception.class, () -> methodToTest());
}
public static <X extends Throwable> Throwable assertThrows(
final Class<X> exceptionClass, final Runnable block) {
try {
block.run();
} catch(Throwable ex) {
if (exceptionClass.isInstance(ex))
return ex;
}
fail("Failed to throw expected exception");
return null;
}
I understand that with the second version you can check for single methods more precisely, and you don't have to worry about other methods within a single test that could throw the expected exception as well. Furthermore, with an "assertThrows" method, all tests can have the same structure, because it all comes down to a call for an assertion.
Besides those two points, are there any pro arguments for the new way? For me, it feels like its still superior to go with the annotations, as long as I am only testing a single method within a single test.
You missed a third way, the ExpectedException jUnit rule:
public class SimpleExpectedExceptionTest {
#Rule
public ExpectedException thrown= ExpectedException.none();
#Test
public void myMethod_throws_no_exception_when_passed_greeting() {
fixture.myMethod("hello");
}
#Test
public void myMethod_throws_MyException_when_passed_farewell() {
thrown.expect(MyException.class);
fixture.myMethod("goodbye");
}
}
I find this clearer than the #Test (expected = ...) version, since the expectation goes closer to the method call.
There is also the plain old Java version, which we used to make do with:
try {
fixture.myMethod("should throw");
fail("Expected an exception");
} catch (MyException e) {
// expected
}
Which of the many is "better" depends entirely on context. Don't adopt one universally. Pick the one that gives you the clearest test in a given situation.
When you begin coding non-test code in a lambda-centric style, it is likely that you'll find yourself wanting to use the lambda-centric assertThrows().
If all you want to test is that an exception is thrown, the first syntax is better. It is standard, it is concise, and it prevents you from writing the same ugly try-catch over and over.
You could have a test slightly more complicated where you want to assert that an exception is thrown and some method is not called. In this case, manually catching the exception is reasonable.
#Test
public void test1() {
DBClient dbClient = spy(new DBClient());
try {
new Server().doRequest(new InvalidRequest(), dbClient);
fail("should have thrown");
} catch (InvalidRequestException e) {
verify(dbClient, times(0)).query(any(Query.class));
}
}
Regarding the use on lambdas more specifically, it's up to you. Just note that Runnable cannot throw checked exceptions so you would need something like
#FunctionalInterface
public interface ThrowingRunnable<E extends Exception> {
void run() throws E;
}
I don't see a problem with either approach--there is no right or wrong in matters of style; just use the one that best suits each situation. I suggest that assertThrows should also check for thrown exceptions that aren't of the expected type, and, as #Dici suggests, that a functional interface that allows checked exceptions be used:
public static <X extends Throwable> Throwable assertThrows(
final Class<X> exceptionClass, final CheckedRunnable block) {
try {
block.run();
} catch(Throwable ex) {
if (exceptionClass.isInstance(ex)) {
return ex;
} else {
throw new AssertionError("Unexpected exception was thrown", ex);
}
}
fail("Failed to throw expected exception");
}
#FunctionalInterface
public interface CheckedRunnable<R extends RuntimeException> {
void run () throws Exception;
}
Suppose I have a class and a method
class A {
void foo() throws Exception() {
...
}
}
Now I would like to call foo for each instance of A delivered by a stream like:
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
Question: How do I properly handle the exception? The code does not compile on my machine because I do not handle the possible exceptions that can be thrown by foo(). The throws Exception of bar seems to be useless here. Why is that?
You need to wrap your method call into another one, where you do not throw checked exceptions. You can still throw anything that is a subclass of RuntimeException.
A normal wrapping idiom is something like:
private void safeFoo(final A a) {
try {
a.foo();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
(Supertype exception Exception is only used as example, never try to catch it yourself)
Then you can call it with: as.forEach(this::safeFoo).
If all you want is to invoke foo, and you prefer to propagate the exception as is (without wrapping), you can also just use Java's for loop instead (after turning the Stream into an Iterable with some trickery):
for (A a : (Iterable<A>) as::iterator) {
a.foo();
}
This is, at least, what I do in my JUnit tests, where I don't want to go through the trouble of wrapping my checked exceptions (and in fact prefer my tests to throw the unwrapped original ones)
This question may be a little old, but because I think the "right" answer here is only one way which can lead to some issues hidden Issues later in your code. Even if there is a little Controversy, Checked Exceptions exist for a reason.
The most elegant way in my opinion can you find was given by Misha here Aggregate runtime exceptions in Java 8 streams
by just performing the actions in "futures". So you can run all the working parts and collect not working Exceptions as a single one. Otherwise you could collect them all in a List and process them later.
A similar approach comes from Benji Weber. He suggests to create an own type to collect working and not working parts.
Depending on what you really want to achieve a simple mapping between the input values and Output Values occurred Exceptions may also work for you.
If you don't like any of these ways consider using (depending on the Original Exception) at least an own exception.
You might want to do one of the following:
propagate checked exception,
wrap it and propagate unchecked exception, or
catch the exception and stop propagation.
Several libraries let you do that easily. Example below is written using my NoException library.
// Propagate checked exception
as.forEach(Exceptions.sneak().consumer(A::foo));
// Wrap and propagate unchecked exception
as.forEach(Exceptions.wrap().consumer(A::foo));
as.forEach(Exceptions.wrap(MyUncheckedException::new).consumer(A::foo));
// Catch the exception and stop propagation (using logging handler for example)
as.forEach(Exceptions.log().consumer(Exceptions.sneak().consumer(A::foo)));
I suggest to use Google Guava Throwables class
propagate(Throwable throwable)
Propagates throwable as-is if it is an
instance of RuntimeException or Error, or else as a last resort, wraps
it in a RuntimeException and then propagates.**
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
throw Throwables.propagate(e);
}
});
}
UPDATE:
Now that it is deprecated use:
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
});
}
You can wrap and unwrap exceptions this way.
class A {
void foo() throws Exception {
throw new Exception();
}
};
interface Task {
void run() throws Exception;
}
static class TaskException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TaskException(Exception e) {
super(e);
}
}
void bar() throws Exception {
Stream<A> as = Stream.generate(()->new A());
try {
as.forEach(a -> wrapException(() -> a.foo())); // or a::foo instead of () -> a.foo()
} catch (TaskException e) {
throw (Exception)e.getCause();
}
}
static void wrapException(Task task) {
try {
task.run();
} catch (Exception e) {
throw new TaskException(e);
}
}
More readable way:
class A {
void foo() throws MyException() {
...
}
}
Just hide it in a RuntimeException to get it past forEach()
void bar() throws MyException {
Stream<A> as = ...
try {
as.forEach(a -> {
try {
a.foo();
} catch(MyException e) {
throw new RuntimeException(e);
}
});
} catch(RuntimeException e) {
throw (MyException) e.getCause();
}
}
Although at this point I won't hold against someone if they say skip the streams and go with a for loop, unless:
you're not creating your stream using Collection.stream(), i.e. not straight forward translation to a for loop.
you're trying to use parallelstream()
A method returns some result, making a number of "attempts" to build it. The first attempt that succeeds should return. If none of them succeed an exception should be thrown:
class Calculator {
public String calculate() throws Exception {
// how do design it?
}
private String attempt1() throws Exception {
// try to calculate and throw if fails
}
private String attempt2() throws Exception {
// try to calculate and throw if fails
}
private String attempt3() throws Exception {
// try to calculate and throw if fails
}
}
It's important to mention that the exception thrown by calculate should preserve stack traces of all other exceptions thrown by private methods. How would you recommend to design calculate() method, with extendability and maintainability in mind?
I would use Composite and Command.
interface CalculateCommand {
public void calculate(CalculateContext context);
}
Now create an implementation for each attempt you want.
Next create a CompositeCommand -- here is an outline (you will need to fill in the blanks)
public class CompositeCalculateCommand implements CalculateCommand {
CompositeCalculateCommand(List<CompositeCommand> commands) {
this.commands = commands; // define this as a field
}
public void calculate(CommandContext context) {
for (CalculateCommand command : commands) {
try {
command.calculate(context);
} catch(RuntimeException e) {
this.exceptions.add(e) // initialize a list to hold exceptions
}
if (context.hasResult) return; // break
}
// throw here. You didn't success since you never saw a success in your context. You have a list of all exceptions.
}
}
finally use it like
CalculateCommand allCommands = new CompositeCalculateCommand(someListOfCommands);
allCommands.calculate(someContextThatYouDefine);
// results now on context.
Note each command implementation is testable on its own, so this is very maintainable. If you need to add calculations, you simply define a new type of CalculateCommand, so this is extensible. It will also play well with dependency injection. Note I define a CommandContext object so different commands can take different types of stuff (put in a context).
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")'
}
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.
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".
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);
}