Thursday, July 7, 2011

Grails - Accessing the Http-Session from Services

Holy Cow. I didn’t make it the last six months to write a post here. Too much stuff is going on in private and business life. But I promise improvement by writing an article at least once a month.
As I’m currently working most of the time on Grails projects, I restart the Blog with a little Grails series. Starting with the question: Is it useful to access a http-session in a Grails Service.

In general it isn't a very good idea to access the web session from within Services.
First of all you never know if the web session is available: Think about calling the service method from a job or JMS call (instead of a controller). There wouldn't be any http-request associated with the current thread.
Second, it's a common and good design pattern to separate the service logic from client specific stuff.

But there are circumstances where it may be adequate to access the session within a service.
One way to do it would be to use a method parameter for transferring the session object.
However, that could clutter method signatures which isn't a nice design also.
Another way could be to use Spring's session scope beans. This seems to be right for
many cases, but could be a little too much overhead for simple use cases.

A pretty alternative is to implement a small service that encapsulates the access to
the http-session in a safe manner.

This service could look like this:

 class WebUtilService {

    void withSession (Closure closure) {
        try {
            GrailsWebRequest request = RequestContextHolder.currentRequestAttributes()
            GrailsHttpSession session = request.session
            closure.call(session)
        }
        catch (IllegalStateException ise) {
            log.warn ("No WebRequest available!")
        }
    }
    
}

It's used like this:

class MyService {
    
    WebUtilService webUtilService
    
    void doSomething() {
        webUtilService.withSession { HttpSession session ->
            log.info ( session.myValue )
            session.newValue = 'Possible, but should be exceptional'
        }
    }

}