Natural Conversations are a way of creating URLs that are a little more 'human readable' and also allows us to bookmark certain pages. Consider an ecommerce site - ideally you want to bookmark a product and the easiest way to do this is by id. So we want to have a showProduct.do?productId=1234 for example. In this example, we want a Product and a ProductAction. You'll have to fill in the blanks yourself on the Product class, but suffice to say that we have an id attribute. Within the ProductAction class, we need to include the usual plumbing of EntityManager and so forth. We will also need a value for the product id from the parameter along with a getter and a setter for this value.


@Name("ProductAction");
@Scope(ScopeType.CONVERSATION);
public class ProductAction implements Serializable {
@In EntityManager entityManager;

private Long productId;

@Out(required = true)
private Product product;

@Begin(join=true)
public String showProduct() {

product = entityManager.find(Product.class, productId);

return "product";
}

public void setProductId(String productId) {
// obviously on a production system we'd catch the exception and handle it nicely
this.productId = Long.parseLong(productId);
}

public String getProductId() {
return productId.toString();
}

}


Now we require some configuration to pipe the parameter on the URL into the action.

In pages.xml:



<conversation name="product" parameter-name="product"
parameter-value="#{product.id}" />

<page view-id="/product.xhtml">
<param name="id" value="#{ProductAction.productId}" />
</page>


SEO-friendly URLs are an extension on this theme. Most search engines do not like parameters on the URL, so a URL that is SEO friendly hides our parameters. For the above example, you really want something along the lines of showProduct.do/1234. So for this part, we need to instruct our application to consider any number after the trailing slash to be passed into the action as the productId.

To achieve this, we need to add URL rewrite capability into our application. First up is the jar file available from http://tuckey.org/urlrewrite/. Next, a little configuration within components.xml:



<component name="URLRewriteFilter"
precedence="30">
<property name="initParameters">
<key>logLevel</key>
<value>WARN</value>
<key>statusEnabled</key>
<value>false</value>
</property>
</component>



Next up is the plumbing between the url we would like to use (i.e. http://yourserver/yourapp/products.seam/1 to http://yourserver/yourapp/products.seam?productId=1). This is achieved by creating a urlrewrite.xml file under your WEB-INF folder (where your components.xml lives) with the following configuration.


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN" "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">


<urlrewrite>
<rule>
<from>^/product.seam/([0-9]+)$</from>
<to last="true">/garage.seam?id=$1</to>
</rule>

</urlrewrite>



And now you have the ability to refer to your products by ID in an SEO friendly way and also using a parameter that is more appealing to human eyes. The SEO method is also quite useful for implementing REST services on your components if so desired.