Home > Back-end >  How to handle exceptions with Optional.orElseGet() properly
How to handle exceptions with Optional.orElseGet() properly

Time:09-18

I want to call an endpoint which takes a string as a parameter and returns some status, but the thing is, sometimes I need to call this endpoint a second time if the first call with the the initial param fails.

I.e. service A calls service B with returnId="123", but service B returns 404, then I want to call service B again with id="abc". (this way it is guaranteed I will have some status.)

I was wondering if I can do this with Optionals and not with a lot of try/catch and if/else blocks.

Here is what I have:

private String fetchStatus(Order order) {
    var status = Optional.ofNullable(order.getReturnId())
        .map(returnId -> getStatus(order.returnId))
        .orElseGet(() -> getStatus(order.getId()));

    log.info("Current status: {}", status);
    return status;
}

private String getStatus(String id) {
    try {
        return externalService.getOrderStatus(id);
    } catch (Exception e) {
        throw new IllegalStateException("Failed to fetch status for order.", e);
    }
}

The problem with the above code is that if the service B (externalService) returns a 404 not found, my code never tries to call the alternative (orElseGet).

What is that I am getting wrong and not understanding properly?

CodePudding user response:

Return null instead of throwing exception so your Optional.ofNullabe will kick in.

private String getStatus(String id) {
    try {
        return externalService.getOrderStatus(id);
    } catch (Exception e) {
        //log something so you knwo what happened
        return null;
    }

If that is a good approach in general, is another story.

CodePudding user response:

Another approach would be to have externalService#getOrderStatus(...) return an Optional<String> instead of throwing an exception, which would make #fetchStatus(...) look like the following:

private String fetchStatus(Order order) {
    var status = Optional.ofNullable(order.getReturnId())
        .flatMap(externalService::getOrderStatus)
        .or(() -> externalService.getOrderStatus(order.getId()))
        .orElseThrow(() -> new IllegalStateException("should not happen according to your question"));
    log.info("Current status: {}", status);
    return status;
}
  • Related