From 62f9f477f5887c3c6237472d7d8db04510675ceb Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 3 Mar 2010 10:18:59 +0000 Subject: [PATCH] SPR-6877 - AnnotationMethodHandlerAdapter.handleResponseBody prioritizes messageConverter over MediaType --- .../AnnotationMethodHandlerAdapter.java | 10 +-- .../ServletAnnotationControllerTests.java | 70 ++++++++++++++++++- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java index da565f3b23f..0c5a823cb39 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java @@ -871,10 +871,9 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator HttpOutputMessage outputMessage = new ServletServerHttpResponse(webRequest.getResponse()); Class returnValueType = returnValue.getClass(); List allSupportedMediaTypes = new ArrayList(); - if (messageConverters != null) { - for (HttpMessageConverter messageConverter : messageConverters) { - allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes()); - for (MediaType acceptedMediaType : acceptedMediaTypes) { + if (getMessageConverters() != null) { + for (MediaType acceptedMediaType : acceptedMediaTypes) { + for (HttpMessageConverter messageConverter : getMessageConverters()) { if (messageConverter.canWrite(returnValueType, acceptedMediaType)) { messageConverter.write(returnValue, acceptedMediaType, outputMessage); this.responseArgumentUsed = true; @@ -882,6 +881,9 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator } } } + for (HttpMessageConverter messageConverter : messageConverters) { + allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes()); + } } throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes); } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java index acc7c57180a..c0681bcb034 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java @@ -26,6 +26,7 @@ import java.lang.annotation.Target; import java.lang.reflect.Method; import java.security.Principal; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -1037,7 +1038,7 @@ public class ServletAnnotationControllerTests { String requestBody = "Hello World"; request.setContent(requestBody.getBytes("UTF-8")); request.addHeader("Content-Type", "text/plain; charset=utf-8"); - request.addHeader("Accept", "text/*"); + request.addHeader("Accept", "text/*, */*"); MockHttpServletResponse response = new MockHttpServletResponse(); servlet.service(request, response); assertEquals(200, response.getStatus()); @@ -1137,7 +1138,7 @@ public class ServletAnnotationControllerTests { GenericWebApplicationContext wac = new GenericWebApplicationContext(); wac.registerBeanDefinition("controller", new RootBeanDefinition(RequestBodyController.class)); RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class); - adapterDef.getPropertyValues().add("messageConverters", new MyMessageConverter()); + adapterDef.getPropertyValues().add("messageConverters", new NotReadableMessageConverter()); wac.registerBeanDefinition("handlerAdapter", adapterDef); wac.refresh(); return wac; @@ -1154,6 +1155,38 @@ public class ServletAnnotationControllerTests { assertEquals("Invalid response status code", HttpServletResponse.SC_BAD_REQUEST, response.getStatus()); } + /* + * See SPR-6877 + */ + @Test + public void overlappingMesssageConvertersRequestBody() throws ServletException, IOException { + @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() { + @Override + protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) { + GenericWebApplicationContext wac = new GenericWebApplicationContext(); + wac.registerBeanDefinition("controller", new RootBeanDefinition(RequestBodyController.class)); + RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class); + List messageConverters = new ArrayList(); + messageConverters.add(new StringHttpMessageConverter()); + messageConverters + .add(new SimpleMessageConverter(new MediaType("application","json"), MediaType.ALL)); + adapterDef.getPropertyValues().add("messageConverters", messageConverters); + wac.registerBeanDefinition("handlerAdapter", adapterDef); + wac.refresh(); + return wac; + } + }; + servlet.init(new MockServletConfig()); + + MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something"); + request.setContent("Hello World".getBytes("UTF-8")); + request.addHeader("Content-Type", "text/plain; charset=utf-8"); + request.addHeader("Accept", "application/json, text/javascript, */*"); + MockHttpServletResponse response = new MockHttpServletResponse(); + servlet.service(request, response); + assertEquals("Invalid response status code", "application/json", response.getHeader("Content-Type")); + } + @Test public void headers() throws ServletException, IOException { initServlet(HeadersController.class); @@ -2123,7 +2156,7 @@ public class ServletAnnotationControllerTests { } } - public static class MyMessageConverter implements HttpMessageConverter { + public static class NotReadableMessageConverter implements HttpMessageConverter { public boolean canRead(Class clazz, MediaType mediaType) { return true; @@ -2148,6 +2181,37 @@ public class ServletAnnotationControllerTests { } } + public static class SimpleMessageConverter implements HttpMessageConverter { + + private final List supportedMediaTypes; + + public SimpleMessageConverter(MediaType... supportedMediaTypes) { + this.supportedMediaTypes = Arrays.asList(supportedMediaTypes); + } + + public boolean canRead(Class clazz, MediaType mediaType) { + return supportedMediaTypes.contains(mediaType); + } + + public boolean canWrite(Class clazz, MediaType mediaType) { + return supportedMediaTypes.contains(mediaType); + } + + public List getSupportedMediaTypes() { + return supportedMediaTypes; + } + + public Object read(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + return null; + } + + public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + outputMessage.getHeaders().setContentType(contentType); + } + } + @Controller public static class HeadersController {