0

How do I propogate an exception thrown in a call to a downstream service to the caller method?

I have a service that calculates something and throws an exception in case of error:

{
  "timestamp": "2019-03-12T08:21:05.316+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "VAKUUTUSVUOSI.MAKSUEHTO is null or not numeric. Can't be added to due date.",
  "path": "/rules/yk32/deducePaymentDueDate"
}

But the calling service displays this exception:

{
    "timestamp": "2019-03-12T08:30:22.912+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "500 null",
    "path": "/calculation/annual/payment"
}

How do I get the caller method also to display the message that the service throws "/rules/yk32/deducePaymentDueDate" instead of "Internal Server Error"?

Calling method:

LocalDate paymentDueDate = ykServiceAdapter.yk32DeducePaymentDueDate(requestDTO);

Calling function in the ykServiceadapter:

public LocalDate yk32DeducePaymentDueDate(Yk32RequestDTO requestDTO) {
    ResponseEntity<LocalDate> re;
    HttpEntity<?> entity = new HttpEntity<>(requestDTO);
    try {
        re = getRestTemplate().exchange(
                buildServiceUrl(externalServiceConfig, RULE_YK32, DEDUCE_PAYMENT_DUEDATE),
                HttpMethod.POST, entity,
                new ParameterizedTypeReference<LocalDate>() {
                });
        return re.getBody();

    } catch (HttpClientErrorException ex) {
        if (HttpStatus.NOT_FOUND.equals(ex.getStatusCode())) {
            return null;
        } else {
            throw ex;
        }
    }
}
DaveyDaveDave
  • 9,821
  • 11
  • 64
  • 77
Jenny
  • 77
  • 1
  • 6

1 Answers1

1

You're working on two separate contexts, via HTTP.

What that means is the Exception generated by yk32DeducePaymentDueDate is transformed to an HTTP 500 response, which might mean the Exception message is used as response body.

Obviously, being that the original Exception gets lost during the HTTP call, RestTemplate is only able to create an HttpClientErrorException based on the HTTP status code

HttpClientErrorException.BadRequest
HttpClientErrorException.Conflict
HttpClientErrorException.Forbidden
HttpClientErrorException.Gone
HttpClientErrorException.MethodNotAllowed
HttpClientErrorException.NotAcceptable
HttpClientErrorException.NotFound
HttpClientErrorException.TooManyRequests
HttpClientErrorException.Unauthorized
HttpServerErrorException.InternalServerError
HttpServerErrorException.NotImplemented
...

In your case the instantiated Exception is

public static class InternalServerError extends HttpServerErrorException {
    InternalServerError(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
        super(HttpStatus.INTERNAL_SERVER_ERROR, statusText, headers, body, charset);
    }
}

Only the Exception message might be recovered, if it has been transmitted in the response body.

You might want to look into a custom ResponseErrorHandler, where you can inspect the full HTTP response and react accordingly.

LppEdd
  • 20,274
  • 11
  • 84
  • 139