Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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) { }
}
like image 915
David Tinker Avatar asked May 21 '12 07:05

David Tinker


People also ask

What are Grails services?

Services in Grails are the place to put the majority of the logic in your application, leaving controllers responsible for handling request flow with redirects and so on.

Does Grails use spring?

Perhaps most importantly, Grails uses Spring's transaction management. And as I've already alluded to, many plugins make use of the Spring integration provided with Java libraries. So, a Grails application is really a Spring application.


1 Answers

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'
  }
}
like image 125
Artur Nowak Avatar answered Sep 28 '22 08:09

Artur Nowak