How to configure MappingJacksonHttpMessageConverter while using spring annotation-based configuration?
Use the WebMvcConfigurer.configureMessageConverters()
method:
Configure the HttpMessageConverters to use [...] If no message converters are added to the list, default converters are added instead.
With @Configuration
you have:
@Configuration
class MvcConf extends WebMvcConfigurationSupport {
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(converter());
addDefaultHttpMessageConverters(converters);
}
@Bean
MappingJacksonHttpMessageConverter converter() {
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter()
//do your customizations here...
return converter;
}
}
Call to addDefaultHttpMessageConverters()
is required because the defaults are not applied when using custom converters.
IMPORTANT NOTE You must remove @EnableWebMvc
for your converters to be configured if you extend WebMvcConfigurationSupport.
How to return serialized object using MappingJackson2HttpMessageConverter
I solved my issue thanks to this answer
https://stackoverflow.com/a/10650452/2010246
A
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
}
Will not work just like that even if I am overriding this method in AbstractDispatcherServletInitializer
Instead of that I had to create separate class for MVC configuration
package configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.util.List;
@Configuration
public class Mvc extends WebMvcConfigurationSupport {
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(converter());
addDefaultHttpMessageConverters(converters);
}
@Bean
MappingJackson2HttpMessageConverter converter() {
return new MappingJackson2HttpMessageConverter();
}
}
Now it loads correctly and I can simply return the class like I wanted to
I guess the core problem was there were no class that is annotated as @Configuration
and extends the WebMvcConfigurationSupport
parent
How can we configure the internal Jackson mapper when using RestTemplate?
The default RestTemplate
constructor registers a set of HttpMessageConverter
s:
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
this.messageConverters.add(new ResourceHttpMessageConverter());
this.messageConverters.add(new SourceHttpMessageConverter());
this.messageConverters.add(new XmlAwareFormHttpMessageConverter());
if (jaxb2Present) {
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jacksonPresent) {
this.messageConverters.add(new MappingJacksonHttpMessageConverter());
}
if (romePresent) {
this.messageConverters.add(new AtomFeedHttpMessageConverter());
this.messageConverters.add(new RssChannelHttpMessageConverter());
}
The MappingJacksonHttpMessageConverter
in turns, creates ObjectMapper
instance directly. You can either find this converter and replace ObjectMapper
or register a new one before it. This should work:
@Bean
public RestOperations restOperations() {
RestTemplate rest = new RestTemplate();
//this is crucial!
rest.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
return rest;
}
@Bean
public MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter() {
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
converter.setObjectMapper(myObjectMapper());
return converter;
}
@Bean
public ObjectMapper myObjectMapper() {
//your custom ObjectMapper here
}
In XML it is something along these lines:
<bean id="restOperations" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<util:list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="customObjectMapper"/>
</bean>
</util:list>
</property>
</bean>
<bean id="customObjectMapper" class="org.codehaus.jackson.map.ObjectMapper"/>
Note that the transition isn't really 1:1 - I have to explicitly create messageConverters
list in XML while with @Configuration
approach I could reference existing one and simply modify it. But this should work.
How to customize Jackson in Spring MVC (not Spring Boot) application
Ok, yes, this works as long as it's combined with @EnableWebMvc
rather than <mvc:annotation-driven/>
:
@EnableWebMvc
@Configuration
public class CustomWebConfiguration extends WebMvcConfigurerAdapter {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
((MappingJackson2HttpMessageConverter) converter).getObjectMapper().
enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
break;
}
}
}
}
Spring, Jackson and Customization (e.g. CustomDeserializer)
You don't say how you're using Jackson in Spring, so I'll assume you're using it through <mvc:annotation-driven/>
and the @RequestBody
and/or @ResponseBody
annotations.
One of the things that <mvc:annotation-driven/>
does is to register a AnnotationMethodHandlerAdapter
bean which comes with a number of pre-configured HttpMessageConverter
beans, including MappingJacksonHttpMessageConverter
, which handles marshalling to and from Jackson-annotated model classes.
Now MappingJacksonHttpMessageConverter
has a setObjectMapper()
method, which allows you to override the default ObjectMapper
. But since MappingJacksonHttpMessageConverter
is created behind the scenes by <mvc:annotation-driven/>
, you can't get to it.
However, <mvc:annotation-driven/>
is just a convenient short-cut. It's just as a valid to declare your own AnnotationMethodHandlerAdapter
bean, injecting into it your own MappingJacksonHttpMessageConverter
bean (via the messageConverters
property), and injecting your own customized ObjectMapper
into that.
You then have the problem of how to build a custom ObjectMapper
, since it's not a very Spring-friendly class. I suggest writing your own simple implementation of FactoryBean
.
So you'd end up with something like this:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper">
<bean class="com.x.MyObjectMapperFactoryBean"/>
</property>
</bean>
</property>
</bean>
Configuring ObjectMapper in Spring
Using Spring Boot (1.2.4) and Jackson (2.4.6) the following annotation based configuration worked for me.
@Configuration
public class JacksonConfiguration {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
return mapper;
}
}
Spring web-app annotation driven - How to configure? (Best Practice)
There is nothing wrong with this approach. Folks prefer it this way. So, go with it, I would say.
Related Topics
Can an Interface Extend Multiple Interfaces in Java
How to Convert Timestamp to Date in Java
How to Shutdown an Executorservice
Java - How to Create New Entry (Key, Value)
Best Practice for Passing Many Arguments to Method
JPA & Criteria API - Select Only Specific Columns
Java.Net.Connectexception :Connection Timed Out: Connect
Soap Request to Webservice with Java
Could Not Serialize Object Cause of Hibernateproxy
How to Use the Unsigned Integer in Java 8 and Java 9
Javafx: "Toolkit" Not Initialized When Trying to Play an Mp3 File Through Mediaplayer Class
Apache Commons Equals/Hashcode Builder
Capturing Browser Logs with Selenium Webdriver Using Java
Spring Security 5:There Is No Passwordencoder Mapped for the Id "Null"