Spring Bean Aliases in Grails

I was looking at the source code of a Spring application recently and saw an applicationContext.xml element that I hadn’t seen before: <alias>. It turns out this has been around for quite a while, since v1.2 (2005). It sure would have been convenient several months ago.

My first Grails app was a Live Chat app for tech support. I used Comet, so I needed to access Grails beans from Java classes. I did this by having my Services implement an interface, and used that as the type for the Spring bean dependency injection.

But the problem with that was that in Grails you don’t get to choose the bean names of artifacts – there’s a strict convention, so a Service named ChatService is registered as chatService. But the convention I’ve always used is to name my interface ChatService and name the implementation class ChatServiceImpl. But then the Spring bean name would be chatServiceImpl.

In a regular Spring app I’d implicitly alias when I added the bean element to the applicationContext.xml file, e.g.

<bean id='chatService' class='com.foo.bar.ChatServiceImpl' />

So instead I chose an option that I really dislike – I named the interface IChatService and the Grails Service ChatService.

But with the <alias> tag, I should be able to do what I want – name the interface ChatService and the Grails Service ChatServiceImpl, and add

<alias name='chatServiceImpl' alias='chatService' />

to resources.xml. The original bean name will still be there, but I can use the more natural bean name for dependency injection.

This doesn’t cause an error, but it doesn’t work either. I spent some time in a debugger and the alias is registered, but the application context that’s available when the app is running is different from the one that the alias was added to.

But it turns out that you can add programatically add aliases at any time, so I added the alias call to BootStrap.groovy:

class BootStrap {

  def grailsApplication

  def init = { servletContext ->
    grailsApplication.mainContext.registerAlias('chatServiceImpl', 'chatService')
  }

  def destroy = {}
}

and now I can use the chatService alias as the bean name.


I noticed though that since aliases are stored in a Map and not directly in the bean registry, that ctx.getBeanDefinitionNames() only returns ‘real’ bean names and no aliases. But it turns out that it’s pretty simple to get all bean names and aliases:

def allNames = [] as Set
ctx.beanDefinitionNames.each { name ->
    allNames << name
    ctx.getAliases(name).each { alias -> allNames << alias }
}

10 Responses to “Spring Bean Aliases in Grails”

  1. Nick says:

    Hi

    I have an alias in my grails resources.xml which defines an alias for Spring security like this.

    There’s an issue in Jira http://jira.codehaus.org/browse/GRAILS-2222 related to aliases not working.

    I tried your method of defining the alias in the bootstrap.groovy but this hasn’t helped.

    Does the code in bootstrap.groovy get executed before or after the beans in resources.xml get processed?

    Nick

  2. Nick says:

    Hi

    Do you know if it’s possible to define an alias in the reosurces.groovy file?

    Nick

  3. Burt says:

    I was playing with this recently but found that its usefulness is limited. You can’t define aliases in resources.groovy – the bean builder doesn’t support them (although it’d be simple to fix). And although they’re valid in resources.xml, the app ctx built there is copied into a new one, but aliases are skipped – only beans are copied.

    BootStrap.groovy runs after the ctx is built, so for singletons (e.g. services) the alias definition is too late. It only really works for prototype beans like controllers, etc.

  4. Nick says:

    Hi

    I’m using Spring security and need to define an alias for the authentication manager in the resources.xml like this:

    This Jira issue seems to describe the problem http://jira.codehaus.org/browse/GRAILS-2222

    I tried your idea of using the BootStrap class to define the above alias but it didn’t work for me. The Spring security entry point filter that complains that it can’t find a bean called ‘authenticationManager’

    Any ideas?

    Nick

  5. Burt says:

    Are you using the Acegi/SpringSecurity plugin or doing it yourself in resources.xml? I think you could put the bean definitions in the parent context in web-app/WEB-INF/applicationContext.xml if you need aliases to work, or wait for 1.1 beta 3.

  6. Nick says:

    Hi Burt,

    We’re using Spring security with some custom NTLM classes / config.

    You’re correct it does work in the web-app/WEB-INF/applicationContext.xml but I was hoping to produce a plugin to wrap up some of our organisation wide security configuration for the other developers to use. Hence I was trying to use the Grails Spring extension point.

    I’ve decided to wait for Grails 1.1 to get a clean solution. Until then I’ll have to drop it in the main Grails app context.

    Thanks for your help and quick responses.

    Nick

  7. Nick says:

    Hi

    Just to confirm that Grail 1.1 has fixed the alias problems mentioned above.

    Nick

  8. Ted Naleid says:

    Thanks! I just had a use for getting all of the bean names and had forgotten about aliases.

    Here’s another way to collect the list:

    def ctx = grailsApplication.mainContext
    def names = ctx.beanDefinitionNames.collect { [ it, ctx.getAliases( it )] }.flatten()

  9. Jason Stell says:

    In case anyone runs across this posting looking for a solution to creating bean aliases in more recent Grails versions (e.g., 1.3.7), in resources.groovy, you can do:

    springConfig.addAlias(‘aliasName’,’beanName’)

  10. […] test for example. This post is based on the presentation Under the hood: Using Spring in Grails and blog post by Burt […]

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.