Save ActionBean fields in session

@Session annotation

@Session annotation is part of Stripes Stuff

Purpose

Sometimes it may be more simple to save specific fields in session. It may also take too much memory to save a complete action bean in session.

For this problem, I created a new interceptor which will scan action beans for @Session annotated fields. It will automatically store these fields in session after the event completes and will restore the fields automatically on subsequent requests. When validation error occurs in any phase, fields will not be saved in session as state would normally become inconsistent.

In addition if a request parameter would replace the field, the field will take the value from the request as expected.

Configuration

Simply add org.stripesstuff.plugin.session to extensions packages in web.xml. A common configuration will look like this.

web.xml
 
<filter> 
<display-name>Stripes Filter</display-name> 
<filter-name>StripesFilter</filter-name> 
<filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class> 
<init-param> 
<param-name>Extension.Packages</param-name> 
<param-value> 
org.stripesstuff.plugin.session 
</param-value> 
</init-param> 
</filter> 

@Session annotation attributes

Attribute

Value

Default

serializable

  • True and field implements java.io.Serializable: field will be kept in session even if session is serialized.
  • False or field does not implement java.io.Serializable: field stored in session will be removed before session is serialized.

true

maxTime

Number of minutes before field is removed from session automatically.

When 0 or negative, maxTime is considered infinite.

-1

key

Key to use to store field in session.

This will allow field sharing between different action beans.

actionBean.getClass() + "#" + field.getName()

If serializable is false and maxTime is negative, field will be removed upon session serialization.

How To

Access objects in session when key is known

Simply use session.getAttribute(key).

Remove objects from session

Just calling session.removeAttribute(key) will not work in all cases. SessionStoreInterceptor saves fields in session after event completes and only if no validation error occurs. To remove object from session manually, the best solutions are:

  1. No validation error: set field to null in the event (if it's not a primitive).
  2. Validation errors: use session.removeAttribute(key).

Faqs

What is the key under which field is saved?

The key used is the key defined in key attribute of @Session annotation.

When no key attribute is defined, the default key used to store fields is actionBean.getClass() + "#" + field.getName().
For instance, if action bean is ca.qc.ircm.web.MyActionBean and field is myField, the default key will be "ca.qc.ircm.web.MyActionBean#myField".

@Session does not work with boolean checkboxes

When a checkbox is checked, a parameter is sent to server. When checkbox is unchecked, nothing is sent to server.

This means that once a @Session annotated checkbox boolean field is checked and the event executes successfully, the boolean field will be true for as long as the field stays in session. Don't use @Session on checkboxes unless you can known that checkbox was unchecked.

Example

Consider this action bean and jsp.

CounterAction.java
 
package ca.qc.ircm.stripes.web; 

import org.stripesstuff.plugin.session.Session; 
import net.sourceforge.stripes.action.ActionBean; 
import net.sourceforge.stripes.action.ActionBeanContext; 
import net.sourceforge.stripes.action.DefaultHandler; 
import net.sourceforge.stripes.action.ForwardResolution; 
import net.sourceforge.stripes.action.HandlesEvent; 
import net.sourceforge.stripes.action.Resolution; 

/** 
* Example of Session annotation use. 
* 
* @author poitrac 
*/ 
public class CounterAction implements ActionBean { 

ActionBeanContext context; 
public ActionBeanContext getContext() {return context;} 
public void setContext(ActionBeanContext context) {this.context = context;} 

/** 
* Keep track of number of clicks. 
*/ 
@Session 
private Integer counter; 
/** 
* Number of clicks this submission will represent. 
*/ 
private Integer amount; 

/** 
* Reset counter to 0. 
* @return Counter page. 
*/ 
@DefaultHandler 
public Resolution input() { 
counter = 0; 
return new ForwardResolution("index.jsp"); 
} 
/** 
* Add 1 to counter. 
* @return Counter page. 
*/ 
@HandlesEvent("count") 
public Resolution count() { 
counter++; 
return new ForwardResolution("index.jsp"); 
} 
/** 
* Add 1 to counter. 
* @return Counter page. 
*/ 
@HandlesEvent("countAmount") 
public Resolution countAmount() { 
counter += amount; 
return new ForwardResolution("index.jsp"); 
} 


public Integer getCounter() { 
return counter; 
} 
public void setCounter(Integer counter) { 
this.counter = counter; 
} 
public Integer getAmount() { 
return amount; 
} 
public void setAmount(Integer amount) { 
this.amount = amount; 
} 
} 
index.jsp
 
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> 
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %> 

<html> 
<head> 
</head> 

<body> 

<p>Count: <c:out value="${actionBean.counter}"></c:out></p> 

<s:form beanclass="ca.qc.ircm.stripes.web.CounterAction" method="POST"> 
<s:submit name="count">Add 1 to counter</s:submit><br><br> 

<s:errors field="amount"></s:errors> 
Enter amount to add to counter: <s:text name="amount" value=""></s:text> <s:submit name="countAmount">Add</s:submit>
</s:form> 

</body> 
</html> 

As you can see, the counter field of CounterAction class has a @Session annotation. This will keep track of the number of clicks made on "count" button. It is also possible to add a specific amount to the counter using countAmount.

Possible attributes to add to @Session annotation

  1. OverwriteParam. When set, the interceptor will overwrite any modifications made from submitted fields that could modify the field in BindingAndValidation lifecycle.
  2. SaveOnError. When set, the interceptor will store the value in session even when validation error occurs. Some specific lifecyle could also be specified to limit the lifecycle where stored fields could be overwritten.

Current issues

  • None to report for now.

Please report any bugs to me at Christian.Poitras@ircm.qc.ca