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 AppModule.java
3.Declare the context of my tapestry page

1.

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){
//ignore
}
}
String searchText = string.substring(index+1, string.length());
if (searchText.length()>0){
productsFilter.setSearchText(searchText);
}

return productsFilter;
}

2. In AppModule.java:

    @SuppressWarnings("unchecked")
    public static void contributeValueEncoderSource(MappedConfiguration configuration)
    {
        configuration.add(ProductsFilter.class, GenericValueEncoderFactory.create(new ProductsFilter()));
    }

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

public class Products {
    private static Logger log = Logger.getLogger(Products.class);
    @Property
	@PageActivationContext
    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.setNodeId(null;
        productsFilter.setSearchText("a product name");
        return productsFilter;
     }

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

@InjectPage
private Products products;

public Object onSuccess(){

ProductsFilter productsFilter = new ProductsFilter();
productsFilter.setSearchText(text);
productsFilter.setNodeId(null);

products.setFilter(productsFilter);
return products;
}
Share and Enjoy:
  • Digg
  • StumbleUpon
  • Facebook
  • Google Bookmarks
  • Reddit
  • RSS

Leave a comment


5 + = nine