Grails - Java-Based Configuration
Spring 3.0 introduced an interesting alternative to XML file-based Spring container configuration. After Spring 2.5 already introduced the annotation-based configuration, it added a new way to configure the Spring bean container: via java-based configuration (the SpringConfig project was taken included in the Spring framework).
As its name implies, Java-based Spring container configuration is about using Java code instead of XML or annotations to configure Spring beans. This way reminds of Google Guice, a dependency injection framework solely using Java code to setup the dependency injection components. In Spring, the
org.springframework.context.annotation package holds the following annotations that can be used as an alternative to XML files to annotate certain classes as Spring context configuration classes:
@Configurationclass indicates that a class is defining multiple methods creating Spring-managed beans. The
@Configurationclass needs to be found by the annotation processing configuration. We will have a look how that can be configured in a Grails application.
@Beanannotation is mainly applied on methods (although it can be applied on annotation types too). It indicates that a method returns a bean manager by the Spring application container. The default strategy for the bean name is to use the name of the bean generating method.
@ComponentScanannotation can be applied on
@Configuationclasses to configure component scanning for certain Java packages or classes.
@DependsOnannotation can be used to indicate that a bean depends on the creation of other beans. It defines a happens-before relationship in terms of the container-managed order of bean creations.
@Importannotation can be used to import
@Configurationclasses into the annotated class. It resembles the
@ImportResourceannotation can be used to import bean definitions into the current
@Lazyanntotation indicates a bean has to be created by the Spring container in a lazy manner.
@Profileannotation can be used to annotate
@Configurationclasses for certain profiles. The current profile can be set by using a VM argument or programatically by calling the
@PropertySourceadds property files to the current Spring environment.
@Scopeannotation indicates the bean scope the bean is created in.
Now let’s have a look at how Java-based Spring configuration can be used in a Grails application.
Enabling Java-Based Configs
Let’s assume we have a package
my.app.config that holds all configuration classes. In a Grails application we need to add this packacke in
Config.groovy to the
grails.spring.bean.packages bean scanning path list.
Voilà, now we can use the annotations described above inside the
my.app.config package. The classes can either be implemented as Groovy or Java classes.
The Java-based Spring configuration can even be used in a mixed-mode: there can still be a
resources.groovy or a
resources.xml or more Spring configuration files in the
grails-app/conf/spring directory, the Spring bean container will merge and resolve the bean definitions from the various sources.
The Spring Reactor project comes with a pretty neat
AsyncTaskExecutor implementation that uses the LMAX Disruptor library under the hoods. If we wanted to use the
reactor.spring.core.task.WorkQueueAsyncTaskExecutor from Reactors Spring module, we can do so by defining a Java-based bean configuration.
In the case of the Reactor project, we’re already provided with a pre-defined configuration annotation from the Reactor project that we have to use additionally on our
@Configuration class: the
@EnableRector annotation uses the
@Import annotation to import a default configuration into our
ReactorBeanDefinitionRegistrar uses another cool feature of the Java-based Spring configuration. It implements the
o.s.context.annotation.ImportBeanDefinitionRegistrar interface to register beans in the current application context if not already defined by the user configuration.
ImportBeanDefinitionRegistrar implementation can be used along
@Configuration classes as annotation parameters for the
@Import annotation in our configuration class:
To add a
WorkQueueAsyncTaskExecutor bean to this configuration we simply have to provide a
@Bean annotated method:
Since the method is named
taskExecutor our bean has the same name. And of course, we could use arbitrary Java code to initialize our bean. Once defined, we can refer to
taskExecutor in every configuration artefact of our application, let it be
resources.xml or any other configuration files.
Please don’t confuse the
Environment parameter with the
org.springframework.core.env.Environment interface, the parameter is of type
reactor.core.Environment and is injected automatically, after being created by the
If we have a look at our code example above, we could decided to move all the builder method arguments to our
app.properties file. We can use the
@PropertySource configuration annotation to include this file in our current configuration:
As can be seen above, the
queue.backlog settings in the
app.properties file can be accessed via the
org.springframework.core.env.Environment bean. This bean needs to be autowired in our configuration to access the message resources. This shows another impressive feature of Spring’s Java-based configuration:
@Configuration classes are themselves treated as beans. This means we can use for example
@Autowired to inject beans into our
@Configuration class. The Spring documentation shows an even better example:
We can even auto-wire
@Configuration classes themselves:
These examples show that the Java-based configuration approach can provide us with much more modularity and reusability than using (the already mighty) Spring bean Groovy DSL which is, by the way, part of Spring 4. As every Grails application is a Spring application, we can use this approach to better structure application provided beans.
Spring 3 introduced another configuration approach besides the XML configuration files and annotation-based configuration: the so-called Java-based configuration. Spring provides a buch of annotations enabling to define beans in pure Java/Groovy code with even better modularity and reusability as can be found in Grails Spring DSL files. This article is an introduction to Java-based configuration and shows how to enable the mechanism in Grails applications.