April 8, 2012

Make JSF your friend again

Let me start by saying that I quite like JSF so I have spent a fair amount of time using it, so I know well enough what’s good and what’s bad about it and while I don’t think it’s god gift to Java Developers, I believe there is a definite pro in using a framework based on a specification that all the players in Java EE have to support.

What I find interesting lately is that I still get all the complaints about how bad JSF is, even though most arguments are only partially valid and mostly only apply to JSF 1.

These complaints aside, let’s look at some common misconceptions that people mention more frequently than others these days.

I can’t use HTML5 with JSF

Although it’s true that JSF uses Facelets as it’s primary view technology and thus on XHTML, it is far from the truth that you are bound to using XHTML 1.0 or 1.1. Even HTML5 has it’s „XHTML5“, or XML-serialized HTML5, which works perfectly fine with JSF.

Now although some browsers do have issues (*cough* IE *cough*) even with HTML5, don’t expect a walk in the park with XHTML5, you still have to jump all the hoops to make it render well (the display:block trick for many new elements comes to mind), but that’s really not JSF’s fault, now is it?

What you have to do though, is to follow the rules as set by W3, thus: In your Facelets template you start out with following chunk of XHTML:

<!DOCTYPE html>
<html xmlns=“http://www.w3.org/1999/xhtml“>
  <head>
    <title>Hello World</title>
    <meta charset=“UTF-8“/>
    <f:view contentType=“application/xhtml+xml“/>
  </head>
  <body>
    <p>Hello world</p>
  </body>
</html>

Wow, now that was simple, wasn’t it? So why do I have the <f:view>-tag in there? Well, it’s basically just to force JSF to always serve the content as the w3-mandated application/xhtml+xml for XML-serialized HTML5.

Now you legitimately wonder what happens if your browser didn’t even send that particular mime-type as accepted in it’s request headers? Well, I guess it’s always a gamble nowadays if your customer uses the „right browser“ when it comes to modern web technologies so you could always take your chances, but HTML5 validators may frown upon thee.

You can’t bookmark JSF-pages

Well, you’re not entirely wrong. Being a bit careless may cause grief, using a commandLink instead of a <h:link> gives the impression (wrongfully so) that you are on another page than the one you really navigated to.

Despite this being a bit of a nuisance it’s far from a universal truth. As I just mentioned, using normal HTML links (which do not have to be embedded in <h:form> either), you get the classic navigation that you’re used to and thus also a good bit more search engine friendly.

Now in conjunction with this I usually get to hear that it’s not possible to bookmark JSF pages since everything is „POST“ed. Also this is no longer valid in JSF 2 (and really it wasn’t valid in JSF 1 either, just a pain in the butt).

To simply fetch any URL parameters that the user (or your <h:link>) sends to a JSF-page you can add following snippet of code to your page:

<f:metadata>
  <f:viewParam name=“userName“ value=“#{userController.userName}“/>
</f:metadata>

An incoming ?userName=Daniel will apply the value Daniel to the property userName in our hypothetical UserController ManagedBean.

Now often setting a value alone doesn’t get you far, sometimes you want to have some sort of „prepare“-phase in your controller and really there are two simple ways that the backing bean can act upon the values that have been sent in the get parameter (please do not add extensive logic to your getters/setters, it’s awful).

Either you add <f:event type=“prerenderview listener=“#{userController.prepare}“/> or you could annotate the prepare-method in your UserController with the annotation @PostConstruct; however: the @PostConstruct is done before injection of query params, so if you need to act upon what's set then the annotation won't get you far. Only way out would be reading query params as we did in JSF1.

Easy as pie, that’s what it is.

You always have sessions

Hmmm... heard it a lot, don’t agree. People that tell me that very thing often present me with @SessionScoped cluttered over every managed bean since the whole viewstate and lifecycle stuff was a bit „too difficult to understand“. In those cases there is little you can do, SessionScoped creates sessions (hence it’s name). There are two scopes that you can use if you don’t like sessions and the first is RequestScoped and the second is ApplicationScoped. Using others will create a session and you’ll have to live with that.

However, there is a valid argument and that comes into play when you use server side state saving. JSF components have state and to restore a JSF components state it’s information hast o be stored somewhere. By default that ist he server and that’s where you get your session even if all you do is use @RequestScoped beans.

To prevent this, add following to your web.xml

<context-param>
  <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
  <param-value>client</param-value>
</context-param>

Doing this the component state will be embedded in the HTML file that is sent to the browser rather than in a session on your server.

Now is that faster, better, safer, more beautiful? No, No, No, Yes. It’s not unsafe per se, but as soon as you send something some consider „a secret“ to someone else (be it a cookie or whatever), you have to accept that somebody might want to put his or her big fat nose into it and look a bit closer.

Luckily, the good folks that worked on JSF gave us a mechanism to encrypt the view state when using client side state saving and if you use JSF on a public web site you should definitely do by setting a ClientStateSavingPassword in your web.xml.

JSF doesn’t work for long-running user sessions

This I hear quite a lot. It stems from the „ViewStateExpiredException“ and it must be one of the more commonly asked questions on internet forums in regards to JSF.

As I mentioned, JSF saves it’s component’s state (which has it’s advantages, trust me on that even though I will not go into detail about it) and as I said, this is either done on the client side or on the server side. As server-side state saving is the default you are both bound to run into trouble when either the session expires or the server does some optimizations (like dropping least recently used states). To prevent this problem I simply give the same recommendation twice, use client-side state saving.

Wrapping up

I know I could go into so much more detail on all this and give a fair amount of additional examples but all in all I just wanted to give you a quick run-through on common objections I get to hear about JSF and I want to show that these objections are not always valid. JSF may or may not be a good fit for your development needs, but at least you now know that you don't need to count it out just because you heard that it isn't even worth investigating.

2 comments:

Daniel Lyons said...

PrettyFaces improves the bookmark situation considerably.

Anonymous said...

http://www.its-not-its.info/