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;
}