Home > front end >  Elasticsearch Java Client Jackson Mapper pollutes Spring Jackson Mapper
Elasticsearch Java Client Jackson Mapper pollutes Spring Jackson Mapper

Time:12-28

I'm updating my Spring Boot project to version 3.0.0 of Spring Boot. One important dependecy is the Spring Data Elastic Repository. I included the starter dependency:

implementation("org.springframework.boot:spring-boot-starter-data-elasticsearch")

After updating the dependecies, my unit test are failing, because no more null values are provided by the web controller. I tried to change the behavior by using the property inclusion configuration:

spring:
  jackson:
    default-property-inclusion: always

This did not help. I debugged the code party and it seems like the new Elastic Java Client has it's own Jackson Mapper config, which sets the global config to 'NON_NULL'.

package co.elastic.clients.json.jackson;

...

public class JacksonJsonpMapper extends JsonpMapperBase {

    private final JacksonJsonProvider provider;
    private final ObjectMapper objectMapper;

   ...

    public JacksonJsonpMapper(ObjectMapper objectMapper) {
        this(
            objectMapper
                .configure(SerializationFeature.INDENT_OUTPUT, false)
                .setSerializationInclusion(JsonInclude.Include.NON_NULL),
            // Creating the json factory from the mapper ensures it will be returned by JsonParser.getCodec()
            new JacksonJsonProvider(objectMapper.getFactory())
        );
    }

...

Does anybody know how to solve this issue?

CodePudding user response:

I found a soultion for the problem. Spring Boot has an autoconfiguration for the Elastic Jackson mapper. This autocofiguration uses the same ObjectMapper as the web controller:

´´´

package org.springframework.boot.autoconfigure.elasticsearch;

...

/**
 * Configurations for import into {@link ElasticsearchClientAutoConfiguration}.
 *
 * @author Andy Wilkinson
 */
class ElasticsearchClientConfigurations {

@ConditionalOnMissingBean(JsonpMapper.class)
@ConditionalOnBean(ObjectMapper.class)
@Configuration(proxyBeanMethods = false)
static class JacksonJsonpMapperConfiguration {

    @Bean
    JacksonJsonpMapper jacksonJsonpMapper(ObjectMapper objectMapper) {
        return new JacksonJsonpMapper(objectMapper);
    }

}

...

´´´

It is possible to override this Bean to copy the ObjectMapper instance and create an own ObjectMapper for the Elastic client:

´´´

@Configuration
internal class CustomJacksonJsonpMapperConfiguration {
@Bean
fun jacksonJsonpMapper(objectMapper: ObjectMapper): JacksonJsonpMapper {

    return JacksonJsonpMapper(objectMapper.copy())
}
}

´´´

  • Related