Rodiq » Page 'tapestry5 custom page context'

tapestry5 custom page context

My problem was to store in a clean way different fields (filters) used for displaying a page (a list of products, in my case). I wanted to handle the case where only some of the fields may be present at a given time. The easiest way would be to encapsulate all possible fields in a new class, and use it as a page context (the new tapestry5 concept, to avoid using http session).

The solution (not at all easy to find, due to lack of documentation, but found a way thanks to Len, who took the time to look in Tapestry source code):

1.Write my class that implements ValueEncoder interface:
2.Declare the new encoder in
3.Declare the context of my tapestry page


public class ProductsFilter implements ValueEncoder
private String searchText;
private Long nodeId;

public String getSearchText() {
return searchText;

public void setSearchText(String searchText) {
this.searchText = searchText;

public Long getNodeId() {
return nodeId;

public void setNodeId(Long nodeId) {
this.nodeId = nodeId;

public java.lang.String toClient(ProductsFilter productsFilter){
String string = "";
if (productsFilter.getNodeId() != null)
string = string + productsFilter.getNodeId();
string = string + "/";
if (productsFilter.getSearchText() != null)
string = string + productsFilter.getSearchText();

return string;

* the value is encoded nodeId/searchText
* examples: 234/mini  /mini 234/
public ProductsFilter toValue(java.lang.String string){

ProductsFilter productsFilter = new ProductsFilter();

int index = string.indexOf("/");

//we have a nodeId
if (index > 0){
String nodeIdString = string.substring(0, index);
try {
long nodeId = Long.parseLong(nodeIdString);
productsFilter.setNodeId(new Long(nodeId));
} catch (Throwable t){
String searchText = string.substring(index+1, string.length());
if (searchText.length()>0){

return productsFilter;

2. In

    public static void contributeValueEncoderSource(MappedConfiguration configuration)
        configuration.add(ProductsFilter.class, GenericValueEncoderFactory.create(new ProductsFilter()));

3. And in (the class of the Products.tml page)

public class Products {
    private static Logger log = Logger.getLogger(Products.class);
    private ProductsFilter productsFilter;
    //even it is a property, this setter is usefull for action handlers followed by redirect
    public void setFilter(ProductsFilter productsFilter) {
		this.productsFilter = productsFilter;

How to use it? For instance with a pagelink that gives as context an object of type ProductsFilter:

<t:pagelink page="products" context="contextParams">link to products</t:pagelink>
    public ProductsFilter getContextParams(){
        ProductsFilter productsFilter = new ProductsFilter();
        productsFilter.setSearchText("a product name");
        return productsFilter;

Or in a submit handler, by setting directly the productsFilter of the products page, then redirecting:

private Products products;

public Object onSuccess(){

ProductsFilter productsFilter = new ProductsFilter();

return products;
Share and Enjoy:
  • Digg
  • StumbleUpon
  • Facebook
  • Google Bookmarks
  • Reddit
  • RSS

Leave a comment

+ two = 10