What is the best way to configure a Grails service with environment specific values? I believe there are two options:
access grailsApplication values from within the service class or
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
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.
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
}
}
Related
Imagine you inject a single database connection to a handful of service classes. They now share what's essentially a global mutable state. How do DI frameworks deal with this? Do they:
Freeze the dependency before injection?
Only share immutable objects?
Wrap each dependency in a decorator to only provide exactly what's dependent on?
I tried searching for this and am a bit surprised I didn't find much. Feel free to provide links.
Related: https://en.wikipedia.org/wiki/Principle_of_least_privilege
Most DI containers provide the feature of registering a dependency within a Lifetime. For instance in .net core DI you can register a service with three different lifetimes:
Singleton: There is only one single instance. All the consumers of that service will use that instance. If one consumer changes the state of that dependency, all the other consumers will see that change.
Scoped: There is one instance per scope, where a scope is a web request. If a consumer changes the state of a scoped service, all the other consumers that will run in the same web request will see the change.
Transient: Each consumer uses a different instance of the service.
Always in .net core, the DBContext is (by default) added as a scoped service, this means that in the same web request all the consumers will use the same instance and this is useful when you need to run a transaction across different consumers (or better across different repositories).
I have an authentication_service, which is required in all the services throughout the application. So, I don't want to inject this service every time (DRY). Is there a way, I can have this common service accessible from all the modules, with injecting via factory?
Thanks!!
You can use service initializers, great article with examples and more important with explained consequences:
http://www.masterzendframework.com/zend-framework/easy-setter-injection-in-zend-framework-2
I suggest you create a base service which defines all the common service requirements, such as your $authService property and the constructor that sets it. Then have your services extend that. Avoid reimplementing the constructor and property in every service to stay DRY, but injecting it via every service's factory is expected.
What actually happens when we do def someService? Does the service code get linked to the controller code?
Grails uses spring IOC, your controllers and services are managed as spring beans, when you define a service inside a controller, spring will inject the service inside the controller, code does not get linked in anyway, just reference to service will be set. Though its not a much expensive operation, you would not want to define service dependencies that are not used to keep the code clean
I think under the hood it's the same process as Spring's #Autowired annotation, so you pay a bit of a performance penalty on start up but I don't think it's significant.
There's another stackoverflow question on the subject here.
Does the service code get linked to the controller code?
That does not make sense.
Actually services in grails are singleton by default.So if you inject a Service by def serviceName it wont create a new service object but a reference to same old service object.
So its not expensive of course.
But if in a service there is a property static session="prototype" or some non-singleton like this.Then it is expensive .
I have created one service in my grails application. in that service 25 methods are there.
Some methods are for fetching data and passes to controller and some methods are for applying business logic and others are for database data CRUD operation.
Is it good idea to write multiple methods with different behavior to service?
and Do I have to make service transactional?
and what is the use of default method
def serviceMethod() {
}
?
this method is created when I am creating new Service...
Is it good idea to write multiple methods with different behavior to
service?
Multiple methods in a service is perfectly fine and it makes simply just makes sense if the methods in a service are related to the context.
Take for example a service called springSecurityService. You would expect the methods contained therein to be related to spring security operations. You wouldn't expect to find a sendMail method there.
Do I have to make service transactional?
You should make services transactional if in that service you perform database operation(mostly writes!). When your service is transactional you have the ability to rollback the database operation in case of a failure.
what is the use of default method
The default method is just a place holder. Feel free to edit or delete it :D
Services are transactional by default in Grails - http://grails.org/doc/latest/guide/services.html#declarativeTransactions
The serviceMethod is generated by the CreateService script. It is just an example, so you can delete it if you wish.
You could put all your business logic in services. It is convenient, but note that this is more of an anti-pattern called Anaemic Domain Model
imho, you should try to follow object-oriented principles and put most of your business processes in the domain classes. When there is a complex process involving multiple domain object, then maybe you can put this in a service.
I'm working on a large legacy application using stateless session beans that has recently been migrated from EJB2 to EJB3, and I'd like to use dependency injection. Unfortunately, in a (IMO misguided) attempt to achieve decoupling, all actual business logic lies in "manager" classes to which the session beans forward their calls. Those manager classes then often use other EJBs.
Can I somehow make these manager classes capable of being injected into the EJBs via #Resource and then having the other EJBs injected into them via #EJB?
The application has to run on glassfish 2.1.
(...) all actual business logic lies in "manager" classes to which the session beans forward their calls.
That was a very common pattern with EJB 2.x allowing to unit test the "manager" classes easily, outside the container, without any adherence to the EJB API.
Can I somehow make these manager classes capable of being injected into the EJBs via #Resource and then having the other EJBs injected into them via #EJB?
Not out-of-the-box with Java EE 5. Injection is limited only to first class constructs defined in the Java EE platform, including:
SessionContext object
DataSources object
UserTransaction
EntityManager interface
TimerService interface
Other enterprise beans
Web services
Message queues and topics
Connection factories for resource adaptes
Environment entries limited to String, Character, Byte, Short, Integer, Long, Boolean, Double, and Float.
In Java EE 6, this would be possible using CDI (JSR-199) and the #Inject annotation in EJBs to inject your managers and also in you managers to get EJBs injected.
Maybe you could try to deploy Weld (the RI of JSR-199) as part of your application on GlassFish v2.1. I didn't experiment this myself, so I can't confirm anything. Just in case, maybe have a look at the Chapter 18. Application servers and environments supported by Weld (GlassFish v2.1 hasn't been tested, but it doesn't mean it doesn't work).
Pascal's suggestion about upgrading to GlassFish 3 sounds probably like the most elegant approach ;)
I'd be curious to hear what prevents moving to a more recent version (not saying there can't be a reason, just wondering what the issue is here).