Avoiding a common spring annotation configuration mistake

Making sure spring singletons are indeed singletons..

Neil Buesing

With annotated based configurations, I have seen this common mistake which will cause multiple instances of a singleton being created. When you have two beans and one bean needs the other, it is easy to construct the two beans as follows:

public class Config {
  @Bean
  public MappingJackson2HttpMessageConverter converter() {
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(objectMapper());
    return converter;
  }  

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

If you are referencing this configuration through an Import, like the following, two instances of the JacksonObjectMapper to be created.

@ComponentScan("com.objectpartners.buesing")
@Import(Config.class)
public class ApplicationConfiguration {
}

Once when spring calls objectMapper() and once when spring calls converter(). Instead, method arguments should be used when one bean needs to reference another.

public class Config {
  @Bean
  public MappingJackson2HttpMessageConverter converter(final ObjectMapper objectMapper) {
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(objectMapper);
    return converter;
  }  

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

Spring will construct objectMapper and provide that single instance when it calls converter to create the other bean. Furthermore, if there are two ObjectMapper instances, you can qualify which ObjectMapper is needed.

public class Config {
  @Bean
  public MappingJackson2HttpMessageConverter converter(@Qualifier("jsonMapper") final ObjectMapper objectMapper) {
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(objectMapper);
    return converter;
  }  

  @Bean
  public ObjectMapper jsonMapper() {
    return new JacksonObjectMapper();
  }  

  @Bean
  public ObjectMapper xmlMapper() {
    return new XmlMapper();
  }
}

Most of this is avoid when beans are auto-scanned and references are managed through @Autowire or @Resource. But when that is not possible, never call a @Bean method directly.

Update: Now if all of your configurations are annotated with @Config spring will create only a single instance of jsonMapper. This is something I didn’t notice until after I wrote this; thanks to Jeff Sheets and Aaron Hanson for helping me uncover this subtle difference. It is good to know how spring works, how it creates beans, and the differences between how configuration is done.

Share this Post

Related Blog Posts

JVM

Asynchronous Programming in Grails 3

October 22nd, 2015

Grails has had support for asynchronous programming for some time now but it seems to have become more well-defined in Grails 3. It has Promises, Events in GORM

Mike Hostetler
JVM

JOOQ Worthy

October 1st, 2015

A discussion about the JOOQ DSL

Object Partners
JVM

Tweaking Column Types in Grails

September 29th, 2015

Changing Hibernate mappings in a Grails application

Mike Hostetler

About the author

Neil Buesing

Sr. Consultant

Neil has more than twenty-two years of Object oriented development experience, with fifteen years of experience with Java/J2EE application development. He has successfully delivered in the role of architect and as lead developer.