In AbstractMessageConverterMethodProcessor#writeWithMessageConverters method, it will create a list called mediaTypesToUse
by acceptableTypes
and producibleTypes
, its order is not added as we excepted, so it will cause choosing the wrong selectedMediaType
that will affect which converter to use.
By the way, the HTTP Header Accept Values
will be reordered by HeaderContentNegotiationStrategy
, this strategy may can solve this problem, even though this is not a same problem, and change this strategy is not such easy as https://github.com/spring-projects/spring-framework/issues/27488 mentioned.
Steps:
1. set MappingJackson2HttpMessageConverter as the first converter(order of converters)
2. send a request with headers have:
Accept: text/html, */*
or:
Accept: text/html, application/json
3. Controller return CharSequence
type
Will treat as a string type:
if (value instanceof CharSequence) {
body = value.toString();
valueType = String.class;
targetType = String.class;
}
Will produce a mediaTypesToUse
:
Both MappingJackson2HttpMessageConverter
and StringHttpMessageConverter
can write the result value, but it will use StringHttpMessageConverter
, even though MappingJackson2HttpMessageConverter
is the first converter of converters now.
Environment: Windows 10 Pro, Spring version 5.3.8
Comment From: poutsma
The acceptable media types are more significant than the producible ones by design, because otherwise the client would end up with a less desirable media type. From this, it follows that we iterate over the acceptable types before the producible ones.
This might have unforeseen consequences, like you describe above, but the alternative would definitely be worse. Changing this order, like you propose in #27725, breaks the ServletAnnotationControllerHandlerMethodTests
, and would break many applications as well, because of backward compatibility reasons.
Instead of relying on the message converter order, it works better to specify the desirable media types explicitly by using the produces
element of your @RequestMapping
annotation, see this section of the reference documentation.