Grails Goodness: Injecting Grails Services into Spring Beans
One of the underlying frameworks of Grails is Spring. A lot of the Grails components are Spring beans and they all live in the Spring application context. Every Grails service we create is also a Spring bean and in this blog post we see how we can inject a Grails service into a Spring bean we have written ourselves. The following code sample shows a simple Grails service we will inject into a Spring bean:
// File: grails-app/services/com/mrhaki/sample/LanguageService.groovy
package com.mrhaki.sample
class LanguageService {
List<String> languages() {
['Groovy', 'Java', 'Clojure', 'Scala']
}
}
We only have one method, languages()
, that returns a list of JVM languages. Next we create a new Groovy class in the src/groovy
directory which will be our Spring bean that will have the LanguageService
injected. We use Spring annotations to make sure our class turns into a Spring bean. With the @Component
we indicate the component as a Spring bean. We use the @Autowired
annotation to inject the Grails service via the constructor:
// File: src/groovy/com/mrhaki/sample/bean/Shorten.groovy
package com.mrhaki.sample.bean
import com.mrhaki.sample.LanguageService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
@Component
class Shorten {
private final LanguageService languageService
@Autowired
Shorten(final LanguageService languageService) {
this.languageService = languageService
}
List<String> firstLetter() {
final List<String> languages = languageService.languages()
languages.collect { it[0] }
}
}
The Shorten
class will use the list of JVM languages from the LanguageService
and return the first letter of each language in the firstLetter()
method. We can instruct Spring to do package scanning and look for Spring beans in for example resources.groovy
, but in Config.groovy
we can also set the property grails.spring.bean.packages
. We define a list of packages for this property and Grails will scan those packages and add any Spring beans to the Spring context. The complete definition in Config.groovy
is now:
...
// packages to include in Spring bean scanning
grails.spring.bean.packages = ['com.mrhaki.sample.bean']
...
With the following integration test we can see the Shorten
class is now a Spring bean and we can invoke the firstLetter()
method that uses the Grails service LanguageService
:
// File: test/integration/com/mrhaki/sample/SpringBeanTests.groovy
package com.mrhaki.sample
import com.mrhaki.sample.bean.Shorten
public class SpringBeansTests extends GroovyTestCase {
Shorten shorten
void testShorten() {
assertEquals(['G', 'J', 'C', 'S'], shorten.firstLetter())
}
}
Written with Grails 2.2.1