Spring-session clears attributes from session after pageContext.include -
Spring-session clears attributes from session after pageContext.include -
i think have come across bug in spring-session
want inquire here if bug. before forget
https://github.com/paranoiabla/spring-session-issue.git
here's github repository reproduces problem. have 2 controllers , 2 jsps, flow goes this:
user openshttp://localhost:8080/
, flow goes through homepagecontroller
, puts 1 attribute in spring-session , returns homepage.jsp
renders session id , number of attributes (1) the homepage.jsp
has line within it: ${pagecontext.include("/include")}
calls includecontroller
invoked. the includecontroller
finds session session repository , logs number of attributes (now absolutely weird logged 0) , returns include.jsp
renders both session id , number of session attributes (0). session id in both jsps same, somehow after pagecontext.include
phone call attributes reset empty map!!! can please confirm if bug. thank you.
problem
the problem when using mapsessionrepository sessionrepositoryfilter automatically sync httpsession spring session overrides explicit utilize of apis. next happening:
sessionrepositoryfilter obtaining current spring session. caches in httpservletrequest ensure every invocation of httpservletrequest.getsession() not create database call. cached version of spring session has no attributes associated it. the homepagecontroller obtains own re-create of spring session, modifies it, , saves it. the jsp flushes response commits httpservletresponse. means must write out session cookie prior flush beingness set. need ensure session persisted @ point because afterwards client may have access session id , able create request. means spring session #1 saved no attributes overrides session saved in #2. the includecontroller obtains spring session saved #3 (which has no attributes) solutionthere 2 options see solving this.
use httpsession apisso how solve this. easiest approach stop using spring session apis directly. preferred anyways since not want tie ourselves spring session apis if possible. example, instead of using following:
@controller public class homepagecontroller { @resource(name = "sessionrepository") private sessionrepository<expiringsession> sessionrepository; @resource(name = "sessionstrategy") private httpsessionstrategy sessionstrategy; @requestmapping(value = "/", method = requestmethod.get) public string home(final model model) { httpservletrequest request = ((servletrequestattributes) requestcontextholder.currentrequestattributes()).getrequest(); final string sessionids = sessionstrategy.getrequestedsessionid(request); if (sessionids != null) { final expiringsession session = sessionrepository.getsession(sessionids); if (session != null) { session.setattribute("attr", "value"); sessionrepository.save(session); model.addattribute("session", session); } } homecoming "homepage"; } } @controller public class includecontroller { private final static logger log = logmanager.getlogger(includecontroller.class); @resource(name = "sessionrepository") private sessionrepository<expiringsession> sessionrepository; @resource(name = "sessionstrategy") private httpsessionstrategy sessionstrategy; @requestmapping(value = "/include", method = requestmethod.get) public string home(final model model) { httpservletrequest request = ((servletrequestattributes) requestcontextholder.currentrequestattributes()).getrequest(); final string sessionids = sessionstrategy.getrequestedsessionid(request); if (sessionids != null) { final expiringsession session = sessionrepository.getsession(sessionids); if (session != null) { log.error(session.getattributenames().size()); model.addattribute("session", session); } } homecoming "include"; } }
you can simplify using following:
@controller public class homepagecontroller { @requestmapping(value = "/", method = requestmethod.get) public string home(httpservletrequest request, model model) { string sessionids = request.getrequestedsessionid(); if (sessionids != null) { final httpsession session = request.getsession(false); if (session != null) { session.setattribute("attr", "value"); model.addattribute("session", session); } } homecoming "homepage"; } } @controller public class includecontroller { @requestmapping(value = "/include", method = requestmethod.get) public string home(httpservletrequest request, final model model) { final string sessionids = request.getrequestedsessionid(); if (sessionids != null) { final httpsession session = request.getsession(false); if (session != null) { model.addattribute("session", session); } } homecoming "include"; } }
use redisoperationssessionrepository of course of study may problematic in event cannot utilize httpsession api directly. handle this, need utilize different implementation of sessionrepository. example, prepare utilize redisoperationssessionrepository. works because smart plenty update attributes have been changed.
this means in step #3 above, redis implementation update lastly accessed time since no other attributes updated. when includecontroller requests spring session still see attribute saved in homepagecontroller.
so why doesn't mapsessionrepository this? because mapsessionrepository based on map or nil thing. when value placed in map single set (we cannot break multiple operations).
spring-session
Comments
Post a Comment