5

I have an instance of HandlerInterceptorAdapter that intercept request to check locale...

public class LocaleControllerInterceptor extends HandlerInterceptorAdapter {   
             @Override
             public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                   final HttpSession session = SessionContextHolder.getSession();
                   // ...
             } 
}

and my SessionContextHolder is :

public abstract class SessionContextHolder {

        public static HttpSession getSession() {
            ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
            return attr.getRequest().getSession(true);
        }

}

when I want to call an endpoint, the preHandle() method of the interceptor will called 2 times (why?!), in the first call, the session that SessionContextHolder gives me (by getSession() method) is an instance of org.apache.catalina.session.StandardSessionFacade, and the second time is an instance of org.springframework.session.data.mongo.MongoExpiringSession. I've already enabled MongoHttpSession by @EnableMongoHttpSession annotation. The problem is that, I expect that the session should always be an instance of MongoExpiringSession but is not.

Can anyone explain the mechanism of Spring-Session and the reason of this behavior?

Jalal Sajadi
  • 412
  • 6
  • 12
  • That's strange; I don't think it should be being called twice. Spring Session works by using a standard servlet filter to replace the session in the request context. – chrylis -cautiouslyoptimistic- Aug 22 '16 at 11:19
  • Also why aren't you simply using `request.getSession`? Way make it more complex then that and use the contraption you have in place. – M. Deinum Aug 22 '16 at 11:34
  • Thank you @chrylis for your comment. I've wondered too. I test it for several time, and it always called twice. But this codes is part of a big project with more than 50k lines of code with several interceptors,I think I should check another part of project to find the reason! – Jalal Sajadi Aug 22 '16 at 12:03
  • Thanks @M.Deinum. You're right. But I used `SessionContextHolder` in a context which has not the request itself (e.g. for set the default locale). I wrote this code instead of passing request... – Jalal Sajadi Aug 22 '16 at 12:11
  • 2
    Which might be a bad idea, as that ties the whole codebase to the web layer. Also do you really need it? Spring already has the `LocaleContextHolder` to obtain the current `Locale` and it integrates with the `LocaleResolver`, it feels a bit like you are trying to bolt your own on top of something that already is supported (more easily) by spring. – M. Deinum Aug 22 '16 at 12:15
  • Dear @M.Deinum, my reason to use this approach is that I need to store the locale during the session life, but as far as I know, `LocalContecxtHolder` utilizes `ThreadLocal` to store current `Locale` that means need to send the expected locale with each request. In my way, I store the current locale as a session attribute, so it's alive during the session life. – Jalal Sajadi Aug 22 '16 at 13:48
  • 1
    The `LocaleContextHolder` indeed uses a `ThreadLocal` however your understanding is wrong. The `ThreadLocal` is filled based on the value retrieved from the `LocaleResolver` for the duration of the current request. Now the coincidence is that there is a `SessionLocaleResolver` which does basically what you are trying to achieve yourself (again). That combined with the `DispatcherServlet` does all you need. – M. Deinum Aug 22 '16 at 13:57

0 Answers0