Skip to content

Commit 62f9f47

Browse files
committed
SPR-6877 - AnnotationMethodHandlerAdapter.handleResponseBody prioritizes messageConverter over MediaType
1 parent 894875c commit 62f9f47

File tree

2 files changed

+73
-7
lines changed

2 files changed

+73
-7
lines changed

org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -871,17 +871,19 @@ private void handleResponseBody(Object returnValue, ServletWebRequest webRequest
871871
HttpOutputMessage outputMessage = new ServletServerHttpResponse(webRequest.getResponse());
872872
Class<?> returnValueType = returnValue.getClass();
873873
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
874-
if (messageConverters != null) {
875-
for (HttpMessageConverter messageConverter : messageConverters) {
876-
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
877-
for (MediaType acceptedMediaType : acceptedMediaTypes) {
874+
if (getMessageConverters() != null) {
875+
for (MediaType acceptedMediaType : acceptedMediaTypes) {
876+
for (HttpMessageConverter messageConverter : getMessageConverters()) {
878877
if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
879878
messageConverter.write(returnValue, acceptedMediaType, outputMessage);
880879
this.responseArgumentUsed = true;
881880
return;
882881
}
883882
}
884883
}
884+
for (HttpMessageConverter messageConverter : messageConverters) {
885+
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
886+
}
885887
}
886888
throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
887889
}

org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.lang.reflect.Method;
2727
import java.security.Principal;
2828
import java.text.SimpleDateFormat;
29+
import java.util.ArrayList;
2930
import java.util.Arrays;
3031
import java.util.Collections;
3132
import java.util.Date;
@@ -1037,7 +1038,7 @@ public void requestBodyResponseBody() throws ServletException, IOException {
10371038
String requestBody = "Hello World";
10381039
request.setContent(requestBody.getBytes("UTF-8"));
10391040
request.addHeader("Content-Type", "text/plain; charset=utf-8");
1040-
request.addHeader("Accept", "text/*");
1041+
request.addHeader("Accept", "text/*, */*");
10411042
MockHttpServletResponse response = new MockHttpServletResponse();
10421043
servlet.service(request, response);
10431044
assertEquals(200, response.getStatus());
@@ -1137,7 +1138,7 @@ protected WebApplicationContext createWebApplicationContext(WebApplicationContex
11371138
GenericWebApplicationContext wac = new GenericWebApplicationContext();
11381139
wac.registerBeanDefinition("controller", new RootBeanDefinition(RequestBodyController.class));
11391140
RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1140-
adapterDef.getPropertyValues().add("messageConverters", new MyMessageConverter());
1141+
adapterDef.getPropertyValues().add("messageConverters", new NotReadableMessageConverter());
11411142
wac.registerBeanDefinition("handlerAdapter", adapterDef);
11421143
wac.refresh();
11431144
return wac;
@@ -1154,6 +1155,38 @@ protected WebApplicationContext createWebApplicationContext(WebApplicationContex
11541155
assertEquals("Invalid response status code", HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
11551156
}
11561157

1158+
/*
1159+
* See SPR-6877
1160+
*/
1161+
@Test
1162+
public void overlappingMesssageConvertersRequestBody() throws ServletException, IOException {
1163+
@SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
1164+
@Override
1165+
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1166+
GenericWebApplicationContext wac = new GenericWebApplicationContext();
1167+
wac.registerBeanDefinition("controller", new RootBeanDefinition(RequestBodyController.class));
1168+
RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1169+
List<HttpMessageConverter> messageConverters = new ArrayList<HttpMessageConverter>();
1170+
messageConverters.add(new StringHttpMessageConverter());
1171+
messageConverters
1172+
.add(new SimpleMessageConverter(new MediaType("application","json"), MediaType.ALL));
1173+
adapterDef.getPropertyValues().add("messageConverters", messageConverters);
1174+
wac.registerBeanDefinition("handlerAdapter", adapterDef);
1175+
wac.refresh();
1176+
return wac;
1177+
}
1178+
};
1179+
servlet.init(new MockServletConfig());
1180+
1181+
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
1182+
request.setContent("Hello World".getBytes("UTF-8"));
1183+
request.addHeader("Content-Type", "text/plain; charset=utf-8");
1184+
request.addHeader("Accept", "application/json, text/javascript, */*");
1185+
MockHttpServletResponse response = new MockHttpServletResponse();
1186+
servlet.service(request, response);
1187+
assertEquals("Invalid response status code", "application/json", response.getHeader("Content-Type"));
1188+
}
1189+
11571190
@Test
11581191
public void headers() throws ServletException, IOException {
11591192
initServlet(HeadersController.class);
@@ -2123,7 +2156,7 @@ public String handle(@RequestBody String body) throws IOException {
21232156
}
21242157
}
21252158

2126-
public static class MyMessageConverter implements HttpMessageConverter {
2159+
public static class NotReadableMessageConverter implements HttpMessageConverter {
21272160

21282161
public boolean canRead(Class clazz, MediaType mediaType) {
21292162
return true;
@@ -2148,6 +2181,37 @@ public void write(Object o, MediaType contentType, HttpOutputMessage outputMessa
21482181
}
21492182
}
21502183

2184+
public static class SimpleMessageConverter implements HttpMessageConverter {
2185+
2186+
private final List<MediaType> supportedMediaTypes;
2187+
2188+
public SimpleMessageConverter(MediaType... supportedMediaTypes) {
2189+
this.supportedMediaTypes = Arrays.asList(supportedMediaTypes);
2190+
}
2191+
2192+
public boolean canRead(Class clazz, MediaType mediaType) {
2193+
return supportedMediaTypes.contains(mediaType);
2194+
}
2195+
2196+
public boolean canWrite(Class clazz, MediaType mediaType) {
2197+
return supportedMediaTypes.contains(mediaType);
2198+
}
2199+
2200+
public List getSupportedMediaTypes() {
2201+
return supportedMediaTypes;
2202+
}
2203+
2204+
public Object read(Class clazz, HttpInputMessage inputMessage)
2205+
throws IOException, HttpMessageNotReadableException {
2206+
return null;
2207+
}
2208+
2209+
public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage)
2210+
throws IOException, HttpMessageNotWritableException {
2211+
outputMessage.getHeaders().setContentType(contentType);
2212+
}
2213+
}
2214+
21512215
@Controller
21522216
public static class HeadersController {
21532217

0 commit comments

Comments
 (0)