Hi all, my name is Hubert A. Klein Ikkink. Not a very common name, right? To make things easier I just picked the first letters of my firstname and surname and came up with haki. So there you have it, now I am also known as Mr. Haki or mrhaki for short. You can read more blog postings at www.mrhaki.com. I am a passionate Groovy and Java developer based in Tilburg, The Netherlands. My goal is to write clean, elegant, user-centered and high quality software. You can find me on Google+ and Twitter. Hubert is a DZone MVB and is not an employee of DZone and has posted 151 posts at DZone. You can read more from them at their website. View Full User Profile

Grails Goodness: Injecting Grails Services into Spring Beans

03.07.2013
| 5064 views |
  • submit to reddit

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

 

Published at DZone with permission of Hubert Klein Ikkink, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)