Dashboard > Stripes > ... > User Additions > Save ActionBean fields in session
Stripes Log In   View a printable version of the current page.
Save ActionBean fields in session
Added by Christian Poitras, last edited by Christian Poitras on Jan 16, 2008  (view change) show comment

Stripes has moved! This site is no longer being actively maintained. Please point your browsers at http://www.stripesframework.org and update your bookmarks. Thank you.

@Session annotation

Purpose

Sometimes it may be more simple to save specific fields in session. It may also take to 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 JIRA I created and can be found here source.  New versions will be added 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.

<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>
            net.sourceforge.stripes.controller.BeforeAfterMethodInterceptor,
            ca.qc.ircm.stripes.interceptor.SessionStoreInterceptor
        </param-value>
    </init-param>
</filter>

@Session annotation attributes

  1. serializable default false. 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 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 session-plugin4.jar)

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

Use SessionStoreInterceptor.getAttribute(session, key) where session is HttpSession and key is the attribute used to store object in session.

Using session.getAttribute(key) will not work since SessionStoreInterceptor uses a private class to package objects to allow automatic removal upon session serialization or when maxTime is reached.

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 errors: set field to null in the event (if it's not a primitive).
  2. Validation errors: use session.removeAttribute(key).

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 field.getDeclaringClass() + "#" + 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".

Example

Consider this action bean and jsp.

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

import ca.qc.ircm.stripes.annotation.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

Site powered by a free Open Source Project / Non-profit License (more) of Confluence - the Enterprise wiki.
Learn more or evaluate Confluence for your organisation.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.2.7 Build:#524 Jul 28, 2006) - Bug/feature request - Contact Administrators