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 167 posts at DZone. You can read more from them at their website. View Full User Profile

Grails Goodness: Using Spring Bean Aliases

03.14.2013
| 2948 views |
  • submit to reddit

Grails uses dependency injection by convention. This means if we have a property messageService then a Spring bean or Grails service with the name messageService is injected. Grails will automatically use the name of a Grails service as the name of the Spring bean definition (applying Java Bean conventions and start with a lowercase). So if we have a Grails service MessageService the resulting Spring bean definition will have the name messageService. Any Spring bean that wants to use the service only has to create the property messageService and dependency injection by convention makes sure the Grails service is injected.

We can change the Spring bean definition name using Spring bean aliases. With an alias we provide an extra name for a Spring bean. In our Grails application we can add an alias in the grails-app/conf/spring/resources.groovy file. In the following sample we add the alias message for the MessageService Grails service:

// File: grails-app/conf/spring/resources.groovy
beans = {
    springConfig.addAlias 'message', 'messageService'
}

We can use aliases to provide different service implementations and conditionally (for example based on environment) activate an implementation. The class that wants to use the service only has to use the dependency injection by convention and define a property with a name. In the resources.groovy file we can then set the alias with the correct name to the implementation we need.

Let's see how this works with an example. Suppose we have a controller that depends on a service with the name messageService. We use an interface to define the type of the service in our sample, but that is not necessary, we could do the same thing without interfaces:

//File: grails-app/controllers/com/mrhaki/grails/spring/MessageController.groovy
package com.mrhaki.grails.spring

class MessageController {

    MessageService messageService

    def index() {
        render messageService.message
    }
}

Let's create the interface, which is very simple in our sample:

// File: src/groovy/com/mrhaki/grails/spring/MessageService.groovy
package com.mrhaki.grails.spring

interface MessageService {

    String getMessage()

}

Next we create two Grails services that implement the MessageService interface: MessageRemoteService and MessageLocalService:

// File: grails-app/services/com/mrhaki/grails/spring/MessageRemoteService.groovy
package com.mrhaki.grails.spring

class MessageRemoteService implements MessageService {

    String getMessage() {
        'Remote message'
    }

}
// File: grails-app/services/com/mrhaki/grails/spring/MessageLocalService.groovy
package com.mrhaki.grails.spring

class MessageLocalService implements MessageService {

    String getMessage() {
        'Local message'
    }

}

If we run the Grails application we don't have a Spring bean definition with the name messageService, but we do have two bean definitions with the names messageRemoteService and messageLocalService. To make sure the MessageController will have the correct service injected we need to add aliases to resources.groovy. By default we want to use the messageRemoteService as messageService, but during development we want to use messageLocalService:

// File: grails-app/conf/spring/resources.groovy
import grails.util.Environment

beans = {
    // Default we use the messageRemoteService as implementation of MessageService
    springConfig.addAlias 'messageService', 'messageRemoteService'

    Environment.executeForCurrentEnvironment {
        development {
            // In development we use messageLocalService as implementation
            // of MessageService.
            springConfig.addAlias 'messageService', 'messageLocalService'
        }
    }
}

So with aliases it is easy to swap service implementations, based on some condition. This can be very useful if we have a service and want to use a mocked or simplified version during development and test for example. This post is based on the presentation Under the hood: Using Spring in Grails and blog post by Burt Beckwith

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