Dashboard > Stripes > ... > User Additions > Save ActionBean fields in session
Save ActionBean fields in session Log In | Sign Up   View a printable version of the current page.

Added by Christian Poitras , last edited by Christian Poitras on Jul 08, 2008  (view change) show comment

@Session annotation

@Session annotation moved to Stripes Stuff!

Changes made in the Stripes Stuff version

@Session annotation location is org.stripesstuff.plugin.session.Session instead of ca.qc.ircm.stripes.annotation.Session.

Fields saved by SessionStoreInterceptor in Stripes Stuff are directly accessible in session. So session.getAttribute(key) returns an object of the same type as the declared field.
This relieves you from calling SessionStoreInterceptor.getAttribute(session, key) which is now deprecated. Replace all calls to SessionStoreInterceptor.getAttribute(session, key) by session.getAttribute(key).

Changes made in version 6 on STS-429

An important change is made to version 6 of the @Session plugin. The serializable attribute now has a default value of true (it was false in all previous versions). To update your code, simply make sure that the classes you save in session are serializable or change serializable attribute to false.

Take note that version 6 of plugin is packed into a zip file. The zip file contains the session-plugin jar file and source code.

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 after the event completes in session 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.

The code is available in the Stripes Stuff project on SourceForge http://sourceforge.net/projects/stripes-stuff/. Older versions are available in the JIRA I created STS-429. Versions will be added to Stripes Stuff when I correct bugs or when I add new attributes to the annotation.

Configuration

Simply add SessionStoreInterceptor to your interceptors in web.xml. A common configuration will look like this.

Stripes Stuff version
<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>Interceptor.Classes</param-name>
        <param-value>
            org.stripesstuff.plugin.session.SessionStoreInterceptor
        </param-value>
    </init-param>
</filter>
Older versions
<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>Interceptor.Classes</param-name>
        <param-value>
            ca.qc.ircm.stripes.interceptor.SessionStoreInterceptor
        </param-value>
    </init-param>
</filter>

@Session annotation attributes

  1. serializable default true. Default value changed in version 6.
    1. When true, interceptor will check if field implements java.io.Serializable. If field implements java.io.Serializable, field will be kept in session even if session is serialized. If field does not implements java.io.Serializable, the field is stored as tough @Session(serializable=false) is used.
    2. When false, field stored in session will be removed before session is serialized.
  2. maxTime default -1. Number of minutes before field is removed from session automatically. When 0 or negative, maxTime is considered infinite.
  3. Key. When a key is set, the interceptor will use that key to store field in session. This will allow field sharing between different action beans. (added in version 4)

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). Changed in Stripes Stuff version
For older version: use SessionStoreInterceptor.getAttribute(session, key) where session is HttpSession and key is the attribute used to store object in session.

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(). Default key changed in 6.1. 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".
In versions 1 to 6, the default key was field.getDeclaringClass() + "#" + field.getName(). This was changed in 6.1 due to unexpected field sharing for classes extending a common super class. Use key attribute of @Session to share fields.

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

Resolved issues

  1. Corrected in session-plugin3.jar : When @Session annotation is used on a Collection or Map field and request parameters overwrite some elements, the other elements will not be modified. This behavior seems inconsistent.
    • Correction : When a request parameter matches the field name, that field will not be recovered from session.

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

Hosting for this site is donated by the wonderful people at Contegix
Site running on a free Atlassian Confluence Open Source Project License granted to Stripes Framework. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.6.2 Build:#919 Nov 26, 2007) - Bug/feature request - Contact Administrators