Saturday, January 29, 2011
RESTful URLs, with JSF 2
JSF 2 introduced the ability to create RESTful URLs with the introduction of the <f:viewParam> tag. The tag is easy enough to use, you simply place it in the <f:metadate> tag, and configure the attributes to decode the url.
<f:metadata> <f:viewParam /> </f:metadata>
There are no words to explain how great a feature this is for JSF. The old “every request is a POST” theory didn’t pan out. RESTful URLs are bookmarkable, and meaningful to end-users. Unfortunately they are still a bit tricky to use in vanilla JSF, as there are only three backing bean scopes in “vanilla” Java EE 6 that are capable of dealing with business transactions/conversations, and each currently has it’s own set of limitations. They are the Session, Conversation, and View scopes
First the Session scope – don’t use it! The Session scope is essentially global for your user as they interact with your web application; there is no concept of a business conversation. In short, you’ll end up with a scalability issue as your session fills up with business objects that are no longer relevant to the current user task.
The second scope to consider is the Conversation scope introduced in Java EE 6 with CDI. It can span multiple requests, but is shorter lived than the Session. It at first seems great, but if you’re not careful, it breaks the concept of RESTful URLs by tagging the nasty little “cid=#” parameter to your query string. If the user bookmarks, or otherwise shares the URL, a conversation expired exception will be thrown when the URL is later reloaded. This quickly becomes a burden to try and deal with. This is something that is fixed with Weld 1.1, but I’ve got apps to write today!
I’m very hopeful that with Weld 1.1, and the fix of issue WELD-549, that I will be able to make better use of Conversation scoped beans. I will the be able to navigate between URLs (with faces-redirect=false) with conversation scoped beans, and not have to worry about the “cid=#” parameter showing up in my URLs when the user performs navigations not relevant to the current conversation. At least hopefully this will be the case!
Additionally and/or alternatively, we need more scopes. Something like the ViewAccess scope I last blogged about, where the developer doesn’t have to think about bean scope so much. Just write your app, and have the framework do the right thing.
Please share your thoughts if you’ve got another way of working with RESTful URLs in your JSF apps, I would love to hear about it!