Spring - Be Careful Overriding Conditional Bean

Ömer Kurular
2 min readJan 26, 2022

--

In Spring, we may need some 3rd party beans in our applications like object mappers, password encoders etc. To use them, we create those beans in our configuration class as follows.

@Configuration
public class BeanConfig {

@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}

Above one is actually quite normal and innocent bean definition. Now, see the example below.

Before getting in, you better see these if you do not know the difference.

SNAKE_CASE -> sample_field_name
CAMEL_CASE -> sampleFieldName

Suppose, you are parsing a json file and mapping it to Java object. Your JSON file contains fields names written in SNAKE_CASE format, like

{
"cars":[
{
"brand":"AUDI",
"production_location":"GERMANY",
"designed_by":"someone"
}
]
}

So, you are creating objectMapper bean with SNAKE_CASE configuration as follows to be able to parse the file.

@Configuration
public class BeanConfig {

@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
return new ObjectMapper();
}
}

We are telling object mapper to use SNAKE_CASE instead of default CAMEL_CASE.

Now, you can parse your JSON file that is using SNAKE_CASE and map it to associated class. After this, you will make a POST request to another service in your environment. What is going to happen? Your object mapper will serialize the request body into json using SNAKE_CASE format. But, other service uses default objectMapper configuration and will not be able to deserialize it as it uses another naming strategy which is CAMEL_CASE. So, other service will not process your request as it is not able to deserialize the request body you sent and you start spending a lot of time to find out what is causing this.

Why did object mapper bean we created affect the rest serialization logic?

Spring auto configuration libraries mostly define beans as conditional using annotations like ones below. So, it gives you flexibility to configure beans according to your needs like the situation where we need to use another naming format for json parsing.

@ConditionalOnMissingBean
@ConditionalOnProperty
@ConditionalOnExpression
@ConditionalOnBean
@ConditionalOnClass

And for our scenario, Spring defines ObjectMapper bean conditional on missing bean as follows.

@ConditionalOnMissingBean
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}

This means that if you create your own object mapper bean as we did in the example above, you use that. Otherwise, it will use the default one.

When we create object mapper bean in our example, it replaces the default object mapper bean so our object mapper configuration is used across the context and the problem we talked about above occurs.

As a result, we must be careful when doing such thing and be careful if the bean you create redefines conditionally configured one.

I hope you liked the article and if you want to read articles about Java and Spring, you can follow me.

--

--

Ömer Kurular

I am Ömer and currently working as a full-time software engineer. I will share my knowledge with you I gained through years of professional and self working.