Spring WebFlux WebClient, RestTemplate получает сообщение об исключении от ClientResponse при ошибке - PullRequest
0 голосов
/ 06 августа 2020

У меня есть служба отдыха в аннотированном классе RestController.

@ResponseStatus(HttpStatus.NO_CONTENT)
@PostMapping(path = SUBMIT_OPENFORM_PATH, consumes = APPLICATION_JSON_VALUE)
public Mono<Void> submitForm(@RequestBody Form form) {
    return service.submitForm(form);
}

и GlobalExceptionHandler задают настраиваемое сообщение в EntityResponse при возникновении ошибки:

@ExceptionHandler(ResourceNotFoundException.class)
private ResponseEntity<Error> handleResourceNotFoundException(ResourceNotFoundException e) {
    log.warn("Unknown resource: {}", e.getMessage());
    return ErrorResponseEntity.fromError(
            ResourceNotFound.builder()
                    .errorReason(e.getMessage())
                    .build()
    );
}

Затем У меня есть такой метод как у клиента этой службы. Я могу использовать RestTemplate или WebClient для вызова службы:

public void proxyOpenformSubmission(String payload) throws Exception {
    try {
       callFormSubmitWithWebClient(payload, token);
    } catch (Exception e) {
        throw(e);
    }
}

Мне нужно получить точное сообщение об исключении, установленное в ExceptionHandler, при ответе или что-то еще при возникновении ошибки. Я получаю код HttpStatus, но мне также нужно получить настраиваемое сообщение об ошибке. Я проверял ClientResponse, сообщения не оказалось. Что я делаю не так? Я пытаюсь установить фильтр в WebClient, чтобы получить ответ и создать собственное исключение на основе ответа:

private void callOpenformSubmitWithWebClient(String formPayload, String token) throws Exception {
    WebClient webClient = WebClient.builder()
    .baseUrl(submitFormUri)
    .defaultHeader(HttpHeaders.CONTENT_TYPE, "application/json")
    .filter(errorHandlingFilter())
    .build();       

    webClient.post()
    .accept(MediaType.APPLICATION_JSON)
    .body(BodyInserters.fromValue(formPayload))
    .headers(headers -> headers.setBearerAuth(token))
    .retrieve()
    .bodyToMono(String.class)
    .block();       
}

Фильтр:

public static ExchangeFilterFunction errorHandlingFilter() {
    return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
        if(clientResponse.statusCode() != null && (clientResponse.statusCode().is5xxServerError() || clientResponse.statusCode().is4xxClientError()) ) {
            //return clientResponse.createException().flatMap( Mono::error );
                        
            return clientResponse.bodyToMono(String.class)
                    .flatMap(errorBody -> Mono.error(new CustomWebClientResponseException(errorBody , clientResponse.statusCode())));

         
        } else {
            
            return Mono.just(clientResponse);
        }
    });
}

Это работает с WebClient, но если Я пытаюсь вызвать это с помощью RestTemplate, тип содержимого в заголовках ответа равен 0, и поэтому тело будет нулевым. Единственное, что я бы увидел, используя RestTemplate вместо WebClient, - это HttpStatus code 400 и его фразу, но не мое собственное сообщение. Неважно, использую ли я postForEntity, exchange ... Он всегда возвращает размер содержимого 0 с RestTemplate.

...