web-dev-qa-db-fra.com

Spring RestTemplate - Remplacement de ResponseErrorHandler

J'appelle un service ReST via RestTemplate et j'essaie de remplacer ResponseErrorHandler dans Spring 3.2 pour gérer les codes d'erreur personnalisés.

CustomResponseErrroHandler

public class MyResponseErrorHandler implements ResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        boolean hasError = false;
        int rawStatusCode = response.getRawStatusCode();
        if (rawStatusCode != 200){
            hasError = true;
        }
        return hasError;
     }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        //String body = IOUtils.toString(response.getBody());
        throw new CustomServiceException(response.getRawStatusCode() , "custom Error");
   }
}

Spring framework invoque la méthode hasError mais pas handleError, donc je ne pouvais pas lever mon exception personnalisée. Après avoir exploré le code source de SpringRestTemplate, je me suis rendu compte que le code de la méthode handleResponseError est à l'origine du problème - Il recherche response.getStatusCode ou response.getStatusText et lançant une exception (comme statusCode/statusText est nul lorsque Rest le service lève une exception) et il n'appelle jamais la méthode implémentée personnalisée ou la méthode par défaut handleError dans la ligne suivante.

SpringRestTemplate code source de la méthode handleResponse:

private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException {
    if (logger.isWarnEnabled()) {
        try {
            logger.warn(method.name() + " request for \"" + url + "\" resulted in " +
response.getStatusCode() + " (" + response.getStatusText() + "); invoking error handler");
        }
        catch (IOException e) {
            // ignore
        }
    }
    getErrorHandler().handleError(response);
}

Pour info, alors que le service lève une exception, je peux lire le rawstatuscode mais pas le statuscode de la réponse

Comment contourner ce code framework et faire appeler mon gestionnaire personnalisé? Merci d'avance pour votre aide.

11
user3670450

Le lien suivant contient des informations utiles sur Flux d'exceptions pour Spring ResponseErrorHandler .

Ajout de code ici, juste au cas où le blog serait en panne:

Code pour ErrorHandler:

public class MyResponseErrorHandler implements ResponseErrorHandler {

    private static final Log logger = LogFactory.getLog(MyResponseErrorHandler.class);

    @Override
    public void handleError(ClientHttpResponse clienthttpresponse) throws IOException {

        if (clienthttpresponse.getStatusCode() == HttpStatus.FORBIDDEN) {
            logger.debug(HttpStatus.FORBIDDEN + " response. Throwing authentication exception");
            throw new AuthenticationException();
        }
    }

    @Override
    public boolean hasError(ClientHttpResponse clienthttpresponse) throws IOException {

        if (clienthttpresponse.getStatusCode() != HttpStatus.OK) {
            logger.debug("Status code: " + clienthttpresponse.getStatusCode());
            logger.debug("Response" + clienthttpresponse.getStatusText());
            logger.debug(clienthttpresponse.getBody());

            if (clienthttpresponse.getStatusCode() == HttpStatus.FORBIDDEN) {
                logger.debug("Call returned a error 403 forbidden resposne ");
                return true;
            }
        }
        return false;
    }
}

Code pour l'utiliser dans RestTemplate:

RestTemplate restclient = new RestTemplate();
restclient.setErrorHandler(new MyResponseErrorHandler());
ResponseEntity<String> responseEntity = clientRestTemplate.exchange(
                    URI,
                    HttpMethod.GET,
                    requestEntity,
                    String.class);
                response = responseEntity.getBody();
16
Abhijeet

Je ne vois pas votre code RestTemplate, mais je suppose que vous définissez votre ResponseErrorHandler pour RestTemplate à utiliser comme:

RestTemplate restClient = new RestTemplate();
restClient.setErrorHandler(new MyResponseErrorHandler());

L'exception est en effet levée dans la méthode handleError. Vous pouvez trouver comment lancer CustomException en utilisant CustomResponseHandler à partir de ne de mes réponses précédentes .

2
nilesh