This Bean builder in Grails aims to provide a simplified way of wiring together dependencies that uses Spring at its core.

In addition, Spring's regular way of configuration (via XML) is essentially static and very difficult to modify and configure at runtime other than programmatic XML creation which is both error prone and verbose. Grails' api:grails.spring.BeanBuilder changes all that by making it possible to programmatically wire together components at runtime thus allowing you to adapt the logic based on system properties or environment variables.

This enables the code to adapt to its environment and avoids unnecessary duplication of code (having different Spring configs for test, development and production environments)

The BeanBuilder class

Grails provides a api:grails.spring.BeanBuilder class that uses dynamic Groovy to construct bean definitions. The basics are as follows:

import org.apache.commons.dbcp.BasicDataSource
import org.codehaus.groovy.grails.orm.hibernate.ConfigurableLocalSessionFactoryBean;
import org.springframework.context.ApplicationContext;

def bb = new grails.spring.BeanBuilder()

bb.beans { dataSource(BasicDataSource) { driverClassName = "org.hsqldb.jdbcDriver" url = "jdbc:hsqldb:mem:grailsDB" username = "sa" password = "" } sessionFactory(ConfigurableLocalSessionFactoryBean) { dataSource = dataSource hibernateProperties = [ "hibernate.hbm2ddl.auto":"create-drop", "hibernate.show_sql":true ] } }

ApplicationContext appContext = bb.createApplicationContext()

Within plug-ins and the grails-app/conf/spring/resources.groovy file you don't need to create a new instance of BeanBuilder. Instead the DSL is implicitly available inside the doWithSpring and beans blocks respectively.

The above example shows how you would configure Hibernate with an appropriate data source with the BeanBuilder class.

Essentially, each method call (in this case dataSource and sessionFactory calls) map to the name of the bean in Spring. The first argument to the method is the bean's class, whilst the last argument is a block. Within the body of the block you can set properties on the bean using standard Groovy syntax

Bean references are resolved automatically be using the name of the bean. This can be seen in the example above with the way the sessionFactory bean resolves the dataSource reference.

Certain special properties related to bean management can also be set by the builder, as seen in the following code:

sessionFactory(ConfigurableLocalSessionFactoryBean) { bean ->
    bean.autowire = 'byName'       // Autowiring behaviour. The other option is 'byType'. [autowire]
    bean.initMethod = 'init'       // Sets the initialisation method to 'init'. [init-method]
    bean.destroyMethod = 'destroy' // Sets the destruction method to 'destroy'. [destroy-method]
    bean.scope = 'request'         // Sets the scope of the bean. [scope]
    dataSource = dataSource
    hibernateProperties = [ "hibernate.hbm2ddl.auto":"create-drop",
                            "hibernate.show_sql":true  ]
}

The strings in square brackets are the names of the equivalent bean attributes in Spring's XML definition.

Using BeanBuilder with Spring MVC

If you want to take advantage of BeanBuilder in a regular Spring MVC application you need to make sure the grails-spring-<version>.jar file is in your classpath. Once that is done you can need to set the following <context-param> values in your /WEB-INF/web.xml file:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.groovy</param-value>
</context-param>
<context-param>
    <param-name>contextClass</param-name>
    <param-value>org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext</param-value>
</context-param>

With that done you can then create a /WEB-INF/applicationContext.groovy file that does the rest:

beans {
	dataSource(org.apache.commons.dbcp.BasicDataSource) {
        driverClassName = "org.hsqldb.jdbcDriver"
        url = "jdbc:hsqldb:mem:grailsDB"
        username = "sa"
        password = ""
    }
}

Loading Bean Definitions from the File System

You can use the BeanBuilder class to load external Groovy scripts that define beans using the same path matching syntax defined here. Example:

def bb = new BeanBuilder()
bb.loadBeans("classpath:*SpringBeans.groovy")

def applicationContext = bb.createApplicationContext()

Here the BeanBuilder will load all Groovy files on the classpath ending with SpringBeans.groovy and parse them into bean definitions. An example script can be seen below:

beans {
    dataSource(BasicDataSource) {
        driverClassName = "org.hsqldb.jdbcDriver"
        url = "jdbc:hsqldb:mem:grailsDB"
        username = "sa"
        password = ""
    }
    sessionFactory(ConfigurableLocalSessionFactoryBean) {
        dataSource = dataSource
        hibernateProperties = [ "hibernate.hbm2ddl.auto":"create-drop",
                                "hibernate.show_sql":true  ]
    }
}

Adding Variables to the Binding (Context)

If you're loading beans from a script you can set the binding to use by creating a Groovy Binding object:

def binding = new Binding()
binding.foo = "bar"

def bb = new BeanBuilder() bb.binding = binding bb.loadBeans("classpath:*SpringBeans.groovy")

def ctx = bb.createApplicationContext()