I am trying to catch a specific runtime exception (so not throwable) and just log it (log.error has a void return type). What is the simplest way to do this vavr?
```
try {
sayHello();
} catch (MyAppRuntimeException ex) {
log.error("Error occured"); // log.error returns void not Void so I couldn't find a suitable method in Vavr library
}
I have tried
Try.run(() -> sayHello())
.recover(MyAppRuntimeException.class, ex->log.error(Error occured: {}, ex.getMessage()));
```
I get Bad return type void cannot be converted to Void
In your case the second parameter of Try::recover call is Function<MyAppRuntimeException, Void>. Try this:
Try.run(() -> sayHello())
.recover(MyAppRuntimeException.class, ex -> {
System.out.println(ex.getMessage());
return null;
});
@ruslansennov Sure, but is there any cleaner way? else I had to return null for lot of my log statements. I have also looked into the .onFailure method and it looks like it is going to catch throwable in which case it will catch all exceptions and errors but I only want to catch one exception which is MyAppRuntimeException. And if there are other RuntimeExceptions that occur then I want them to be thrown as any other java program does but not go silent by catching Throwable.
the only value that can exist for Void is null. there is way to instantiate Void.
there could be an overload that accept a Consumer<E>, and handles this interally.
@hamnis Consumer<E> This is all we are looking for
@kant111 and @hamnis this is idiosyncratic Java. In functional parlance, it isn't a function if it doesn't return anything. In Java, that's ok. It's a consumer
Well. because of the Java typesystem this is not really correct. Since we cannot infer the inner type the Try is supposed to have, it will have to be a new method not an overload. Changing the return type to Try<Void> is probably not what you expected.
static <X extends Throwable> Try<Void> recoverUnit(Try<Void> tried, Class<X> exception, Consumer<? super X> f) {
return tried.recover(exception, ex -> {
f.accept(ex);
return null;
});
}
I know, this is really a pain in the ass in Java but adding overloads (and primitive specializations in general) isn't a viable solution for us.
With primitive generics all will be fine (fingers crossed).
@danieldietrich Can you describe why it isn't a viable solution ?
@kant111, @hamnis
Can you describe why it isn't a viable solution ?
Maybe I was too fast closing the issue. I don't like to add special cases for void or primitive types. It will blow up the API unnecessarily. Especially it seems odd to _recover_ literally _nothing_.
What do you all think about the following?
default <X extends Throwable> Try<T> onFailure(Class<X> exception, Consumer<? super X> action) {
Objects.requireNonNull(exception, "exception is null");
Objects.requireNonNull(action, "action is null");
if (isFailure() && exception.isAssignableFrom(getCause().getClass())) {
action.accept((X) getCause());
}
return this;
}
@danieldietrich That looks good to me (As long as we are not catching throwable's I think we are good) ! It might even solve https://github.com/vavr-io/vavr/issues/2137
Most helpful comment
@kant111, @hamnis
Maybe I was too fast closing the issue. I don't like to add special cases for
voidor primitive types. It will blow up the API unnecessarily. Especially it seems odd to _recover_ literally _nothing_.What do you all think about the following?