web-dev-qa-db-fra.com

RestTemplate - Gestion des en-têtes / corps de réponse dans les exceptions (RestClientException, HttpStatusCodeException)

Dans mon service Web reposant, en cas de mauvaise réponse (5xx) ou de codes de réponse 4xx, j'écris un en-tête personnalisé "x-app-err-id" dans la réponse.

Côté client, j'utilise la méthode d'échange de RestTemplate pour effectuer un appel au service Web RestFul. Tout va bien lorsque le code de réponse est 2xx.

ResponseEntity<Component> response = restTemplate.exchange(webSvcURL,
    HttpMethod.POST, 
    requestEntity,
    Component.class);

Mais s'il y a une exception (HttpStatusCodeException) car il s'agit d'une mauvaise requête (5xx) ou 4xx, dans le bloc catch de HttpStatusCodeException, j'obtiens une réponse (voir ci-dessus) comme nulle et donc je n'ai pas accès à mon en-tête personnalisé I défini dans mon service Web. Comment obtenir des en-têtes personnalisés à partir de la réponse en cas d'exceptions dans RestTemplate.

Une autre question est, je mets un objet d'erreur (json) dans le corps de réponse en cas d'erreur et je voudrais savoir comment accéder au corps de réponse ainsi en cas d'exceptions dans RestTemplate

28
Chandra

Je l'ai finalement fait en utilisant ResponseErrorHandler.

public class CustomResponseErrorHandler implements ResponseErrorHandler {

    private static ILogger logger = Logger.getLogger(CustomResponseErrorHandler.class);

    private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler();

    public void handleError(ClientHttpResponse response) throws IOException {

        List<String> customHeader = response.getHeaders().get("x-app-err-id");

        String svcErrorMessageID = "";
        if (customHeader != null) {
            svcErrorMessageID = customHeader.get(0);                
        }

        try {           

            errorHandler.handleError(response);

        } catch (RestClientException scx) {         

            throw new CustomException(scx.getMessage(), scx, svcErrorMessageID);
        }
    }

    public boolean hasError(ClientHttpResponse response) throws IOException {
        return errorHandler.hasError(response);
    }
}

Et puis utilisez ce gestionnaire de réponse personnalisé pour RestTemplate en configurant comme indiqué ci-dessous

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
   <property name="messageConverters">
       <list>
           <ref bean="jsonConverter" />
       </list>
   </property>    
   <property name="errorHandler" ref="customErrorHandler" />
</bean>

<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
   <property name="supportedMediaTypes" value="application/json" />
</bean>

<bean id="customErrorHandler " class="my.package.CustomResponseErrorHandler">
</bean>
31
Chandra

Vous ne devriez pas avoir à créer un gestionnaire d'erreurs personnalisé. Vous pouvez obtenir le corps et les en-têtes de l'exception HttpStatusCodeException qui est levée.

try {
    ResponseEntity<Component> response = restTemplate.exchange(webSvcURL,
        HttpMethod.POST, 
        requestEntity,
        Component.class);
} catch (HttpStatusCodeException e) {
    List<String> customHeader = e.getResponseHeaders().get("x-app-err-id");
    String svcErrorMessageID = "";
    if (customHeader != null) {
        svcErrorMessageID = customHeader.get(0);                
    }
    throw new CustomException(e.getMessage(), e, svcErrorMessageID);
    // You can get the body too but you will have to deserialize it yourself
    // e.getResponseBodyAsByteArray()
    // e.getResponseBodyAsString()
}
17
meustrus