Yeps, as lewthor says multiple tabs share a session.
One way to deal with the situation is to have a tab specific url component that will be included in the session key. If you are on a product listing page, and you're opening a new tab per product, if you make sure that the urls upon tab opening are different e.g. by using product id in the url /product/{product.id}
, all you have to do make the proper behaviour is append the id to session key searchresults{product.id}
There is also a @SessionAttribute centric solution, a customization that serves just this purpose, descibed in the blog here and based on the older blog described here. The solution implements a CustomSessionAttributeStore, and maintaines a Map of Maps where the inner Map is the deafult SessionAttributes, identified by the conversation id (in your case the tab id)
public class ConversationalSessionAttributeStore implements SessionAttributeStore, InitializingBean {
@Inject
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
private Logger logger = Logger.getLogger(ConversationalSessionAttributeStore.class.getName());
private int keepAliveConversations = 10;
public final static String CID_FIELD = "_cid";
public final static String SESSION_MAP = "sessionConversationMap";
@Override
public void storeAttribute(WebRequest request, String attributeName, Object attributeValue) {
Assert.notNull(request, "WebRequest must not be null");
Assert.notNull(attributeName, "Attribute name must not be null");
Assert.notNull(attributeValue, "Attribute value must not be null");
String cId = getConversationId(request);
if (cId == null || cId.trim().length() == 0) {
cId = UUID.randomUUID().toString();
request.setAttribute(CID_FIELD, cId, WebRequest.SCOPE_REQUEST);
}
logger.debug("storeAttribute - storing bean reference for (" + attributeName + ").");
store(request, attributeName, attributeValue, cId);
}
private String getConversationId(WebRequest request) {
return request.getParameter(CID_FIELD);
}
}
The whole project is posted on GitHub