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
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.