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.
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.