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
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.
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.
public class HttpEntity<T> extends Object. Represents an HTTP request or response entity, consisting of headers and body.
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.
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With