Reputation: 1948
Do Grails Service
s by default have access to the session object? As in being able to do:
session.putSomeValueNeededLater
I am asking because I have the need to store a variable as a result of one service method that another service method(in the same service) might need later and I am trying to avoid doing this via a global variable in the service because I have a feeling that is considered bad design. So I thought the session might be an alternative approach. Thanks.
Edit: In my service I have this situation:
masterMethod() {
call method1()
call method2()
//Check if either method 1 or 2 set some variable that indicates whether method 3 needs to be called.
if (condition == true) { call method3 } // Is it a good idea to store the condition in the session?
}
method 1() { //if some condition, masterMethod() needs to call method 3. Where to store this? In session? }
method 2() { //if some condition, masterMethod() needs to call method 3. Where to store this? In session? }
method 3() {...}
Upvotes: 0
Views: 3640
Reputation: 187499
You can access the session from anywhere in a Grails app with
def session = WebUtils.retrieveGrailsWebRequest().session
Even though this will work in a service, you should only access the session from the web layer (controllers, GSPs, taglibs, etc.). However, for the particular scenario you've described above, I don't see why you need to use the session at all, could you do something like this instead?
def masterMethod() {
def method1Result = method1()
def method2Result = method2()
method3(method1Result, method2Result)
}
def method3(method1Result, method2Result) {
// decide what to do based on the results of methods 1 and 2
}
Upvotes: 3
Reputation: 423
if you want to code a great and scalable functionality you must use a design pattern. When like in your case you have a list of operations that depends on some conditional things or are governed by a process the right approach is to use Chain of Responsability pattern. I used it also in a grails application. I'll show you my solution
The first step is to create an interface this is not a Service, is a standar groovy class that you can store in Source/groovy:
public interface MyMasterHandler {
public void setNext(MyMasterHandler handler)
public void handleRequest(Operation operation)
}
As you can see we ohave only two methods: setNext that you'll use for create the chain and handleRequest where you'll put the logic of one single chain of responsability
So after you will create some handlers, one for responsability scope and an object to share information:
Object:
public class Operation {
Boolean callmethod3 = false
}
Mthod1 handler:
class Method1 implements MyMasterHandler {
private MyMasterHandler next
@Override
void setNext(MyMasterHandler handler) {
next = handler
}
@Override
void handleRequest(Operation operation) throws SomeExceptionIfYouWant {
if (some.condition || operation.some.condition )
{
operation.callmethod3 = true
}
next.handleRequest(operation)
}
}
Mthod2 handler:
class Method2 implements MyMasterHandler {
private MyMasterHandler next
@Override
void setNext(MyMasterHandler handler) {
next = handler
}
@Override
void handleRequest(Operation operation) throws SomeExceptionIfYouWant {
if (operation.callmethod3 == true )
{
next.handleRequest(operation)
}
}
}
Mthod3 handler:
class Method1 implements MyMasterHandler {
private MyMasterHandler next
@Override
void setNext(MyMasterHandler handler) {
next = handler
}
@Override
void handleRequest(Operation operation) throws SomeExceptionIfYouWant {
do stuff of method3
}
}
After that in yuou service/controller you only need to initialize an oject class (in this example is Operation) from the session or from you want and create the chain:
class MyController(){
def test(){
Operation op = new Operation(params) //or session, here we use grails marshalling, if you have params.callmethod3 the object will auto initialized
MyMasterHandler one = new Method1()
MyMasterHandler two = new Method2()
MyMasterHandler three = new Method3()
one.setNext(two)
two.setNext(three)
one.handleRequest(op)
}
}
So the nice thing is that the business login is splitted in your handlers, and in a future if you want to add a new chain you must create only a new handler. If you want you can store object Operation in the session of a controller and then pass it to the service or who create and start the chain. In the chain if you want you can throw particular Exception so in the service/controller you can handle the exeption thrown and do whit that wath you want.
Upvotes: 3