SPR-7353 Use canWrite to narrow down list of producible types
This commit is contained in:
parent
d02e37a307
commit
c5833b192e
|
|
@ -164,8 +164,10 @@ public abstract class AbstractMessageConverterMethodProcessor
|
|||
ServletServerHttpResponse outputMessage)
|
||||
throws IOException, HttpMediaTypeNotAcceptableException {
|
||||
|
||||
Class<?> returnValueClass = returnValue.getClass();
|
||||
|
||||
List<MediaType> acceptableMediaTypes = getAcceptableMediaTypes(inputMessage);
|
||||
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(inputMessage.getServletRequest());
|
||||
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(inputMessage.getServletRequest(), returnValueClass);
|
||||
|
||||
Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>();
|
||||
for (MediaType a : acceptableMediaTypes) {
|
||||
|
|
@ -196,7 +198,7 @@ public abstract class AbstractMessageConverterMethodProcessor
|
|||
|
||||
if (selectedMediaType != null) {
|
||||
for (HttpMessageConverter<?> messageConverter : messageConverters) {
|
||||
if (messageConverter.canWrite(returnValue.getClass(), selectedMediaType)) {
|
||||
if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {
|
||||
((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Written [" + returnValue + "] as \"" + selectedMediaType + "\" using [" +
|
||||
|
|
@ -213,23 +215,28 @@ public abstract class AbstractMessageConverterMethodProcessor
|
|||
* Returns the media types that can be produced:
|
||||
* <ul>
|
||||
* <li>The producible media types specified in the request mappings, or
|
||||
* <li>The media types supported by all configured message converters, or
|
||||
* <li>Media types of configured converters that can write the specific return value, or
|
||||
* <li>{@link MediaType#ALL}
|
||||
* </ul>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<MediaType> getProducibleMediaTypes(HttpServletRequest request) {
|
||||
protected List<MediaType> getProducibleMediaTypes(HttpServletRequest request, Class<?> returnValueClass) {
|
||||
Set<MediaType> mediaTypes = (Set<MediaType>) request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
|
||||
if (!CollectionUtils.isEmpty(mediaTypes)) {
|
||||
return new ArrayList<MediaType>(mediaTypes);
|
||||
}
|
||||
else if (!allSupportedMediaTypes.isEmpty()) {
|
||||
return allSupportedMediaTypes;
|
||||
List<MediaType> result = new ArrayList<MediaType>();
|
||||
for (HttpMessageConverter<?> converter : messageConverters) {
|
||||
if (converter.canWrite(returnValueClass, null)) {
|
||||
result.addAll(converter.getSupportedMediaTypes());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return Collections.singletonList(MediaType.ALL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<MediaType> getAcceptableMediaTypes(HttpInputMessage inputMessage) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,18 @@
|
|||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.method.annotation.support;
|
||||
import static org.easymock.EasyMock.capture;
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.eq;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.isA;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.easymock.EasyMock.reset;
|
||||
import static org.easymock.EasyMock.verify;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.web.servlet.HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
|
@ -24,7 +36,6 @@ import java.util.Collections;
|
|||
import org.easymock.Capture;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
|
@ -41,10 +52,6 @@ import org.springframework.web.HttpMediaTypeNotSupportedException;
|
|||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Test fixture with {@link HttpEntityMethodProcessor} and mock {@link HttpMessageConverter}.
|
||||
|
|
@ -164,6 +171,8 @@ public class HttpEntityMethodProcessorTests {
|
|||
MediaType accepted = MediaType.TEXT_PLAIN;
|
||||
servletRequest.addHeader("Accept", accepted.toString());
|
||||
|
||||
expect(messageConverter.canWrite(String.class, null)).andReturn(true);
|
||||
expect(messageConverter.getSupportedMediaTypes()).andReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
|
||||
expect(messageConverter.canWrite(String.class, accepted)).andReturn(true);
|
||||
messageConverter.write(eq(body), eq(accepted), isA(HttpOutputMessage.class));
|
||||
replay(messageConverter);
|
||||
|
|
@ -218,6 +227,8 @@ public class HttpEntityMethodProcessorTests {
|
|||
MediaType accepted = MediaType.TEXT_PLAIN;
|
||||
servletRequest.addHeader("Accept", accepted.toString());
|
||||
|
||||
expect(messageConverter.canWrite(String.class, null)).andReturn(true);
|
||||
expect(messageConverter.getSupportedMediaTypes()).andReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
|
||||
expect(messageConverter.canWrite(String.class, accepted)).andReturn(false);
|
||||
replay(messageConverter);
|
||||
|
||||
|
|
@ -245,6 +256,8 @@ public class HttpEntityMethodProcessorTests {
|
|||
ResponseEntity<String> returnValue = new ResponseEntity<String>("body", responseHeaders, HttpStatus.ACCEPTED);
|
||||
|
||||
Capture<HttpOutputMessage> outputMessage = new Capture<HttpOutputMessage>();
|
||||
expect(messageConverter.canWrite(String.class, null)).andReturn(true);
|
||||
expect(messageConverter.getSupportedMediaTypes()).andReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
|
||||
expect(messageConverter.canWrite(String.class, MediaType.TEXT_PLAIN)).andReturn(true);
|
||||
messageConverter.write(eq("body"), eq(MediaType.TEXT_PLAIN), capture(outputMessage));
|
||||
replay(messageConverter);
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@
|
|||
package org.springframework.web.servlet.mvc.method.annotation.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
|
@ -27,7 +29,9 @@ import org.springframework.core.MethodParameter;
|
|||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
|
|
@ -151,6 +155,8 @@ public class RequestResponseBodyMethodProcessorTests {
|
|||
servletRequest.addHeader("Accept", accepted.toString());
|
||||
|
||||
String body = "Foo";
|
||||
expect(messageConverter.canWrite(String.class, null)).andReturn(true);
|
||||
expect(messageConverter.getSupportedMediaTypes()).andReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
|
||||
expect(messageConverter.canWrite(String.class, accepted)).andReturn(true);
|
||||
messageConverter.write(eq(body), eq(accepted), isA(HttpOutputMessage.class));
|
||||
replay(messageConverter);
|
||||
|
|
@ -199,6 +205,8 @@ public class RequestResponseBodyMethodProcessorTests {
|
|||
MediaType accepted = MediaType.TEXT_PLAIN;
|
||||
servletRequest.addHeader("Accept", accepted.toString());
|
||||
|
||||
expect(messageConverter.canWrite(String.class, null)).andReturn(true);
|
||||
expect(messageConverter.getSupportedMediaTypes()).andReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
|
||||
expect(messageConverter.canWrite(String.class, accepted)).andReturn(false);
|
||||
replay(messageConverter);
|
||||
|
||||
|
|
@ -207,6 +215,19 @@ public class RequestResponseBodyMethodProcessorTests {
|
|||
fail("Expected exception");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleStringReturnValue() throws Exception {
|
||||
List<HttpMessageConverter<?>>converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
converters.add(new ByteArrayHttpMessageConverter());
|
||||
converters.add(new StringHttpMessageConverter());
|
||||
|
||||
processor = new RequestResponseBodyMethodProcessor(converters);
|
||||
processor.handleReturnValue("Foo", returnTypeString, mavContainer, webRequest);
|
||||
|
||||
assertEquals("text/plain;charset=ISO-8859-1", servletResponse.getHeader("Content-Type"));
|
||||
assertEquals("Foo", servletResponse.getContentAsString());
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
public String handle1(@RequestBody String s, int i) {
|
||||
return s;
|
||||
|
|
|
|||
Loading…
Reference in New Issue