Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throwing ResourceAccessException vs HttpClientErrorException for RestTemplate client in Spring

Using Spring 4.3.1 on Apache Tomcat 8.5, We have implemented a REST server that handles GET, POST & PUT requests. The POST request is handled in the form:

@POST
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Transactional
public Response postMethod(final MyDomain object) {
     domainHandler.createDomain(object);
     return Response.status(201).entity(object).build();
}

During handling POST request on the server side, the WebApplicationException is thrown, which is handled by:

@Provider
public class WebExceptionMapper implements ExceptionMapper<WebApplicationException> {
     @Override
     public Response toResponse(WebApplicationException exception) {
          int httpStatus = exception.getResponse().getStatus();
          ErrorMessage em = new WebErrorMessage(exception.getMessage());
          return Response.status(httpStatus).entity(em).build();
     }
}

On the client side:

response = rest.exchange(requestURL, method, requestEntity, MyDomain.class);

the ResourceAccessException is thrown:

2017-07-25 15:46:41,489 ERROR [com.my.code.web.presentation.ManagementController:63] (http-nio-8080-exec-7#34): Internal exception occured with cause:
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8080/": Server returned HTTP response code: 500 for URL: http://localhost:8080/; nested exception is java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:8080/
     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:633) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:498) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at com.my.code.web.integration.client.rest.FeedbackRestClient.callForApiCreateFeedback(FeedbackRestClient.java:218) ~[classes/:?]
     at com.my.code.web.integration.client.rest.FeedbackRestClient.pushFeedbackData(FeedbackRestClient.java:70) ~[classes/:?]
     at com.my.code.web.presentation.FeedbackController.feedback(FeedbackController.java:91) ~[classes/:?]
     at sun.reflect.GeneratedMethodAccessor72.invoke(Unknown Source) ~[?:?]
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_131]
     at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_131]
     at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114) ~[spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) [spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) [spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) [servlet-api.jar:?]
     at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [servlet-api.jar:?]
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [catalina.jar:8.5.16]
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:8.5.16]
     at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:8.5.16]
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:8.5.16]
     at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.5.16]
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:8.5.16]
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:8.5.16]
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [catalina.jar:8.5.16]
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [catalina.jar:8.5.16]
     at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [catalina.jar:8.5.16]
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [catalina.jar:8.5.16]
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [catalina.jar:8.5.16]
     at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624) [catalina.jar:8.5.16]
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [catalina.jar:8.5.16]
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [catalina.jar:8.5.16]
     at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-coyote.jar:8.5.16]
     at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-coyote.jar:8.5.16]
     at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-coyote.jar:8.5.16]
     at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-coyote.jar:8.5.16]
     at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-coyote.jar:8.5.16]
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_131]
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_131]
     at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.5.16]
     at java.lang.Thread.run(Thread.java:748) [?:1.8.0_131]
Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL: http://localhost:8080/
     at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1876) ~[?:1.8.0_131]
     at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474) ~[?:1.8.0_131]
     at org.springframework.http.client.SimpleClientHttpResponse.getBody(SimpleClientHttpResponse.java:85) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at com.my.code.web.integration.client.rest.BufferingClientHttpResponseWrapper.getBody(BufferingClientHttpResponseWrapper.java:46) ~[classes/:?]
     at com.my.code.web.integration.client.rest.LoggingRequestInterceptor.traceResponse(LoggingRequestInterceptor.java:66) ~[classes/:?]
     at com.my.code.web.integration.client.rest.LoggingRequestInterceptor.intercept(LoggingRequestInterceptor.java:34) ~[classes/:?]
     at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:85) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:69) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:619) ~[spring-web-4.3.1.RELEASE.jar:4.3.1.RELEASE]
     ... 47 more

Question:

Why the exception org.springframework.web.client.ResourceAccessException is thrown, but not org.springframework.web.client.HttpClientErrorException, what's happening for handling the GET request when WebApplicationException occurs?

The ResourceAccessException exception does not have methods that allow me to read the HTTP status, eg getRawStatusCode (), getResponseHeaders(), etc.

like image 892
Marcin Avatar asked Jul 25 '17 14:07

Marcin


People also ask

What exceptions can RestTemplate throw?

By default, the RestTemplate will throw one of these exceptions in the case of an HTTP error: HttpClientErrorException – in the case of HTTP status 4xx. HttpServerErrorException – in the case of HTTP status 5xx. UnknownHttpStatusCodeException – in the case of an unknown HTTP status.

What is HttpClientErrorException in Java?

Note: Remember HttpClientErrorException is thrown when a 4xx error is received. So if the request you send is wrong either setting header or sending wrong data, you could receive this exception.


1 Answers

Because it's wrapping an IOException, not looking at the actual response code.

The root cause appears to be because BufferingClientHttpResponseWrapper is trying to read a body without checking if there is one first.

like image 64
OrangeDog Avatar answered Oct 15 '22 09:10

OrangeDog