Her-Bak
Her-Bak

Reputation: 81

Configuring Jackson for Spring Integration

Another question for the same project once mentioned in this question. We have now developed quite a few routes to serve a REST/JSON web service from a composite back-end.

The endpoint is an <int-http:inbound-gateway> that performs implicit JSON to object from the request and object to JSON for the response. Now we really need to tune Jackson to solve a few issues with the JSON we deliver in the responses. Nothing fancy or unusual: mostly, serve dates as String instead of Timestamps, removing null attributes, registering the JSR-310 module.

For the other modules in the platform, we use Java DSL with a @Configuration class and a bean like this:

@Configuration
public class ControllerConfig {
  @Bean
  @Primary
  public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.setSerializationInclusion(Include.NON_NULL);
    return objectMapper;
  }
}

But it seems to have no effect on Spring Integration. I have also tried Spring Boot configuration:

spring.jackson.default-property-inclusion=NON_NULL

and it does not work either. I read very carefully this thread and my understanding from Artem Bilan's answer is that indeed, Spring Integration does not consider the Spring Boot configuration.

So... I'm feeling stupid: what is the canonical way of configuring Jackson globally for Spring Integration ?

jackson 2.8.7 / spring 4.3.7 / spring boot 1.5.2 / spring integration 4.3.8

Upvotes: 2

Views: 1550

Answers (2)

Her-Bak
Her-Bak

Reputation: 81

A big thank you to @Artem Bilan for answering my question promptly and showing me the way to go (after I fought for two days on my own).

Customizing the HttpMessageConverter is indeed the good direction. The code below is not the finest I've written but it does the job nicely. I have added this stanza to our @Configuration bean:

@Bean
public List<HttpMessageConverter<?>> customMessageConverters() {
  MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
  ObjectMapper objectMapper = new ObjectMapper();
  objectMapper.registerModule(new JavaTimeModule());
  objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
  objectMapper.setSerializationInclusion(Include.NON_NULL);
  jsonConverter.setObjectMapper(objectMapper);

  List<HttpMessageConverter<?>> result = new ArrayList<HttpMessageConverter<?>>();
  result.add(jsonConverter);

  return result;
}

Then, the magic suggested by Artem Bilan works nicely: we have just added

message-converters="customMessageConverters"

to our inbound-gateway.

I hope this helps someone, someday. My apologies for any typo but all this is coded in a bank where posting to StackOverflow is blocked, hence no copy and paste...

Upvotes: 1

Artem Bilan
Artem Bilan

Reputation: 121550

Correct. Spring Integration is a pure Spring Framework extension and it indeed knows nothing about conventional auto-configuration and injections.

So, what you have to do is don not forget to inject your objectMapper whenever it is necessary.

For example for that <int-http:inbound-gateway> you have to inject a proper set of the HttpMessageConverter. For example I see that Spring Boot provides the HttpMessageConverters bean. I believe that MappingJackson2HttpMessageConverter is injected to that one by the JacksonHttpMessageConvertersConfiguration. So, you can use it for your purpose like this:

<int-http:inbound-gateway
         message-converters="#{messageConverters.converters}">

Upvotes: 1

Related Questions