Affects: 2.7.x
Configuration of Jackson is only done with this configuration class:
@Configuration
public class MiscConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer builderCustomizer() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
}
When the project is running request mapping is done as if the configuration is not applied.
When I autowire MappingJackson2HttpMessageConverter to some dummy component and run serialization by hand it works fine.
@Component
public class Dummy {
private final MappingJackson2HttpMessageConverter c;
public Dummy(MappingJackson2HttpMessageConverter c) {
this.c = c;
c.getObjectMapper().writeValueAsString(ZonedDateTIme.now()); // works fine
}
}
When I dived into spring mvc configurations I saw this method in WebMvcConfigurationSupport
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcValidator") Validator validator) {
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
adapter.setContentNegotiationManager(contentNegotiationManager);
adapter.setMessageConverters(getMessageConverters());
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
adapter.setCustomArgumentResolvers(getArgumentResolvers());
adapter.setCustomReturnValueHandlers(getReturnValueHandlers());
...
}
protected final List<HttpMessageConverter<?>> getMessageConverters() {
if (this.messageConverters == null) { // always is null at first run
this.messageConverters = new ArrayList<>();
configureMessageConverters(this.messageConverters); // calls all WebMvcConfigurers which do nothing on this call
if (this.messageConverters.isEmpty()) {
addDefaultHttpMessageConverters(this.messageConverters); // creation of converter showed next line
// new MappingJackson2HttpMessageConverter(Jackson2ObjectMapperBuilder.json().build())
}
extendMessageConverters(this.messageConverters); // calls all WebMvcConfigurers which do nothing on this call
}
return this.messageConverters;
}
}
so it looks like only converter for json is default one
Only elegant workaround I've found is to insert autowired Converter inside converters list with the help of WebMvcConfigurer.extendMessageConverters
@Configuration
@EnableWebSecurity
@EnableWebMvc
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class Config implements WebMvcConfigurer {
private final MappingJackson2HttpMessageConverter jacksonConverter;
public Config(MappingJackson2HttpMessageConverter jacksonConverter) {
this.jacksonConverter = jacksonConverter;
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, jacksonConverter);
}
}
BUT in the RestTemplate everything is working fine because of the class HttpMessageConverters
Can you provide me some guidance is this bug or a feature?
Comment From: sbrannen
Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use the issue tracker only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.
The above is our standard policy. Having pointed that out, however, I can add the following.
Message converter configuration with the Spring Framework is documented in the reference manual.
Jackson2ObjectMapperBuilderCustomizer
is a Spring Boot feature, not a Spring Framework feature. If you would like more information on that, feel free to use Google or similar search engines.