-1

I use webclient from weblux to send a request to a remote server. At this point, I can get error 400. I need to intercept it and send it to the client.

webClient
                        .post()
                        .uri(
                            
                        )
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                        .body(
                            BodyInserters
                                .fromFormData()
                                .with()
                                .with()
                
                        )
                        .retrieve()
                        .onStatus(
                            HttpStatus::isError, response -> response.bodyToMono(String.class) // error body as String or other class
                                .flatMap(error -> Mono.error(new WrongCredentialsException(error)))
                                )
                        .bodyToMono(TResponse.class)
                        .doOnNext(...);
  • error
@ControllerAdvice
@Slf4j
public class ApplicationErrorHandler {

  @ExceptionHandler(WrongCredentialsException.class)
    public ResponseEntity<ErrorResponse> handleResponseException(WrongCredentialsException ex) {
      //  log.error("Error from WebClient - Status {}, Body {}", ex.getRawStatusCode(), ex.getResponseBodyAsString(), ex);

      ErrorResponse error = new ErrorResponse();
      return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
          .body(error);
    }

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ErrorResponse {

    private String errorCode;

    private String message;
}

  • rest api

@PostMapping

  public ResponseEntity<String> send(@RequestBody Dto dto) {

        log.debug("An notification has been send to user");

        return new ResponseEntity<>(HttpStatus.OK);
    }

I tried the options from here, but it didn't work out . Can someone explain how it works and how it can be configured for my case?

skyho
  • 1,438
  • 2
  • 20
  • 47

1 Answers1

1
  • first case
return Objects.requireNonNull(oauthWebClient
                .post()
                .uri(uri)
                .bodyValue(dto)
                .attributes(oauth2AuthorizedClient(authorizedClient))
                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .exchangeToMono(response -> {

                    HttpStatus httpStatus = response.statusCode();

                    if (httpStatus.is4xxClientError()) {
                        getErrFromClient(response, httpStatus);
                    }

                    if (httpStatus.is5xxServerError()) {
                        getErrFromServer(response, httpStatus);
                    }

                    return Mono.just(ResponseEntity.status(response.statusCode()));
                })
                .block())
                .build();
    }

    private void getErrFromServer(DtoResponse response, HttpStatus httpStatus) {

        String err = response.bodyToMono(String.class).toString();
        log.error("HttpStatus: {}, message: {}", httpStatus, err);

        HttpHeaders httpHeaders = response.headers().asHttpHeaders();

        List<String> errorBody = httpHeaders.get("errBody");

        assert errBody != null;
        throw new CustomException(
                "{ HttpStatus : " + httpStatus + " , message : " + errBody + " }");
    }

    private void getErrFromClient(DtoResponse response, HttpStatus httpStatus) {

        String err = response.bodyToMono(String.class).toString();

        log.error("HttpStatus: {}, err: {}", httpStatus, err);

        HttpHeaders httpHeaders = response.headers().asHttpHeaders();
        List<String> errorBody = httpHeaders.get("errBody");

        assert errBody != null;
        throw new CustomException(
                "{ HttpStatus : " + httpStatus + " , message : " + errBody + " }");
    }

  • and than
@ControllerAdvice
public class HandlerAdviceException {

    @ExceptionHandler(CustomException.class)
    public ResponseEntity<ErrorResponse> handleCustomException(CustomException e) {

//here your code
//for example:

        String errMessage = e.getLocalizedMessage();

        return ResponseEntity
                .internalServerError()
                .body(new ErrorResponse(ErrorCode.INTERNAL_ERROR, errMessage));
    }

}

  • second case
          return webClient
            .post()
            .uri(
              properties......,
              Map.of("your-key", properties.get...())
            )
            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .body(
              prepare....()
            )
            .retrieve()
            .bodyToMono(TokenResponse.class)
            .doOnSuccess(currentToken::set);
        }

Here, if successful, you will get the result you need, but if an error occurs, then you only need to configure the interceptor in the Advice Controller for WebClientResponseException.

@ControllerAdvice
@Slf4j
public class CommonRestExceptionHandler extends ResponseEntityExceptionHandler {

  @ExceptionHandler(WebClientResponseException.class)
  protected ResponseEntity<ApiErrorResponse> handleWebClientResponseException(WebClientResponseException ex) {

    log.error(ex.getClass().getCanonicalName());

    String errMessageAdditional = .....

    final ApiErrorResponse apiError = ApiErrorResponse.builder()
      .message(ex.getLocalizedMessage())
      .status(HttpStatus.UNAUTHORIZED)
      .build();
//if it needs
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.add(.......);

    return new ResponseEntity<>(apiError, httpHeaders,  apiError.getStatus());
  }
}
skyho
  • 1,438
  • 2
  • 20
  • 47