LogikDevelopment
Posts Tagged Faces Navigation
How to personalise the URLs with Faces Navigation?
This is an important question if you want to have search engine friendly URLs on your website!
But unfortunately, the solution is not straightforward with JavaServer Faces (JSF). 🙁
First of all, for security reason JSF doesn’t allow you to use the GET method for your forms. I didn’t really understand why but this is very (too) restrictive!
Can you imagine Google doing the same thing? We would have the same URL for every search terms http://www.google.co.uk/search
instead of something like http://www.google.co.uk/search?hl=en&safe=off&esrch=FT1&q=test&meta=&aq=f&aqi=g10&aql=&oq=&gs_rfai=
.
It wouldn’t be very easy to share a search page with a friend if Google was using the POST method. 😉
So the question is how to get around this JSF limitation?
Let’s take a look at how would look our faces-navigation.xml
file for a search page:
<navigation-case> <from-action>#{searchBean.searchAction}</from-action> <from-outcome>success</from-outcome> <to-view-id>/search.xhtml</to-view-id> <redirect /> </navigation-case>
In this example, all the JSF elements calling the action searchBean.searchAction
will be redirected to the search.xhtml
page.
But, how are we going to get the search parameters into the URL?
Ideally, it would be great to be able to do something like the following:
<navigation-case> <from-action>#{searchBean.searchAction}</from-action> <from-outcome>success</from-outcome> <to-view-id>/search.xhtml?q=#{param.q}</to-view-id> <redirect /> </navigation-case>
This solution would allow us to inject EL expressions into the URL before the page is redirected to the destination page.
In order to do this, we need to create our own view handler and register it to our application. 😎
The code below is the view handler class which also includes some comments:
package com.logikdev.gui.handler; import javax.el.ExpressionFactory; import javax.el.ValueExpression; import javax.faces.application.ViewHandler; import javax.faces.context.FacesContext; import com.sun.facelets.FaceletViewHandler; /** * Overrides the Facelet view handler to support EL expressions in URLs. * @author Stéphane Moreau */ public class DynamicViewHandler extends FaceletViewHandler { public DynamicViewHandler(ViewHandler parent) { super(parent); } /* (non-Javadoc) * @see com.sun.facelets.FaceletViewHandler#getActionURL(javax.faces.context.FacesContext, java.lang.String) */ @Override public String getActionURL(FacesContext context, String viewId) { String queryString = null; // Replace the EL expressions in the URL ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory(); ValueExpression valueExpression = expressionFactory.createValueExpression(context.getELContext(), viewId, String.class); String result = (String) valueExpression.getValue(context.getELContext()); // Separate the query string from the URL int dotIndex = result.lastIndexOf('.'); int questionMarkIndex = result.indexOf('?'); if (questionMarkIndex != -1) { queryString = result.substring(questionMarkIndex, dotIndex); viewId = result.substring(0, questionMarkIndex) + result.substring(dotIndex); } // Call the parent without the query string result = super.getActionURL(context, viewId); // Put back the query string at the end of the URL if (queryString != null) { result += queryString; } return result; } }
And the following is the code to put in the faces-config.xml
file in order to register the newly created view handler to the application:
<application> <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver> <view-handler>com.logikdev.gui.handler.DynamicViewHandler</view-handler> </application>
One last thing!
This view handler also has a limitation which I wasn’t able to fix. 🙁 The file extension has to ALWAYS be placed at the end of the to-view-id
URL! The view handler will then put it back before the question mark.
For example:
<navigation-case> <from-action>#{searchBean.searchAction}</from-action> <from-outcome>success</from-outcome> <!-- The extension has to be at the end --> <to-view-id>/search?q=#{param.q}.xhtml</to-view-id> <redirect /> </navigation-case>
If you perform a search on ‘jsf’ with the above navigation rule, the user will be redirected to the page /search.xhtml?q=jsf
.
EL expressions, Faces Navigation, Java, JSF, SEO, view handler
Share this
Archives
- March 2014 (2)
- September 2013 (1)
- August 2013 (1)
- July 2013 (1)
- June 2013 (1)
- February 2013 (1)
- January 2013 (1)
- December 2012 (1)
- September 2012 (1)
- August 2012 (1)
- June 2012 (1)
- May 2012 (1)
- April 2012 (3)
- February 2012 (1)
- December 2011 (3)
- November 2011 (2)
- October 2011 (2)
- September 2011 (2)
- July 2011 (1)
- June 2011 (2)
- May 2011 (2)
- April 2011 (2)
- March 2011 (2)
- February 2011 (2)
- January 2011 (2)
- December 2010 (1)
- November 2010 (2)
- October 2010 (3)
- September 2010 (1)
- August 2010 (2)
- July 2010 (1)
- June 2010 (2)
- May 2010 (3)
- March 2010 (2)
- February 2010 (3)
- January 2010 (2)
- December 2009 (3)
- November 2009 (3)
Tags
Ajax Amazon S3 Arch Linux backup bash benchmarking Bug cron D-Link decryption DNS-313 DNS-323 encryption Html Internet Explorer IOzone Java JavaScript javax.crypto JSF Linux locale Mac OS X Monitoring MyFaces MySQL OAuth onclick OpenSolaris PHP Raspberry Pi RichFaces s3sync Samba shell SQL Server Tomcat Twitter Twitter4J UTF-8 VBScript virtual storage pool Windows Zabbix zpool