Manejo de excepción Spring Resttemplate

Debajo está el fragmento de código; básicamente, estoy tratando de propagar la excepción cuando el código de error no es 200.

ResponseEntity response = restTemplate.exchange(url.toString().replace("{version}", version), HttpMethod.POST, entity, Object.class); if(response.getStatusCode().value()!= 200){ logger.debug("Encountered Error while Calling API"); throw new ApplicationException(); } 

Sin embargo, en el caso de una respuesta de 500 del servidor, recibo la excepción

 org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 

¿Realmente necesito envolver el método de intercambio de plantillas de prueba? ¿Cuál sería entonces el propósito de los códigos?

Desea crear una clase que implemente ResponseErrorHandler y luego use una instancia de la misma para configurar el manejo de errores de su plantilla de reposo.

 public class MyErrorHandler implements ResponseErrorHandler { @Override public void handleError(ClientHttpResponse response) throws IOException { // your error handling here } @Override public boolean hasError(ClientHttpResponse response) throws IOException { ... } } [...] public static void main(String args[]) { RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(new MyErrorHandler()); } 

Además, Spring tiene la clase DefaultResponseErrorHandler , que puedes ampliar en lugar de implementar la interfaz, en caso de que solo quieras anular el método handleError .

 public class MyErrorHandler extends DefaultResponseErrorHandler { @Override public void handleError(ClientHttpResponse response) throws IOException { // your error handling here } } 

Eche un vistazo a su código fuente para tener una idea de cómo Spring maneja los errores de HTTP.

Debería detectar una excepción HttpStatusCodeException :

 try { restTemplate.exchange(...); } catch (HttpStatusCodeException exception) { int statusCode = exception.getStatusCode().value(); ... } 

Otra solución es la que se describe aquí al final de esta publicación por “enlian”: http://springinpractice.com/2013/10/07/handling-json-error-object-responses-with-springs-resttemplate

 try{ restTemplate.exchange(...) } catch(HttpStatusCodeException e){ String errorpayload = e.getResponseBodyAsString(); //do whatever you want } catch(RestClientException e){ //no response payload, tell the user sth else } 

Spring trata ingeniosamente los códigos de error http como excepciones, y asume que su código de manejo de excepciones tiene el contexto para manejar el error. Para que el intercambio funcione como lo esperaría, haga esto:

  try { return restTemplate.exchange(url, httpMethod, httpEntity, String.class); } catch(HttpStatusCodeException e) { return ResponseEntity.status(e.getRawStatusCode()).headers(e.getResponseHeaders()) .body(e.getResponseBodyAsString()); } 

Esto devolverá todos los resultados esperados de la respuesta.

Si utiliza el agrupamiento (fábrica de cliente http) o el mecanismo de equilibrio de carga (eureka) con su RestTemplate , no podrá RestTemplate el lujo de crear una new RestTemplate por clase. Si llama a más de un servicio, no puede usar setErrorHandler porque se usaría globalmente para todas sus solicitudes.

En este caso, capturar la HttpStatusCodeException parece ser la mejor opción.

La única otra opción que tiene es definir múltiples instancias de RestTemplate usando la anotación @Qualifier .

Además, pero este es mi gusto, me gusta el manejo de mis errores acurrucado a mis llamadas.

El código de cambio está abajo :

 public  ResponseEntity exchange(String url, HttpMethod method, HttpEntity< ?> requestEntity, Class responseType, Object... uriVariables) throws RestClientException 

La excepción RestClientException tiene excepciones HttpClientErrorException y HttpStatusCodeException .

Por lo tanto, en RestTemplete puede HttpStatusCodeException excepciones HttpClientErrorException y HttpStatusCodeException . En el objeto de excepción, puede obtener el mensaje de error exacto de esta manera: exception.getResponseBodyAsString()

Aquí está el código de ejemplo :

 public Object callToRestService(HttpMethod httpMethod, String url, Object requestObject, Class< ?> responseObject) { printLog( "Url : " + url); printLog( "callToRestService Request : " + new GsonBuilder().setPrettyPrinting().create().toJson(requestObject)); try { RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); restTemplate.getMessageConverters().add(new StringHttpMessageConverter()); HttpHeaders requestHeaders = new HttpHeaders(); requestHeaders.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity<>(requestObject, requestHeaders); long start = System.currentTimeMillis(); ResponseEntity< ?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject); printLog( "callToRestService Status : " + responseEntity.getStatusCodeValue()); printLog( "callToRestService Body : " + new GsonBuilder().setPrettyPrinting().create().toJson(responseEntity.getBody())); long elapsedTime = System.currentTimeMillis() - start; printLog( "callToRestService Execution time: " + elapsedTime + " Milliseconds)"); if (responseEntity.getStatusCodeValue() == 200 && responseEntity.getBody() != null) { return responseEntity.getBody(); } } catch (HttpClientErrorException exception) { printLog( "callToRestService Error :" + exception.getResponseBodyAsString()); //Handle exception here }catch (HttpStatusCodeException exception) { printLog( "callToRestService Error :" + exception.getResponseBodyAsString()); //Handle exception here } return null; } 

Aquí está la descripción del código :

En este método, debe pasar la clase de solicitud y respuesta. Este método analizará automáticamente la respuesta como objeto solicitado.

En primer lugar, debe agregar el convertidor de mensajes.

 restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); restTemplate.getMessageConverters().add(new StringHttpMessageConverter()); 

Luego debes agregar requestHeader . Aquí está el código:

 HttpHeaders requestHeaders = new HttpHeaders(); requestHeaders.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity<>(requestObject, requestHeaders); 

Finalmente, debes llamar al método de intercambio:

 ResponseEntity< ?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject); 

Para la impresión prety utilicé la biblioteca Gson. aquí está el gradle: compile 'com.google.code.gson:gson:2.4'

Simplemente puede llamar al código de abajo para obtener una respuesta:

 ResponseObject response=new RestExample().callToRestService(HttpMethod.POST,"URL_HERE",new RequestObject(),ResponseObject.class); 

Aquí está el código de trabajo completo :

 import com.google.gson.GsonBuilder; import org.springframework.http.*; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.RestTemplate; public class RestExample { public RestExample() { } public Object callToRestService(HttpMethod httpMethod, String url, Object requestObject, Class< ?> responseObject) { printLog( "Url : " + url); printLog( "callToRestService Request : " + new GsonBuilder().setPrettyPrinting().create().toJson(requestObject)); try { RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); restTemplate.getMessageConverters().add(new StringHttpMessageConverter()); HttpHeaders requestHeaders = new HttpHeaders(); requestHeaders.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity<>(requestObject, requestHeaders); long start = System.currentTimeMillis(); ResponseEntity< ?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject); printLog( "callToRestService Status : " + responseEntity.getStatusCodeValue()); printLog( "callToRestService Body : " + new GsonBuilder().setPrettyPrinting().create().toJson(responseEntity.getBody())); long elapsedTime = System.currentTimeMillis() - start; printLog( "callToRestService Execution time: " + elapsedTime + " Milliseconds)"); if (responseEntity.getStatusCodeValue() == 200 && responseEntity.getBody() != null) { return responseEntity.getBody(); } } catch (HttpClientErrorException exception) { printLog( "callToRestService Error :" + exception.getResponseBodyAsString()); //Handle exception here }catch (HttpStatusCodeException exception) { printLog( "callToRestService Error :" + exception.getResponseBodyAsString()); //Handle exception here } return null; } private void printLog(String message){ System.out.println(message); } } 

Gracias 🙂

Aquí está mi método POST con HTTPS que devuelve un cuerpo de respuesta para cualquier tipo de respuestas malas.

 public String postHTTPSRequest(String url,String requestJson) { //SSL Context CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); //Initiate REST Template RestTemplate restTemplate = new RestTemplate(requestFactory); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); //Send the Request and get the response. HttpEntity entity = new HttpEntity(requestJson,headers); ResponseEntity response; String stringResponse = ""; try { response = restTemplate.postForEntity(url, entity, String.class); stringResponse = response.getBody(); } catch (HttpClientErrorException e) { stringResponse = e.getResponseBodyAsString(); } return stringResponse; }