Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This document has two major sections:

  1. #Smart State Management using the ActionBeanContext
  2. #Redirect-after-Post using the Flash Scope

...

Code Block
titleActionBeanContext subclass
 
public class MyAppActionBeanContext extends ActionBeanContext { 

	public void setUser(User user) { 
		getRequest().getSession().setAttribute("user", user); 
	} 

	public User getUser() { 
		return (User) getRequest().getSession().getAttribute("user"); 
    } 
} 

Now that you have your own ActionBeanContext you'll need to tell Stripes to use it. The easiest way is to drop your class into an extensions package (see Extensions). Alternatively, you can add the following initialization parameter to the Stripes Filter in your web.xml:

Code Block
xml
xml
titleConfiguring your ActionBeanContext
 
<init-param> 
	<param-name>ActionBeanContext.Class</param-name> 
	<param-value>com.myco.MyAppActionBeanContext</param-value> 
</init-param> 

...

Code Block
titleUsing a co-variant return type in your ActionBean
public class MyActionBean implements ActionBean { 
	private MyAppActionBeanContext context; 

	/** Interface method from ActionBean. */ 
	public setContext(ActionBeanContext context) { 
		this.context = (MyAppActionBeanContext) context; 
	} 

	/** Interface method from ActionBean, using a co-variant return type! */ 
	public MyAppActionBeanContext getContext() { 
		return this.context; 
	} 

... 
} 

In Java 1.4 and earlier, the getContext() method would not compile because the interface specifies it must return ActionBeanContext, and the class specifies MyAppActionBeanContext. It'd fail even though MyAppActionBeanContext extends ActionBeanContext. In Java 1.5 this is allowed, and it helps make things a bit cleaner. And if you create your own BaseActionBean class you can put this in there and never have to see it again (smile)

...

But wait, there's more. Because the ActionBeanContext is attached to your ActionBean, and your ActionBean is dropped into a request attribute, you now have two ways of accessing things stored in session. On a JSP:

Code Block
xml
xml
 
<div>${user} == ${actionBean.context.user}</div> 

...

Code Block
titleMyAppActionBeanContext.java
 
public abstract class MyAppActionBeanContext extends ActionBeanContext { 
	public abstract void setUser(User user); 
	public abstract User getUser(); 
} 

...

Code Block
titleMyAppActionBeanContextImpl.java
 
public class MyAppActionBeanContextImpl extends MyAppActionBeanContext { 

	public void setUser(User user) { 
		getRequest().getSession().setAttribute("user", user); 
	} 

	public User getUser() { 
		return (User) getRequest().getSession().getAttribute("user"); 
	} 
} 

And then, we create out test ActionBeanContext:

Code Block
titleMyAppActionBeanContextTestImpl.java
 
public class MyAppActionBeanContextTestImpl extends MyAppActionBeanContext { 
	private User user; 

	public void setUser(User user) { this.user = user; } 

	public User getUser() {return this.user; } 
} 

...

Code Block
titleExample usage of FlashScope
 
public List<Message> getMessages(String key) { 
	FlashScope scope = FlashScope.getCurrent(getRequest(), true); 
	List<Message> messages = (List<Message>) scope.get(key); 

	if (messages == null) { 
		messages = new ArrayList<Message>(); 
		scope.put(key, messages); 
	} 

	return messages; 
} 

The true on the first line tells FlashScope to manufacture a FlashScope if one doesn't yet exist. After that the scope is used just like any other scope - as a container of key/value pairs.

...

By default ActionBeans are not put in flash scope. This is partly for backwards compatibility reasons, and partly because it just isn't necessary to do it all the time! That doesn't mean it's hard to do though. If you're using the standard RedirectResolution it's as simple as chaining one more method call:

Code Block
 
return new RedirectResolution("/some/page.jsp").flash(this); 

Even if you're redirecting some other way, it's still very easy:

Code Block
 
// From within the ActionBean 
FlashScope.getCurrent(getContext().getRequest(), true).put(this); 

...

Lets say you called this method in one of your ActionBeans:

Code Block
 
public void addRecipe(HttpServletRequest request, String message) { 
	FlashScope fs = FlashScope.getCurrent(request, true); 
	List<String> messages = (List<String>) fs.get("recipes"); 

	if (messages == null) { 
		messages = new ArrayList<String>(); 
		fs.put("recipes", messages); 
	} 

	messages.add(message); 
} 

Then you redirected to another ActionBean which forwards to a JSP. This is how you access the FlashScope in your JSP:

Code Block
xml
xml
 
<c:forEach var="recipe" items="${recipes}"> 
	<div class="recipe_name">${recipe.name}</div> 
</c:forEach> 

...