From 35f40ae6549e9cb7e597e59b85683ece297132cf Mon Sep 17 00:00:00 2001 From: Sebastien Deleuze Date: Thu, 2 Apr 2015 12:05:45 +0200 Subject: [PATCH] Add @JsonView deserialization support for request bodies Jackson 2.5.0 or later is required. Issue: SPR-12501 --- .../AbstractJackson2HttpMessageConverter.java | 7 + .../json/MappingJacksonInputMessage.java | 70 +++++++++ .../AnnotationDrivenBeanDefinitionParser.java | 9 ++ .../WebMvcConfigurationSupport.java | 12 +- .../annotation/JsonViewRequestBodyAdvice.java | 70 +++++++++ ...tationDrivenBeanDefinitionParserTests.java | 4 +- .../WebMvcConfigurationSupportTests.java | 6 +- ...questResponseBodyMethodProcessorTests.java | 143 +++++++++++++++--- 8 files changed, 297 insertions(+), 24 deletions(-) create mode 100644 spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonInputMessage.java create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/JsonViewRequestBodyAdvice.java diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java index 5bdb5bb880..47d460dca5 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java @@ -203,6 +203,13 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractHttpM private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) { try { + if (inputMessage instanceof MappingJacksonInputMessage) { + Class deserializationView = ((MappingJacksonInputMessage)inputMessage).getDeserializationView(); + if (deserializationView != null) { + return this.objectMapper.readerWithView(deserializationView) + .forType(javaType).readValue(inputMessage.getBody()); + } + } return this.objectMapper.readValue(inputMessage.getBody(), javaType); } catch (IOException ex) { diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonInputMessage.java b/spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonInputMessage.java new file mode 100644 index 0000000000..1e6492c77c --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonInputMessage.java @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.http.converter.json; + +import java.io.IOException; +import java.io.InputStream; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpInputMessage; + +/** + * {@link HttpInputMessage} that can eventually stores a Jackson view that will be used + * to deserialize the message. + * + * @author Sebastien Deleuze + * @since 4.2 + */ +public class MappingJacksonInputMessage implements HttpInputMessage { + + private final InputStream body; + + private final HttpHeaders headers; + + private Class deserializationView; + + + public MappingJacksonInputMessage(InputStream body, HttpHeaders headers) { + this.body = body; + this.headers = headers; + } + + public MappingJacksonInputMessage(InputStream body, HttpHeaders headers, Class deserializationView) { + this(body, headers); + this.deserializationView = deserializationView; + } + + + public void setDeserializationView(Class deserializationView) { + this.deserializationView = deserializationView; + } + + public Class getDeserializationView() { + return deserializationView; + } + + @Override + public InputStream getBody() throws IOException { + return this.body; + } + + @Override + public HttpHeaders getHeaders() { + return this.headers; + } + +} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java index 588a64c3e6..dca386dfe3 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java @@ -73,6 +73,7 @@ import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter; import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter; import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; +import org.springframework.web.servlet.mvc.method.annotation.JsonViewRequestBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; @@ -221,6 +222,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager); handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef); handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters); + addRequestBodyAdvice(handlerAdapterDef); addResponseBodyAdvice(handlerAdapterDef); if (element.hasAttribute("ignore-default-model-on-redirect")) { @@ -308,6 +310,13 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { return null; } + protected void addRequestBodyAdvice(RootBeanDefinition beanDef) { + if (jackson2Present) { + beanDef.getPropertyValues().add("requestBodyAdvice", + new RootBeanDefinition(JsonViewRequestBodyAdvice.class)); + } + } + protected void addResponseBodyAdvice(RootBeanDefinition beanDef) { if (jackson2Present) { beanDef.getPropertyValues().add("responseBodyAdvice", diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index aea2bc348f..fe63763026 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -83,7 +83,9 @@ import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter; import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter; import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; +import org.springframework.web.servlet.mvc.method.annotation.JsonViewRequestBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice; +import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; @@ -478,9 +480,13 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv adapter.setCustomReturnValueHandlers(returnValueHandlers); if (jackson2Present) { - List> interceptors = new ArrayList>(); - interceptors.add(new JsonViewResponseBodyAdvice()); - adapter.setResponseBodyAdvice(interceptors); + List requestBodyAdvices = new ArrayList(); + requestBodyAdvices.add(new JsonViewRequestBodyAdvice()); + adapter.setRequestBodyAdvice(requestBodyAdvices); + + List> responseBodyAdvices = new ArrayList>(); + responseBodyAdvices.add(new JsonViewResponseBodyAdvice()); + adapter.setResponseBodyAdvice(responseBodyAdvices); } AsyncSupportConfigurer configurer = new AsyncSupportConfigurer(); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/JsonViewRequestBodyAdvice.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/JsonViewRequestBodyAdvice.java new file mode 100644 index 0000000000..3708e7a02e --- /dev/null +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/JsonViewRequestBodyAdvice.java @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.servlet.mvc.method.annotation; + +import java.io.IOException; +import java.lang.reflect.Type; + +import com.fasterxml.jackson.annotation.JsonView; + +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; +import org.springframework.http.converter.json.MappingJacksonInputMessage; + +/** + * A {@code RequestBodyAdvice} implementation that adds support for + * Jackson's {@code @JsonView} annotation declared on a Spring MVC + * {@code @HttpEntity} and {@code @RequestBody} method parameters. + * + *

The deserialization view specified in the annotation will be passed in to + * the {@code MappingJackson2HttpMessageConverter} which will then use it to + * deserialize the request body with. + * + *

Note that despite {@code @JsonView} allowing for more than one class to + * be specified, the use for a request body advice is only supported with + * exactly one class argument. Consider the use of a composite interface. + * + *

Jackson 2.5.0 or later is required. + * + * @author Sebastien Deleuze + * @since 4.2 + * @see com.fasterxml.jackson.databind.ObjectMapper#readerWithView(Class) + */ +public class JsonViewRequestBodyAdvice extends RequestBodyAdviceAdapter { + + @Override + public boolean supports(MethodParameter methodParameter, Type targetType, + Class> converterType) { + return (AbstractJackson2HttpMessageConverter.class.isAssignableFrom(converterType) && + methodParameter.getParameterAnnotation(JsonView.class) != null); + } + + @Override + public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter methodParameter, + Type targetType, Class> selectedConverterType) throws IOException { + JsonView annotation = methodParameter.getParameterAnnotation(JsonView.class); + Class[] classes = annotation.value(); + if (classes.length != 1) { + throw new IllegalArgumentException( + "@JsonView only supported for request body advice with exactly 1 class argument: " + methodParameter); + } + return new MappingJacksonInputMessage(inputMessage.getBody(), inputMessage.getHeaders(), classes[0]); + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java index ff553f67e7..322acd675b 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java @@ -40,6 +40,7 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; +import org.springframework.web.servlet.mvc.method.annotation.JsonViewRequestBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; @@ -189,7 +190,8 @@ public class AnnotationDrivenBeanDefinitionParserTests { assertNotNull(value); assertTrue(value instanceof List); List converters = (List) value; - assertTrue(converters.get(0) instanceof JsonViewResponseBodyAdvice); + assertTrue(converters.get(0) instanceof JsonViewRequestBodyAdvice); + assertTrue(converters.get(1) instanceof JsonViewResponseBodyAdvice); } } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java index 17e3ed3fb7..277897c307 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java @@ -71,6 +71,7 @@ import org.springframework.web.servlet.handler.ConversionServiceExposingIntercep import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite; import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; +import org.springframework.web.servlet.mvc.method.annotation.JsonViewRequestBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; @@ -190,8 +191,9 @@ public class WebMvcConfigurationSupportTests { DirectFieldAccessor fieldAccessor = new DirectFieldAccessor(adapter); @SuppressWarnings("unchecked") List interceptors = (List) fieldAccessor.getPropertyValue("requestResponseBodyAdvice"); - assertEquals(1, interceptors.size()); - assertEquals(JsonViewResponseBodyAdvice.class, interceptors.get(0).getClass()); + assertEquals(2, interceptors.size()); + assertEquals(JsonViewRequestBodyAdvice.class, interceptors.get(0).getClass()); + assertEquals(JsonViewResponseBodyAdvice.class, interceptors.get(1).getClass()); } @Test diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java index 2e64b0a5fe..be6a90944a 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java @@ -30,6 +30,7 @@ import org.junit.Test; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.target.SingletonTargetSource; import org.springframework.core.MethodParameter; +import org.springframework.http.HttpEntity; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -179,9 +180,7 @@ public class RequestResponseBodyMethodProcessorTests { assertEquals("foobarbaz", result); } - // SPR-9942 - - @Test(expected = HttpMessageNotReadableException.class) + @Test(expected = HttpMessageNotReadableException.class) // SPR-9942 public void resolveArgumentRequiredNoContent() throws Exception { this.servletRequest.setContent(new byte[0]); this.servletRequest.setContentType("text/plain"); @@ -191,9 +190,7 @@ public class RequestResponseBodyMethodProcessorTests { processor.resolveArgument(paramString, mavContainer, webRequest, binderFactory); } - // SPR-12778 - - @Test + @Test // SPR-12778 public void resolveArgumentRequiredNoContentDefaultValue() throws Exception { this.servletRequest.setContent(new byte[0]); this.servletRequest.setContentType("text/plain"); @@ -205,9 +202,7 @@ public class RequestResponseBodyMethodProcessorTests { assertEquals("default value for empty body", arg); } - // SPR-9964 - - @Test + @Test // SPR-9964 public void resolveArgumentTypeVariable() throws Exception { Method method = MyParameterizedController.class.getMethod("handleDto", Identifiable.class); HandlerMethod handlerMethod = new HandlerMethod(new MySimpleParameterizedController(), method); @@ -227,9 +222,7 @@ public class RequestResponseBodyMethodProcessorTests { assertEquals("Jad", result.getName()); } - // SPR-11225 - - @Test + @Test // SPR-11225 public void resolveArgumentTypeVariableWithNonGenericConverter() throws Exception { Method method = MyParameterizedController.class.getMethod("handleDto", Identifiable.class); HandlerMethod handlerMethod = new HandlerMethod(new MySimpleParameterizedController(), method); @@ -251,9 +244,7 @@ public class RequestResponseBodyMethodProcessorTests { assertEquals("Jad", result.getName()); } - // SPR-9160 - - @Test + @Test // SPR-9160 public void handleReturnValueSortByQuality() throws Exception { this.servletRequest.addHeader("Accept", "text/plain; q=0.5, application/json"); @@ -383,9 +374,7 @@ public class RequestResponseBodyMethodProcessorTests { assertFalse(content.contains("without")); } - // SPR-12149 - - @Test + @Test // SPR-12149 public void jacksonJsonViewWithResponseEntityAndXmlMessageConverter() throws Exception { Method method = JacksonViewController.class.getMethod("handleResponseEntity"); HandlerMethod handlerMethod = new HandlerMethod(new JacksonViewController(), method); @@ -406,6 +395,112 @@ public class RequestResponseBodyMethodProcessorTests { assertFalse(content.contains("without")); } + @Test // SPR-12501 + public void resolveArgumentWithJacksonJsonView() throws Exception { + String content = "{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}"; + this.servletRequest.setContent(content.getBytes("UTF-8")); + this.servletRequest.setContentType(MediaType.APPLICATION_JSON_VALUE); + + Method method = JacksonViewController.class.getMethod("handleRequestBody", JacksonViewBean.class); + HandlerMethod handlerMethod = new HandlerMethod(new JacksonViewController(), method); + MethodParameter methodParameter = handlerMethod.getMethodParameters()[0]; + + List> converters = new ArrayList>(); + converters.add(new MappingJackson2HttpMessageConverter()); + + RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor( + converters, null, Arrays.asList(new JsonViewRequestBodyAdvice())); + + @SuppressWarnings("unchecked") + JacksonViewBean result = (JacksonViewBean)processor.resolveArgument(methodParameter, + this.mavContainer, this.webRequest, this.binderFactory); + + assertNotNull(result); + assertEquals("with", result.getWithView1()); + assertNull(result.getWithView2()); + assertNull(result.getWithoutView()); + } + + @Test // SPR-12501 + public void resolveHttpEntityArgumentWithJacksonJsonView() throws Exception { + String content = "{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}"; + this.servletRequest.setContent(content.getBytes("UTF-8")); + this.servletRequest.setContentType(MediaType.APPLICATION_JSON_VALUE); + + Method method = JacksonViewController.class.getMethod("handleHttpEntity", HttpEntity.class); + HandlerMethod handlerMethod = new HandlerMethod(new JacksonViewController(), method); + MethodParameter methodParameter = handlerMethod.getMethodParameters()[0]; + + List> converters = new ArrayList>(); + converters.add(new MappingJackson2HttpMessageConverter()); + + HttpEntityMethodProcessor processor = new HttpEntityMethodProcessor( + converters, null, Arrays.asList(new JsonViewRequestBodyAdvice())); + + @SuppressWarnings("unchecked") + HttpEntity result = (HttpEntity)processor.resolveArgument(methodParameter, + this.mavContainer, this.webRequest, this.binderFactory); + + assertNotNull(result); + assertNotNull(result.getBody()); + assertEquals("with", result.getBody().getWithView1()); + assertNull(result.getBody().getWithView2()); + assertNull(result.getBody().getWithoutView()); + } + + @Test // SPR-12501 + public void resolveArgumentWithJacksonJsonViewAndXmlMessageConverter() throws Exception { + String content = "withwithwithout"; + this.servletRequest.setContent(content.getBytes("UTF-8")); + this.servletRequest.setContentType(MediaType.APPLICATION_XML_VALUE); + + Method method = JacksonViewController.class.getMethod("handleRequestBody", JacksonViewBean.class); + HandlerMethod handlerMethod = new HandlerMethod(new JacksonViewController(), method); + MethodParameter methodParameter = handlerMethod.getMethodParameters()[0]; + + List> converters = new ArrayList>(); + converters.add(new MappingJackson2XmlHttpMessageConverter()); + + RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor( + converters, null, Arrays.asList(new JsonViewRequestBodyAdvice())); + + @SuppressWarnings("unchecked") + JacksonViewBean result = (JacksonViewBean)processor.resolveArgument(methodParameter, + this.mavContainer, this.webRequest, this.binderFactory); + + assertNotNull(result); + assertEquals("with", result.getWithView1()); + assertNull(result.getWithView2()); + assertNull(result.getWithoutView()); + } + + @Test // SPR-12501 + public void resolveHttpEntityArgumentWithJacksonJsonViewAndXmlMessageConverter() throws Exception { + String content = "withwithwithout"; + this.servletRequest.setContent(content.getBytes("UTF-8")); + this.servletRequest.setContentType(MediaType.APPLICATION_XML_VALUE); + + Method method = JacksonViewController.class.getMethod("handleHttpEntity", HttpEntity.class); + HandlerMethod handlerMethod = new HandlerMethod(new JacksonViewController(), method); + MethodParameter methodParameter = handlerMethod.getMethodParameters()[0]; + + List> converters = new ArrayList>(); + converters.add(new MappingJackson2XmlHttpMessageConverter()); + + HttpEntityMethodProcessor processor = new HttpEntityMethodProcessor( + converters, null, Arrays.asList(new JsonViewRequestBodyAdvice())); + + @SuppressWarnings("unchecked") + HttpEntity result = (HttpEntity)processor.resolveArgument(methodParameter, + this.mavContainer, this.webRequest, this.binderFactory); + + assertNotNull(result); + assertNotNull(result.getBody()); + assertEquals("with", result.getBody().getWithView1()); + assertNull(result.getBody().getWithView2()); + assertNull(result.getBody().getWithoutView()); + } + @SuppressWarnings("unused") public String handle( @@ -563,6 +658,18 @@ public class RequestResponseBodyMethodProcessorTests { return new ResponseEntity(bean, HttpStatus.OK); } + @RequestMapping + @ResponseBody + public JacksonViewBean handleRequestBody(@JsonView(MyJacksonView1.class) @RequestBody JacksonViewBean bean) { + return bean; + } + + @RequestMapping + @ResponseBody + public JacksonViewBean handleHttpEntity(@JsonView(MyJacksonView1.class) HttpEntity entity) { + return entity.getBody(); + } + } private static class EmptyRequestBodyAdvice implements RequestBodyAdvice {