David Tinker
David Tinker

Reputation: 9634

How to select a service implementation in a Grails application?

I have several services implementing a common interface and I want to be able to choose one of them to inject into other services when my application starts up.

I have tried referencing the service implementation from resources.groovy as shown below but then Spring makes a new instance of the selected service and doesn't autowire its dependencies.

How can I get this solution to work? Or is there another way?

class MyService {

    Repository repository

    interface Repository {
        void save(...)
    }
}

class MySqlRepositoryService implements MyService.Repository { ... }

class FileRepositoryService implements MyService.Repository { ... }

resources.groovy:

beans = {
    ...
    repository(FileRepositoryService) { }
}

Upvotes: 9

Views: 828

Answers (1)

Artur Nowak
Artur Nowak

Reputation: 5354

It's of course possible to retrieve the reference to service from hand-built factory, but in my opinion, the approach you've taken is the best one. I use it myself, because it gathers all the information on configuration phase of the application in one place, so it's easier to track down which implementation is used.

The pitfall with autowiring that you've encountered can be explained very easily. All the classes put in grails-app/services are automatically configured by Grails as Spring singleton beans with autowiring by name. So the bean definition you've placed in grails-app/conf/resources.groovy creates another bean, but without the defaults imposed by Grails conventions.

The most straightforward solution is to put the implementation in src/groovy to avoid duplication of beans and use the following syntax to turn on the autowiring:

beans = {
  repository(FileRepositoryService) { bean ->
    bean.autowire = 'byName'
  }
}

Upvotes: 3

Related Questions