Bookmarking JSF pages with PrettyFaces

In this recipe, we will explore an open source extension for JSF 1.0 and JSF 2.0 that enables creation of bookmarkable, pretty URLs. Its name is PrettyFaces and it includes some nice features, such as:

  • Page-load actions
  • Seamless integration with Faces navigation
  • Dynamic view ID assignment
  • Managed parameter parsing
  • Configuration-free compatibility with other JSF frameworks

Getting ready

We developed this recipe with NetBeans 6.8, JSF 2.0, and GlassFish v3. The JSF 2.0 classes were obtained from the NetBeans JSF 2.0 bundled library. In addition, we have used PrettyFaces, which provides support for JSF 2.0. You can download this distribution from http://ocpsoft.com/prettyfaces/. The PrettyFaces libraries (including necessary dependencies) are in the book code bundle, under the /JSF_libs/PrettyFaces JSF 2.0 folder.

First copy the PrettyFaces libraries into your application /WEB-INF/lib folder, and second, add into the web.xml descriptor the PrettyFaces filter, as shown next:

…
<filter>
<filter-name>Pretty Filter</filter-name>
<filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Pretty Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
…

Now, you are ready to use PrettyFaces into JSF applications.

How to do it...

PrettyFaces is able to work around URLs by reading a specific configuration file, named pretty-config.xml, which is responsible for mapping URLs to Faces Views. Such a file is listed next (this file is stored in the /WEB-INF folder):

<?xml version="1.0" encoding="UTF-8"?>
<pretty-config
xmlns="http://ocpsoft.com/prettyfaces-xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.com/prettyfaces-xsd
http://ocpsoft.com/xml/ns/prettyfaces/pretty-1.0.xsd">
<url-mapping id="1">
<pattern> /say_hello_1 </pattern>
<view-id>faces/hello1.xhtml</view-id>
</url-mapping>
<url-mapping id="2">
<pattern> /say_hello_2 </pattern>
<query-param name="hello" decode="false">
#{bean.hello}
</query-param>
<view-id>faces/hello2.xhtml</view-id>
</url-mapping>
<url-mapping id="3">
<pattern> /say_hello_3 </pattern>
<query-param name="hello" decode="false">
#{bean.hello}
</query-param>
<action>#{bean.upperHello}</action>
<view-id>faces/hello2.xhtml</view-id>
</url-mapping>
<url-mapping id="4">
<pattern> /say_hello_4 </pattern>
<view-id>#{bean.beanURL}</view-id>
</url-mapping>
</pretty-config>

As you can see a pretty-config.xml file is made from a set of <url-mapping> tags. Each tag maps a URL and is uniquely identified by the id attribute. The body of <url-mapping> can contain the following elements:

<pattern>/…/…/#{someBean.paramName}</pattern>

The <pattern> tag is required and it specifies which URL will be matched. Any EL expressions #{someBean.paramName} found within the pattern will be processed as value injection. This tag must appear only once per <url-mapping> tag.

<query-param name="key">#{someBean.queryParamValue}</query-param>

The <query-param> tag is optional and it defines a managed query parameter of the form http://my.site.com/url?key=somevalue, where if the parameter exists, the value will be injected into the specified managed bean. The name attribute is required and its value is a string representing the request value key. This tag also supports an optional attribute, named decode, which can be true (default) or false and it indicates if this <query-param> will/will not be URLDecoded. This tag can appear zero or more times per <url-mapping> tag.

Note

JSF commandLink and AJAX <f:param> values are also covered by the <query-param> tag.

<view-id>#{someBean.methodName}<view-id>

The <view-id> tag specifies the JSF view ID displayed by this mapping. It can be provided by a bean method (in this case the method must return an object for which the toString method will return the view Id) or by a String value. This tag must appear only once per <url-mapping> tag.

Note

The View Id may be any resource located within the current Servlet Context.

<action>#{someBean.methodName}</action>

The <action> tag specifies an action method to be called after URL parameters have been parsed and assigned into beans. This tag also supports two attributes: the phaseId attribute is optional and its value is a string indicating that this action should occur immediately after the specified phase (the default is after RESTORE_VIEW phase, but it can be RESTORE_VIEW, APPLY_REQUEST_VALUES, PROCESS_VALIDATIONS, UPDATE_MODEL_VALUES, INVOKE_APPLICATION, RENDER_RESPONSE, or ANY_PHASE).

Note

If the phase does not occur, neither will your action method. If ANY_PHASE is specified, the action method will fire on EVERY phase.

The second optional attribute is onPostback, which is a Boolean (default true). Set it to false if this action method should not occur on form postback.

This tag can appear zero or more times per <url-mapping> tag.

Now, you can see all these elements in the previous pretty-config.xml file. Next, we have developed a page to show how to call different other pages through Pretty. This page is named index.xhtml and is listed next:

…
<h:body>
<!-- example 1 -->
<h:outputLink value="say_hello_1">
<h:outputText value="HELLO (example_1)."/>
</h:outputLink>
<br/>
<!-- example 2 -->
<h:outputLink value="say_hello_2?hello=Adrian">
<h:outputText value="HELLO (example_2)"/>
</h:outputLink>
<br/>
<!-- example 3 -->
<h:outputLink value="say_hello_3?hello=Adrian">
<h:outputText value="HELLO (example_3)"/>
</h:outputLink>
<br/>
<!-- example 4 -->
<h:outputLink value="say_hello_4">
<h:outputText value="HELLO (example_4)"/>
</h:outputLink>
<br/>
</h:body>
…

And the bean used in this example is:

package beans;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class Bean {
private String hello = "";
public Bean() {
}
public String getHello() {
return hello;
}
public void setHello(String hello) {
this.hello = hello;
}
public void upperHello() {
this.hello = this.hello.toUpperCase();
}
public String beanURL(){
return "/faces/hello3.xhtml";
}
}

Now when you try to bookmark a URL managed by PrettyFaces you can see the "pretty" URL is used instead of the "ugly" one!

How it works...

PrettyFaces makes use of its own filter to intercept URLs. Once it captures a URL it resolves it against the pretty-config.xml file by accessing the corresponding <url-mapping> tag. When we bookmark a page the <pattern> body is bookmarked and the real URL is hidden.

There's more...

PrettyFaces also provides other facilities such as:

  • Using dynamic view ID capabilities
  • Using the Managed Query Parameter facility
  • Validating URL parameters
  • Wiring navigation into JSF action methods
  • Parsing complex / dynamic-length URLs
  • Accessing PrettyContext through EL
  • Rendering HTML links and URLs
  • Configuring logging (log4j)

See also

The code bundled with this book contains a complete example of this recipe. The project can be opened with NetBeans 6.8 and it is named: Bookmarking_JSF_pages_with_PrettyFaces.

More information about PrettyFaces is available at http://ocpsoft.com/prettyfaces/docs/.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset