Currently when I need to share a method like processParams(params)
between different controllers, I use either inheritance or services.
Both solution has some inconvenients :
- With inheritance, you cannot use multiple inheritance which means that you need to have all of your controller utility methods in one place. And also, there is a bug in grails that does not detect any code changes in Base Controller classes in development mode (you need to restart the app)
- With services, you don't have access to all injected properties like params, session, flush...
So my question is : is there any other way to use some common methods accessible for multiple controllers ?
Common functionality is a call for a new class, not necessarily common ancestor. The question formulation is missing responsibility statement for it. Needless to say, it's a single responsibility that we create a new class for. I take further decisions basing on class responsibility.
I prefer a hybrid of robbbert's and Jared's answers: I construct extra classes, passing them necessary controller internals as parameters. Sometimes the classes develop from method objects. Like:
Not so brief, but lets you get code under tests and keep coupling low.
As
SomeResponsibilityDoer
is only going to have couple of fields - request an response - it's not a big deal constructing it with every request.It's also not a big deal having
SomeResponsibilityDoer
not reloaded on controller change in dev, because:src/groovy
.One option I like is to write the common methods as a category, then mix it into the controllers as necessary. It gives a lot more flexibility than inheritance, has access to stuff like params, and the code is simple and understandable.
Here's a tiny example:
You can write all the common method in commonService and use that service to envoke commmon method
This doesn't help the restarting in development mode issue you have, but it's the way I've solved this problem. It's ugly and probably not good practice, but I factor common code into classes as closures. Then I can do something like:
and from with in the controllerClosures class
You can use the Delegation design pattern:
In case of a controller, assign the helper class directly at the instance field (or in the nullary constructor):
The delegate's type information gets compiled into the containing class.