Question

What is the best way to configure a Grails service with environment specific values? I believe there are two options:

  1. access grailsApplication values from within the service class or
  2. configure the service bean in a beans closure in Config.groovy or resources.groovy.

I've seen a couple of posts on stackoverflow and other places that show how to do #1 (accessing grailsApplication in the service). One such post is: Inject grails application configuration into service.

However, I think this creates an unnecessary coupling of the service to Grails. Isn't this similar to accessing Spring's applicationContext in a pojo rather than configuring/injecting the values? Also, I've not had any luck getting this to work in a unit test of the service class as of yet.

Two books have examples of injecting the properties (approach #2). The book The Definitive Guide to Grails 2, chapter 10, section entitled "Services in Action" shows how to do this, but without an environment specific value. The book Groovy and Grails Recipes, section 16-2 also shows an example using resources.groovy, but I've not been able to get it to work either yet.

The following blog post also has a nice example, but not environment specific: http://ldaley.com/post/1253952347/getting-more-out-of-property-override-configuration. Chapter 15 of the Grails Reference is consistent with these examples as well and shows how to set the properties on a bean on a per environment basis.

However, none of the examples of either approach give any opinion or rational for doing it one way or another. Is there really no pros and cons to either approach? Wouldn't the injection approach be easier to unit test and more consistent with the spring way of doing things?

Nathan

Était-ce utile?

La solution

I'd say use whichever you're more comfortable with. I tend to go with accessing grailsApplication.config directly from the service, because that lets you make the configuration more "semantic" (for want of a better word) in the sense that you can name the configuration options after what they do, rather than which bean they control. And if two (or more) different beans need to know the site administrator's email address (for example) then they can both read grailsApplication.config.myapp.admin.email rather than my having to configure beans.monitorService.destinationEmail and beans.userService.fromEmail separately.

In unit tests you'd have to mock the grailsApplication config anyway, so it's no big deal filling in test values for the config options your services need to read.

Autres conseils

There's a difference in the concept of services (classes that exists in the service folder) and Spring Beans defined in resources.groovy.

To services, Grails already setup transactions:

Services are typically involved with coordinating logic between domain classes, and hence often involved with persistence that spans large operations. Given the nature of services, they frequently require transactional behaviour. You can use programmatic transactions with the withTransaction method, however this is repetitive and doesn't fully leverage the power of Spring's underlying transaction abstraction.

The Spring Beans that you declared aren't transactional by default.

"However, I think this creates an unnecessary coupling of the service to Grails"

Since Grails services differ from Spring Beans I don't see a problem using approach #1.

For Unit Tests you need to manually wire up you service instance. Example:

class MyService {
  def grailsApplication
}

class MyServiceTests {
  MyService getServiceInstance() {
    MyService myService = new MyService()
    myService.grailsApplication = grailsApplication //static attribute in unit tests
    return myService
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top