Vavr's Try.of().getOrElseThrow()
See the blog Vavr One Log 03 - A Safe Try:
T getOrElseThrow(Supplier)
getOrElseThrow
expects an exception-supplier as argument. This may be a lambda, method-reference, or any functional.
Its purpose is to map the thrown exception to your instance of a custom Exception. For example:
Try.ofCallable(methodWhichThrowsCustomException)
.getOrElseThrow(throwable -> new CustomerException(
HttpStatus.REQUEST_TIMEOUT,
ErrorConstant.ERROR_CODE_REQUEST_TIMEOUT,
ErrorConstant.ERROR_MESSAGE_TIME_OUT,
throwable
))
}
Issue
Note: we use throwable -> new ..
inside parentheses, nothing more. The exception instance is just created (and returned implicitly), we do not throw it - we supply it to vavr which throws then.
You passed a consumer instead. The consuming lambda { throw new ...; }
is throwing a new Exception immediately instead of simply mapping it with { return new CustomException("Custom message", thrown); }
.
See also
Exceptions from TimeLimiter
throw the exception that the "methodWhichThrowsCustomException" throws
Assume you have a method:
public String sayHelloWorld(boolean shouldThrow) throws CustomException {
if (shouldThrow) throw new CustomException("Hello Exception");
return "Hello World!";
}
You pass this to the TimeLimiter
When it executes and it was not able to complete successfully within time,
it throws either of two exceptions
- when exceeding the time-limit, Resilience4J throws a
TimeoutException
:
When a timeout occurs, it cancels the running Future before throwing a TimeoutException
.
- for any other
ExecutionException
, like when your method throws a custom exception, it will find that cause and rethrow this exception. See TimeLimiterImpl
, catch-block, line 57.
Then you should be able to catch it:
try {
// The blocking variant which is basically future.get(timeoutDuration, MILLISECONDS)
String result = timeLimiter.executeFutureSupplier(
() -> CompletableFuture.supplyAsync(() -> sayHelloWorld(true)));
log.info(result);
} catch (Exception e) {
log.error(e); // or print to debug, handle, etc.
}
or using Vavr's Try:
String result = Try.of(() -> timeLimiter.executeFutureSupplier(
() -> CompletableFuture.supplyAsync(() -> sayHelloWorld(true))) // method forced to throw
).getOrElseThrow(throwable -> throwable); // will throw as is (without mapping to another exception)
log.info(result);
See also:
Implementing Timeouts with Resilience4j - Reflectoring