I'm using spring-boot with spring-web and jackson.
Problem: when a RestTemplate is initialized automatically by spring, the constructor receives some duplicate MessageConverters:
org.springframework.http.converter.ByteArrayHttpMessageConverter@6a1b4854,
org.springframework.http.converter.StringHttpMessageConverter@2d5b549b,
org.springframework.http.converter.StringHttpMessageConverter@6a175162,
org.springframework.http.converter.ResourceHttpMessageConverter@7641c4e7,
org.springframework.http.converter.ResourceRegionHttpMessageConverter@650a0b50,
org.springframework.http.converter.xml.SourceHttpMessageConverter@55e3b64d,
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@52f71d2,
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@f3c27e9,
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@7d31fb6c,
org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter@701c413,
org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter@48543f11
You see, there are 3 duplicates:
StringHttpMessageConverter
MappingJackson2HttpMessageConverter
MappingJackson2XmlHttpMessageConverter
As I don't initialize any message converters myself: why does the application context contain duplicate converters at all, that are then added to the resttemplate?
Especially: doesn't this confuse the (de)serializing if some converters occur duplicate (but with different configuration)?
For example: the ObjectMapper of the first MappingJackson2HttpMessageConverter contains more registeredModuleTypes [Jdk8Module, JavaTimeModule, ParamterNamesModule, JsonComponentModule, GeoModule] than the 2nd one (that only contains: [Jdk8Module, JavaTimeModule]).
Does that make sense?
It's instantiated via RestTemplateAutoConfiguration.restTemplateBuilder(), there all the duplicate MessageConverters are already present.
The culprit is here, at
HttpMessageConvertersSpecifically, this line (formatted)
The
converterscollection contains the scannedHttpMessageConverter(s).Based on the environment.
That list is then joined with a default one provided by
WebMvcConfigurationSupportInfact the documentations for
WebMvcConfigurationSupportstatesThe scanned
HttpMessageConverter(s) are found and instantiated viaHttpMessageConvertersAutoConfiguration, whose documentation isThat class exposes by itself a
StringHttpMessageConverterThan, it imports Jackson or Gson auto-configurations
And that's how those environment-based ones are "summed" to the pre-defined ones.
Spring doesn't get confused by duplicates because it just takes the first which is compatible.
See how an
HttpMessageConverteris choosedYou can see it is just a simple for loop, and each convert is asked to say "can I do this?" via the
canWritemethodThe first valid is picked.