2. WHY SERVICES
• Image a scenario of a company where employees are assigned tasks based on the nature
of their work. There is a employee Popeye who is the team leader so he has different
responsibilities such as :
• Handle client calls and guide them.
• Generate excel sheets with data for analysis.
• Manage schedule of team members .
• Schedule and look over calls for team members.
As you can see Popeye’s work is too hectic and complicated because all the tasks being
handled by them are of very different nature , he’s more likely to get stressed out and make
mistakes. His errors could cost a lot of money in the long run. Another problem is it's not easy
to replace Popeye as he is too involved in a complicated setup.
Likewise in software, it is not really a great idea to write a class with different responsibilities,
a single class or source file should only be involved in only one nature of task .If there is a lot
of things going on, this will only introduce bugs and problems later as the application will be
very complicated to maintain.
3. WHY NOT JUST CONTROLLER
Consider a controller in Grails .Inside a controller, we can do the following.
• Handle routing logic.
• Invoke GORM operations to manipulate data in database.
• Render text and show it to user.
However, it is not advisable that we do all those things inside a controller. Grails
allows a developers to do all these things together for flexibility, but it should be
avoided. The real purpose of a controller is to deal with the routing login which
means :
• Receive requests from user.
• Invoke the appropriate business login(services)
• Invoke the view to display result
4. DON’T REPEAT YOURSELF(DRY)
These days most of the technologies are following the DRY concept
which follows a strict practice of not having to duplicate code, using a
service layer is you could reuse a business logic in multiple places
without code duplication. Having a single copy of a particular business
logic will make a project shorter (in terms of lines of codes) and easier
to maintain. Changing the business logic will just require a change in
only one particular place.
5. CREATING A SERVICE
- To create a service , you can use create-service command from the root folder of your application.Ex.
grails create-service com.test.Test
The above command would create a TestService in com/test directory path .
- Or you can also create service from your ide.
- Service created would have the following content
package com.test
class TestService{
def serviceMethod(){
}
}
- You can go on adding as many method in the services having same nature of tasks.
6. INJECTING A SERVICE
• To use service methods , you would need to inject the service .
• Services can be injected in a controller , domain , tag libs,Bootstrap or another service.
• To inject a service in a controller
package com.test
class TestController{
def testService
def saveData(){
testService.serviceMethod()
}
}
7. TRANSACTION MANAGEMENT
• Transaction is a very important concept. Hope you are well aware of ACID(Atomicity, Consistency, Isolation, Durability)
properties .
• Usually we wish certain sequence of database changes to be successful. If not possible we want no operation to happen at
all.
• Imagine a code that deducts money from one account (accountFrom.balance = accountFrom.balance - amount), and adds
money to another account (accountTo.balance = accountTo.balance + amount). Imagine if something happened (an
Exception) after deducting from the source account and the destination account was not updated. Money will be lost and
not accounted for. For this type of codes, we want an "all or nothing" behavior. This concept is also called atomicity.
• Since Grails supports transactions, it automatically do these things to us when we declare a service to be transactional:
• If all db operations are successful, reflect the changes to the database (this is also called commit)
• If one db operation result in exception, return to the original state and forget/undo all the previous operations (this is also
called rollback)
• By default all services are transactional, if you don’t want transactional behavior of the service you can get rid of it by
class TestService(){
static transactional=false
}
8. SCOPE
• By default, access to service methods is not synchronized, so nothing prevents concurrent execution of those
methods. In fact, because the service is a singleton and may be used concurrently, you should be very careful
about storing state in a service.
• You You can change this behavior by placing a service in a particular scope. The supported scopes are:
• prototype - A new service is created every time it is injected into another class
• request - A new service will be created per request
• flash - A new service will be created for the current and next request only
• flow - In web flows the service will exist for the scope of the flow
• conversation - In web flows the service will exist for the scope of the conversation. ie a root flow and its sub
flows
• session - A service is created for the scope of a user session
• singleton (default) - Only one instance of the service ever exists
• To enable one of the scopes, add a static scope property to your class whose value is one of the above. Ex
static scope=“session”