Configuration
Setting up PrettyFaces is simple.
- Configure PrettyFaces Filters in WEB-INF/web.xml
- Create the WEB-INF/pretty-config.xml file
(Steps 1 & 2 are required. Advanced features are optional.)
- Advanced Features
- Components
This step is pretty straight-forward, right?
or include a maven dependency in your pom.xml (optional)
<dependency>
<groupId>com.ocpsoft</groupId>
<artifactId>ocpsoft-pretty-faces</artifactId>
<version>1.2.2</version>
</dependency> |
<dependency>
<groupId>com.ocpsoft</groupId>
<artifactId>ocpsoft-pretty-faces</artifactId>
<version>1.2.2</version>
</dependency>
<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>
</filter-mapping> |
<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>
</filter-mapping>
<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="login">
<pattern> /login </pattern>
<view-id> /faces/login.jsf </view-id>
</url-mapping>
<url-mapping id="home">
<pattern> /home </pattern>
<query-param name="displayWelcomeMessage">#{homeBean.displayWelcomeMessage}</query-param>
<view-id> #{homeBean.getViewPath} </view-id>
</url-mapping>
<url-mapping id="viewStory">
<pattern>
/story/#{myBean.currentStoryId}/
</pattern>
<view-id> /faces/story/viewStory.jsf </view-id>
<action>#{myBean.loadStory}</action>
</url-mapping>
<url-mapping id="viewComment">
<pattern>
/story/#{myBean.currentStoryId}/#{myBean.commentId}
</pattern>
<view-id>/faces/story/comment.jsf</view-id>
<action>#{myBean.loadComment}</action>
</url-mapping>
</pretty-config> |
<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="login">
<pattern> /login </pattern>
<view-id> /faces/login.jsf </view-id>
</url-mapping>
<url-mapping id="home">
<pattern> /home </pattern>
<query-param name="displayWelcomeMessage">#{homeBean.displayWelcomeMessage}</query-param>
<view-id> #{homeBean.getViewPath} </view-id>
</url-mapping>
<url-mapping id="viewStory">
<pattern>
/story/#{myBean.currentStoryId}/
</pattern>
<view-id> /faces/story/viewStory.jsf </view-id>
<action>#{myBean.loadStory}</action>
</url-mapping>
<url-mapping id="viewComment">
<pattern>
/story/#{myBean.currentStoryId}/#{myBean.commentId}
</pattern>
<view-id>/faces/story/comment.jsf</view-id>
<action>#{myBean.loadComment}</action>
</url-mapping>
</pretty-config>
Each <url-mapping id=””> must specify a unique id. And contains the following attributes and elements, in order:
- <pattern>/blog/article/#{someBean.paramName}</pattern> – Specify the pattern for which this URL will be matched. This element is required, and has a multiplicity of 1 (only one)
- <query-param name=”key”>#{someBean.queryParamValue}</query-param> – Defines a managed query parameter of the form http://site.com/url?key=somevalue, where if the parameter exists, the value will be injected into the specified managed bean. This also handles JSF commandLink and AJAX <f:param> values. This element is optional, and has a multiplicity of 0…N (zero or more)
- <view-id>#{someBean.methodName}<view-id> – Specify the JSF view ID displayed by this mapping, by either calling an el Method (must return an object for which the toString() method will return the view Id) or using a literal value. This element is required, and has a multiplicity of 1 (only one)
- <action>#{someBean.methodName}</action> – Specify an action method to be called after URL parameters have been parsed and assigned into beans. This element has a multiplicity of 0…N (zero or more)
Order of processing:
- URL pattern parsing, query-parameter handling, and value injection into JSF managed beans.
- View-Id calculation (if a view Id is dynamic, the el method will be called.)
- JSF gains control of the request via RequestDispatcher.forward(“/context/faces/viewId.jsf”).
- Action methods called before RESTORE_VIEW phase, unless the optional phaseId attribute is specified.
Valid values for this attribute are: RESTORE_VIEW, APPLY_REQUEST_VALUES, PROCESS_VALIDATIONS, UPDATE_MODEL_VALUES, INVOKE_APPLICATION, RENDER_RESPONSE, ANY_PHASE.
Note however, that if the phase does not occur, neither will your action method.
Dynamic view IDs allow a mapped URL to display content from any JSF view. This is prevents doing redirects which would otherwise destroy information stored in the URL, and also provides some extra functionality for application design.
public class ManagedBean
{
public String getViewPath()
{
// This method returns the path of the JSF view to display
// when the URL /home is accessed.
if(user.isLoggedIn())
{
// Note: the extension '.jsf' is the mapped faces extension
return "/faces/home.jsf";
}
// The home page can instead display a different view; return
// the pretty:mappingId of the view you wish to display.
// Note that this will not cause a redirect, and will not
// change the client browser URL.
// If you wish to issue a redirect, you should use a page
// load action instead of a dynamic view Id function.
return "pretty:login";
}
} |
public class ManagedBean
{
public String getViewPath()
{
// This method returns the path of the JSF view to display
// when the URL /home is accessed.
if(user.isLoggedIn())
{
// Note: the extension '.jsf' is the mapped faces extension
return "/faces/home.jsf";
}
// The home page can instead display a different view; return
// the pretty:mappingId of the view you wish to display.
// Note that this will not cause a redirect, and will not
// change the client browser URL.
// If you wish to issue a redirect, you should use a page
// load action instead of a dynamic view Id function.
return "pretty:login";
}
}
Managed query parameters allow automatic assignment of values into JSF managed bean fields, instead of parsing and URL Decoding the value manually out of the request object.
Examining this sample mapping, we can see that the developer has specified two managed query-parameters. The ‘sortBy’ and ‘itemId’ parameters.
<pretty-config>
<url-mapping id="itemList">
<pattern> /items/list </pattern>
<query-param name="sortBy">#{itemBean.sortByField}</query-param>
<query-param name="itemId">#{itemBean.currentItemId}</query-param>
<view-id> /faces/items/list.jsf </view-id>
<action>#{itemBean.loadItems}</action>
</url-mapping>
</pretty-config> |
<pretty-config>
<url-mapping id="itemList">
<pattern> /items/list </pattern>
<query-param name="sortBy">#{itemBean.sortByField}</query-param>
<query-param name="itemId">#{itemBean.currentItemId}</query-param>
<view-id> /faces/items/list.jsf </view-id>
<action>#{itemBean.loadItems}</action>
</url-mapping>
</pretty-config>
The managed bean that accompanies this mapping:
public class ItemBean
{
private List<Item> items;
private Integer currentItemId;
private String sortByField;
public String deleteItem()
{
// currentItemId will be automatically populated by
// PrettyFaces if the parameter was passed in the request
// (see example JSF page below)
ItemManager.deleteById(currentItemId);
// Redisplay the current page via redirect.
return "pretty:"
}
public void loadItems()
{
// The sortByField member will be null if the sortBy
// query-parameter is not found in the request
this.items = ItemManager.getSortedItems(sortByField);
}
//... getters and setters...
} |
public class ItemBean
{
private List<Item> items;
private Integer currentItemId;
private String sortByField;
public String deleteItem()
{
// currentItemId will be automatically populated by
// PrettyFaces if the parameter was passed in the request
// (see example JSF page below)
ItemManager.deleteById(currentItemId);
// Redisplay the current page via redirect.
return "pretty:"
}
public void loadItems()
{
// The sortByField member will be null if the sortBy
// query-parameter is not found in the request
this.items = ItemManager.getSortedItems(sortByField);
}
//... getters and setters...
}
Example JSF page: Notice the <f:param> tag.
This will generate a link that provides the ‘itemId’ parameter to the request for PrettyFaces to parse.
<c:forEach var="item" items="${itemBean.items}">
<h:commandLink>
Delete this item.
<f:param name="itemId" value="${item.id}" />
</h:commandLink>
</c:forEach> |
<c:forEach var="item" items="${itemBean.items}">
<h:commandLink>
Delete this item.
<f:param name="itemId" value="${item.id}" />
</h:commandLink>
</c:forEach>
public class PageBean
{
public String goHome()
{
// this will tell pretty to redirect the client to the home-page
// no parameters are mapped, so this is pretty simple
return "pretty:home";
}
public String goHomeAndWelcome()
{
// this will tell pretty to redirect the client to the home-page
// since there is a managed query-parameter defined in the mapping,
// PrettyFaces will generate the URL, and append the mapped param
// eg: /home?displayWelcome=true
homeBean.displayWelcomeMessage(true);
return "pretty:home";
}
public String goViewStory()
{
// this will tell pretty to redirect the client to the viewStory page
// PrettyFaces will generate the URL by extracting any values from
// the mapping beans and using them to inject back into the pattern
// therefore, navigation can be controlled by placing a value into
// the mapped field before PrettyFaces extracts it and generates the URL
// so... /story/#{myBean.currentStoryId}/ ...becomes... /story/12/
viewStoryBean.setCurrentStoryId(12);
return "pretty:viewStory";
}
public String doRefreshByRedirect()
{
// using the "pretty:" prefix without a mapping-id will cause a
// redirect to the current page
return "pretty:";
}
public String doNormalJSFRender()
{
// returning an value without the "pretty:" prefix will fall back to
// the default JSF navigation handlers
return "someNavigationCase";
}
} |
public class PageBean
{
public String goHome()
{
// this will tell pretty to redirect the client to the home-page
// no parameters are mapped, so this is pretty simple
return "pretty:home";
}
public String goHomeAndWelcome()
{
// this will tell pretty to redirect the client to the home-page
// since there is a managed query-parameter defined in the mapping,
// PrettyFaces will generate the URL, and append the mapped param
// eg: /home?displayWelcome=true
homeBean.displayWelcomeMessage(true);
return "pretty:home";
}
public String goViewStory()
{
// this will tell pretty to redirect the client to the viewStory page
// PrettyFaces will generate the URL by extracting any values from
// the mapping beans and using them to inject back into the pattern
// therefore, navigation can be controlled by placing a value into
// the mapped field before PrettyFaces extracts it and generates the URL
// so... /story/#{myBean.currentStoryId}/ ...becomes... /story/12/
viewStoryBean.setCurrentStoryId(12);
return "pretty:viewStory";
}
public String doRefreshByRedirect()
{
// using the "pretty:" prefix without a mapping-id will cause a
// redirect to the current page
return "pretty:";
}
public String doNormalJSFRender()
{
// returning an value without the "pretty:" prefix will fall back to
// the default JSF navigation handlers
return "someNavigationCase";
}
}
4.1 The pretty:link component
PrettyFaces provides a JSF component to output an HTML link to the page. The link tag requires a mapping-id (specified in the pretty-config.xml,) identifying which link to render.
If the provided mappingId requires any url-pattern-parameters or managed-query-parameters, they can be passed in via the <f:param> tag.
Url pattern parameters do NOT have a name attribute, and are parsed in the order they are passed into the tag. Managed-query-parameters DO have a name attribute, and order is irrelevant.
For Example: The viewComment pattern requires:
<!-- From pretty-config.xml, viewComment mapping-id, above:
/story/#{myBean.currentStoryId}/#{myBean.commentId}-->
<%@ taglib prefix="pretty" uri="http://ocpsoft.com/prettyfaces" %>
<pretty:link mappingId="comment">
<f:param value="#{myBean.currentStoryId}"/>
<f:param value="#{myBean.commentId}"/>
Go to Comment. (This is Link Text)
</pretty:link> |
<!-- From pretty-config.xml, viewComment mapping-id, above:
/story/#{myBean.currentStoryId}/#{myBean.commentId}-->
<%@ taglib prefix="pretty" uri="http://ocpsoft.com/prettyfaces" %>
<pretty:link mappingId="comment">
<f:param value="#{myBean.currentStoryId}"/>
<f:param value="#{myBean.commentId}"/>
Go to Comment. (This is Link Text)
</pretty:link>
4.2 The pretty:urlbuffer component
PrettyFaces provides a JSF component to generate a URL for use as a page scoped variable through El. This tag requires a mapping-id (specified in the pretty-config.xml)
If the provided mappingId requires any url-pattern-parameters or managed-query-parameters, they can be passed in via the <f:param> tag.
Url pattern parameters do NOT have a name attribute, and are parsed in the order they are passed into the tag. Managed-query-parameters DO have a name attribute, and order is irrelevant.
For Example: The viewItem pattern requires:
<!-- From the managed-query-parameter section above, itemList mapping-id.-->
<pretty:urlbuffer
var="itemListUrl"
mappingId="itemList">
<f:param name="itemId" value="22" />
<f:param name="sortBy" value="price" />
</pretty:urlbuffer>
<h:outputText
value="Generated Url Is: #{requestScope.itemListUrl}" />
<!-- /items/list?itemId=22&sortBy=price -->
<br/> |
<!-- From the managed-query-parameter section above, itemList mapping-id.-->
<pretty:urlbuffer
var="itemListUrl"
mappingId="itemList">
<f:param name="itemId" value="22" />
<f:param name="sortBy" value="price" />
</pretty:urlbuffer>
<h:outputText
value="Generated Url Is: #{requestScope.itemListUrl}" />
<!-- /items/list?itemId=22&sortBy=price -->
<br/>
This design is intended to reduce complexity and prevent manual manipulation of URLs.
Finished. Run your application!
You should now have a fully functional PrettyFaces configuration.