Search code examples
spring-session

Get the current session with spring-session


Here's my question: I'm writing a platform which I will be giving to the customers to implement their projects with. So in my platform I have created a SessionService in which I have methods like getCurrentSession, getAttribute, setAttribute, etc. Before spring-session my getCurrentMethod looked like this:

@Override public HttpSession getCurrentSession() { if (this.session == null) { final ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); return attr.getRequest().getSession(true); // true == allow create } return this.session; }

which worked perfectly fine, although it looks ugly and have no backing like redis. Now I want to migrate to spring-session and I was hoping to use the SessionRepository to find the current session of the user, however I can only see a getSession(String id) in there. I believe the id is stored in the cookie, so to use it I will probably have to pass the HttpServletRequest object from my controllers, to my facades, to the service layer which is very near the db layer. This looks like a very bad idea to me, so my question would be: is there any way to get the currentSession near the db layer? One way I would think is to write an interceptor that will be invoked the controllers, which will set the current session in the repository, or the service maybe? I'm just not sure this is the right way to go.


Solution

  • Obtaining the Session Id from Service Layer

    You can use the RequestContextHolder to retrieve the session id, set attributes, and remove attributes.

    The RequestContextHolder is typically setup using RequestContextListener or RequestContextFilter. Spring Session does NOT work with RequestContextListener because there is no way for Spring Session to wrap the request before the RequestContextListener is invoked.

    Unfortunately, this means for Spring Boot applications, RequestContextHolder does not work out of the box. To work around it you can create a RequestContextFilter Bean. See spring-boot/gh-2637 for updates on this issue.

    Should I be putting this in session?

    Just because it is easy to put a lot of objects in session and it is stored in Redis does not mean it is the right thing to do.

    Keep in mind that the entire session is retrieved on every request. So while Redis is fast, this can have a significant impact if there are lots of objects in session. Obviously the implementation can be optimized for your situation, but I think the concept of session generally holds this property.

    A general rule of thumb is, "Do I need this object for over 95% of my requests?" (read this as almost all of my requests). If so, it may be a candidate for session. In most cases, the object should be security related if it fits this criteria.

    Should I access session id from ThreadLocal in the service layer?

    This is certainly open for debate as code is as much of an art as it is a science.

    However, I'd argue that you should not be obtaining the session id from thread locale variables throughout your architecture. Doing this feels a bit like obtaining a "Person id" and obtaining the current "Person id" from the HttpServletRequest in a ThreadLocale. Instead, values should be obtained from the controller and passed into your service layer.