web-dev-qa-db-fra.com

Comment gérer une réponse vide dans Spring RestTemplate

Mon service d'autorisation renvoie un http 204 en cas de succès et un http 401 en cas d'échec, mais pas de responseBody. Je ne suis pas en mesure de consommer cela avec le client RestTemplate. Il échoue lors de la tentative de sérialisation de la réponse. L'erreur de Jackson suggère que j'active FAIL_ON_EMPTY_BEANS dans le sérialiseur, mais comment définir cela dans restTemplate

Le client consommant le reste de l'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;
        }
    }

Le service de repos

@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);
        }
    }
}

L'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

Le correctif tenté

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);
            }
        }

La prochaine erreur

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
22
Monish Sen

Utilisez String au lieu de AuthenticationResponse. Si vous obtenez une réponse vide, la valeur String sera vide.

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

MISE À JOUR: Vérifiez cela lien . Je pense que cela résoudra votre problème.

ResponseEntity<Void> response = restTemplate.getForEntity(authenticateUrl,Void.class);
Void body = response.getBody();
43
Hareesh