Grails 3 was a great update to the framework and kept it up-to-date with modern requirement in web development. Modularization, profiles, revamped build system and configuration were all great changes that made working with grails more productive and fun again.
I quite like the choice of YAML for the configuration settings because you can easily describe sections and hierarchies without much syntactic noise.
Unfortunately, there are some caveats. One of them went live and caused a (minor) irritation for our customer:
The session timeout was back to the 30 minutes default and not prolongued to the one hour we all agreed upon some years (!) ago.
Investigating the cause
Our configuration in application.yml
was correctly set to the desired one hour timeout and in development everything was working as expected. But the thing is that the setting server.session.timeout
is only applied to the embedded tomcat. If your application is deployed to a standalone servlet container this setting is ignored. Unfortunately it is far from obvious which settings in application.yml are used in what situation.
In the case of a standalone servlet container you would just edit your applications web.xml
and the container would use the setting there. While this would work, it is not very nice because you have two locations for one setting. In software development we call that duplication. What makes things worse is, that there is no web.xml in our case! So what now?
The solution
We have two problems here
- Providing the functionality our customer desires
- Removing the code duplication so that development and production work the same way
Our solution is to apply the setting from application.yml to the HTTP-Session of the request using an interceptor:
class SessionInterceptor { int order = -1000 SessionInterceptor() { matchAll() } boolean before() { int sessionTimeout = grailsApplication.config.getProperty('server.session.timeout') as int log.info("Configured session timeout is: ${sessionTimeout}") request.session?.setMaxInactiveInterval(sessionTimeout) true } }
That way we use a single source of truth, namely the configuration in application.yml
, both in development and production.
Can I match just once when login succeeds? Thanks!
Not that I know. I did not even find a way to provide the setting in context.xml which would be kind of ok for us…
how i can display session expired message to user with this.
Well, in the interceptor you have access to the HttpSession object, where the timeout is set. You can query the session object for last access time and calculate if the session is expired and handle that case.
how i can display timeout message to the user with this
How do you change the timeout time with this? For example, I need the timeout time to be 15 min.
Well, the timeout is defined in the property server.session.timeout in application.yml in seconds. So for 15 mins set it to 900.