简体   繁体   中英

How to throw custom exception from resilience4j TimeLimitter?

I am using resilience4j's TimeLimiter to control timeout requests for a RestTemplate call. I am throwing a custom exception if the response.getBody() is null but, resilience4j's always throwing exception provided in getorElseThrow. how can I throw a custom exception here?

Try.ofCallable(methodWhichThrowsCustomException).getOrElseThrow(throwable -> {throw new ApplicationException(HttpStatus.REQUEST_TIMEOUT,
                    ErrorConstant.ERROR_CODE_REQUEST_TIMEOUT, ErrorConstant.ERROR_MESSAGE_TIME_OUT);
        });
    }

Here i am trying throw the exception that the "methodWhichThrowsCustomException" throws, but i am not able to do that it only throws the exception the thrown here.

I don't know resilience4j but I'm pretty sure you are using getOrElseThrow wrong. The syntax you most likely want is this:

Try.ofCallable(methodWhichThrowsCustomException())
   .getOrElseThrow(throwable -> new ApplicationException(HttpStatus.REQUEST_TIMEOUT, ErrorConstant.ERROR_CODE_REQUEST_TIMEOUT, ErrorConstant.ERROR_MESSAGE_TIME_OUT));

Note that you don't need to throw inside getOrElseThrow , you only need to return the new exception to throw, Vavr will take care of throwing it.

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 ...; } { throw new ...; } is throwing a new Exception immediately instead of simply mapping it with { return new CustomException("Custom message", thrown); } { 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

  1. when exceeding the time-limit, Resilience4J throws a TimeoutException :

When a timeout occurs, it cancels the running Future before throwing a TimeoutException .

  1. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM