Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle empty response in Spring RestTemplate

My Authorization service returs a http 204 on success and a http 401 on failure but no responseBody. I'm not able to consume this with the RestTemplate client. It fails attempting to serialize the response. The error from Jackson suggest that i turn on FAIL_ON_EMPTY_BEANS in the serializer, but how do set this in restTemplate

The client consuming the rest api

@SuppressWarnings("rawtypes") @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {      RestTemplate restTemplate = new RestTemplate();     System.out.println("\n\n\n\n ============API REQUEST INTERCEPTOR=============== \n\n\n\n\n");      if(StringUtils.isBlank(request.getHeader(AuthenticationKeys.AUTHENTICATIONTOKEN.name().toLowerCase()))){         //TODO AUTHORIZE TOKEN         ResponseEntity<AuthenticationResponse> authenticateResponse = restTemplate.getForEntity(authenticateUrl, AuthenticationResponse.class);         if(authenticateResponse.getStatusCode().is2xxSuccessful()){             //TODO SET THE TOKEN IN THE CONTEXT             return true;         }else{             //TODO DO SOME ERROR HANDLING             return false;         }     }else{         AuthorizationRequest authorizationRequest = new AuthorizationRequest();         authorizationRequest.setToken("TESTNG");         ResponseEntity<Object> authorizationResponse = restTemplate.postForEntity(authorizeUrl, request, Object.class);         if(authorizationResponse.getStatusCode().is2xxSuccessful()){             return true;         }else{             //TODO DO SOME ERROR HANDLING             if(authorizationResponse.getStatusCode().equals(HttpStatus.UNAUTHORIZED)){                 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Oops! access to this API is not authorized to you.");             }             return false;         }     } 

The rest service

@RequestMapping(value="/authorize", method = RequestMethod.POST)     void authorize(@RequestBody @Valid AuthorizationRequest request, HttpServletResponse response){         if(request.getToken().equals("TESTING")){             response.setStatus(HttpServletResponse.SC_NO_CONTENT);         }else{             response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);         }     } } 

The exception

Caused by: com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.apache.catalina.connector.CoyoteInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.apache.shiro.web.servlet.ShiroHttpServletRequest["request"]->org.apache.catalina.connector.RequestFacade["inputStream"])     at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:26) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:575) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:663) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:575) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:663) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:129) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2238) ~[jackson-databind-2.5.0.jar:2.5.0]     at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     ... 52 more 

The Attempted Fix

RestTemplate restTemplate = new RestTemplate();         List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();         for(HttpMessageConverter<?> converter : converters){             if(converter instanceof MappingJackson2HttpMessageConverter){                 ((MappingJackson2HttpMessageConverter) converter).getObjectMapper().configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);             }         } 

The next error

org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: getInputStream() has already been called for this request (through reference chain: org.apache.shiro.web.servlet.ShiroHttpServletRequest["request"]->org.apache.catalina.connector.RequestFacade["reader"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: getInputStream() has already been called for this request (through reference chain: org.apache.shiro.web.servlet.ShiroHttpServletRequest["request"]->org.apache.catalina.connector.RequestFacade["reader"])     at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:238) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:777) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:566) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:529) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:356) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at mordeth.orchestration.interceptor.ApiRequestInterceptor.preHandle(ApiRequestInterceptor.java:120) ~[ApiRequestInterceptor.class:?]     at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:134) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) [spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) [spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868) [spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at javax.servlet.http.HttpServlet.service(HttpServlet.java:646) [servlet-api.jar:?]     at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api.jar:?]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) [catalina.jar:7.0.57]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.57]     at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat7-websocket.jar:7.0.57]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.57]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.57]     at mordeth.orchestration.controller.CorsFilter.doFilterInternal(CorsFilter.java:21) [CorsFilter.class:?]     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.57]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.57]     at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) [shiro-web-1.2.0.jar:1.2.0]     at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) [shiro-web-1.2.0.jar:1.2.0]     at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) [shiro-core-1.2.0.jar:1.2.0]     at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) [shiro-core-1.2.0.jar:1.2.0]     at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:380) [shiro-core-1.2.0.jar:1.2.0]     at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) [shiro-web-1.2.0.jar:1.2.0]     at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) [shiro-web-1.2.0.jar:1.2.0]     at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.57]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.57]     at org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:67) [log4j-web-2.0.jar:2.0]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.57]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.57]     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.57]     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.57]     at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503) [catalina.jar:7.0.57]     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) [catalina.jar:7.0.57]     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [catalina.jar:7.0.57]     at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [catalina.jar:7.0.57]     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.57]     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421) [catalina.jar:7.0.57]     at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070) [tomcat-coyote.jar:7.0.57]     at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611) [tomcat-coyote.jar:7.0.57]     at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314) [tomcat-coyote.jar:7.0.57]     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [?:1.7.0_71]     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [?:1.7.0_71]     at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.57]     at java.lang.Thread.run(Thread.java:745) [?:1.7.0_71] Caused by: com.fasterxml.jackson.databind.JsonMappingException: getInputStream() has already been called for this request (through reference chain: org.apache.shiro.web.servlet.ShiroHttpServletRequest["request"]->org.apache.catalina.connector.RequestFacade["reader"])     at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:210) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:177) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:190) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:671) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:575) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:663) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:129) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2238) ~[jackson-databind-2.5.0.jar:2.5.0]     at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     ... 52 more Caused by: java.lang.IllegalStateException: getInputStream() has already been called for this request     at org.apache.catalina.connector.Request.getReader(Request.java:1239) ~[catalina.jar:7.0.57]     at org.apache.catalina.connector.RequestFacade.getReader(RequestFacade.java:505) ~[catalina.jar:7.0.57]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_71]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_71]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_71]     at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_71]     at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:536) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:663) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:575) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:663) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:129) ~[jackson-databind-2.5.0.jar:2.5.0]     at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2238) ~[jackson-databind-2.5.0.jar:2.5.0]     at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]     ... 52 more 
like image 743
Monish Sen Avatar asked May 26 '15 07:05

Monish Sen


People also ask

What is difference between getForObject and getForEntity?

For example, the method getForObject() will perform a GET and return an object. getForEntity() : executes a GET request and returns an object of ResponseEntity class that contains both the status code and the resource as an object. getForObject() : similar to getForEntity() , but returns the resource directly.

How do you handle RestTemplate errors?

Default Error Handling 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 HttpEntity in RestTemplate?

public class HttpEntity<T> extends Object. Represents an HTTP request or response entity, consisting of headers and body.

How do you use RestTemplate getForObject?

The getForObject method fetches the data for the given response type from the given URI or URL template using HTTP GET method. To fetch data for the given key properties from URL template we can pass Object Varargs and Map to getForObject method. The getForObject returns directly the object of given response type.


1 Answers

Use String instead of AuthenticationResponse. If you get an empty response, the String value will be empty.

ResponseEntity<String> authenticateResponse = restTemplate.getForEntity(authenticateUrl, String.class); 

UPDATE: Check this link. I think this will fix your issue.

ResponseEntity<Void> response = restTemplate.getForEntity(authenticateUrl,Void.class); Void body = response.getBody(); 
like image 138
Hareesh Avatar answered Oct 06 '22 00:10

Hareesh