Open crisarmen opened 7 years ago
I also encountered this issue, here's how I'm working around it:
In an @Configuration
class:
@Bean
public FilterRegistrationBean<Filter> sessionSetWhenGetAttributesFilter(final @Autowired SessionSetWhenGetAttributesFilter sessionSetWhenGetAttributes){
final FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setOrder(SessionRepositoryFilter.DEFAULT_ORDER -1);
filterRegistrationBean.setFilter(sessionSetWhenGetAttributes);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
return filterRegistrationBean;
}
Then create SessionSetWhenGetAttributesFilter.java:
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
/** When {@link HttpSession#getAttribute(String)} is called, also call {@link HttpSession#setAttribute(String, Object)}.
* This application is written with the assumption that if an object is gotten from the session then changed, then that change is persisted.
* However, Spring Session does not work that way -it requires {@link HttpSession#setAttribute(String, Object)} to be called to tell it that the object has changed.
* This approach isn't terribly efficient (it calls {@link HttpSession#setAttribute(String, Object)} more than necessary) but it's much less effort that determining all the places where {@link HttpSession#setAttribute(String, Object)} should be called and adding those missing invocations.
* @author Craig Andrews
* @see <a href="https://github.com/spring-projects/spring-session/issues/648">https://github.com/spring-projects/spring-session/issues/648</a>
*/
@Component("sessionSetWhenGetAttributes")
public class SessionSetWhenGetAttributesFilter extends OncePerRequestFilter {
private static class HttpSessionWrapper implements HttpSession {
protected final HttpSession delegate;
public HttpSessionWrapper(HttpSession delegate) {
this.delegate = delegate;
}
public long getCreationTime() {
return delegate.getCreationTime();
}
public String getId() {
return delegate.getId();
}
public long getLastAccessedTime() {
return delegate.getLastAccessedTime();
}
public ServletContext getServletContext() {
return delegate.getServletContext();
}
public void setMaxInactiveInterval(int interval) {
delegate.setMaxInactiveInterval(interval);
}
public int getMaxInactiveInterval() {
return delegate.getMaxInactiveInterval();
}
public HttpSessionContext getSessionContext() {
return delegate.getSessionContext();
}
public Object getAttribute(String name) {
return delegate.getAttribute(name);
}
public Object getValue(String name) {
return delegate.getValue(name);
}
public Enumeration<String> getAttributeNames() {
return delegate.getAttributeNames();
}
public String[] getValueNames() {
return delegate.getValueNames();
}
public void setAttribute(String name, Object value) {
delegate.setAttribute(name, value);
}
public void putValue(String name, Object value) {
delegate.putValue(name, value);
}
public void removeAttribute(String name) {
delegate.removeAttribute(name);
}
public void removeValue(String name) {
delegate.removeValue(name);
}
public void invalidate() {
delegate.invalidate();
}
public boolean isNew() {
return delegate.isNew();
}
}
private static class SessionSetWhenGetAttributesWrapper extends HttpSessionWrapper {
public SessionSetWhenGetAttributesWrapper(HttpSession delegate) {
super(delegate);
}
@Override
public Object getAttribute(String name) {
Object value = super.getAttribute(name);
setAttribute(name, value);
return value;
}
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
filterChain.doFilter(new HttpServletRequestWrapper(request) {
@Override
public HttpSession getSession(boolean create) {
final HttpSession session = super.getSession(create);
return session == null ? null : return new SessionSetWhenGetAttributesWrapper(session);
}
@Override
public HttpSession getSession() {
return new SessionSetWhenGetAttributesWrapper(super.getSession());
}
}, response);
}
}
Hello,
I am trying to use spring-session-data-redis:1.2.2 on an existing project built with Spring/Spring MVC.
At the moment we have java objects stored in the session, and such objects are retrieved a modified in different parts of the code. Just as a simplified example, consider the simple object:
At a certain point in the flow we retrieve the object an modify the internal value doing something like:
And after in the flow we retrieve it and read the value doing something like:
Before trying to use spring-session, here value was 99. But now when I retrieve the value, I don't see 99, but I see the original value that the TestObject had when he was initially stored in the session.
Is there something I can configure in order to be able to replicate the behaviour I had before using spring-session?
Few notes:
but I was curious to know if there was something I could do without modifying the existing code.
Thanks in advance for your help.