I seized the opportunity at the recent Atlanta Java Software Symposium to attend both of David Geary's sessions on JavaServer Faces, and left the sessions terrified. I mean seriously, what's with running JavaServer together? Is this a new Sun marketing term, the JavaServer?
So what's the scoop? First of all, make no mistake about it – JSF is designed to replace Struts, Tapestry, etc. as THE standard J2EE model for MVC. So what's the problem? Some problems in the current version will, in fact, go away. David seems to be very aware of some of the pain points developers have found in the current rev of JSF, and committed to getting those things remedied. That being said, there are still some very deep seated problems that will certainly affect my eagerness to adopt this new standard. (Being practical, I will certainly learn enough to remain current, and enough to maintain/attain whatever form of employment I’m after.) I believe the main problems revolve around redundancy with Struts and indecision in the API.
The redundancy angle is somewhat necessary, in that it needs to replace Struts in order to justify its existence, but think of it in terms of taking Struts and making it more cumbersome. JSF has an Action to match Struts' actions, a Form much like ActionForm, a hidden controller powered by faces-config.xml (much like struts-config.xml). It has validation, and message bundle support for internationalization. At present, you have to specify WHICH bundle to use for pretty much every message you want to output, but it seems like that will be fixed. In essence, you have MOST of the things you’ve come to expect from Struts, plus a “LifeCycle”, which may or may not be exposed to the developer in the end, plus an event model, and with some glaring omissions.
It lacks some of the Struts 1.1 features that made life easier, such as the DynaForm, so we're back at the Struts 1.0 square-one of proliferating an inordinate number of classes to make a simple app.
Now for the indecision in the API. This was glaringly exposed to me in an example of how to log inside of a JSF action using Servlet logging. The line of code to do this was:
((ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext()).log(“What a pain!!”);
The JavaDoc for FacesContext indicates that this approach is taken so that the application isn’t necessarily aware of its container. But wait – getContext() returns an Object, so in order to do ANYTHING meaningful, we need to be aware of our container. The example cited is a ServletContext vs. a PortletContext. The Portlet spec states this about a PortletContext: “The PortletContext must offer access to the same set of resources the ServletContext exposes.” So one would HOPE that PortletContext would actually extend ServletContext, but this seems to have been left hanging in the Portlet specification.
The overall point here is that so much trouble has been taken to remain independent of context of the container and of the client, yet certain things baked into the fabric of JSF are implicitly dependent on aspects of the container or client. A key example of this is one of JSF’s new concepts (compared to Struts) of an event listener – there are two types of listeners – an action listener, and a value-changed listener. The value-changed listener supposedly responds to changes to a form field – the example given was that of changing the country, and adjusting the address fields to match the new locale. The problem with this concept is the assumption that the client has a meaningful way to relay this event back to the server. For any sort of wireless device, this is a non-starter. It certainly applies for standard HTML and possibly XUL, but this concept is VERY MUCH tied to the capabilities of the client. Even when you want to place the event in an HTML page, you have to code your own Javascript to submit the form on update of the field, and it’s hardly distinguishable from submitting the form (sadly, it even causes validation errors to show up, even if your only intent was to reconfigure the form, and even if the user didn’t even have the opportunity to fill in that field yet!).
So in general, some of JSF seems to trip over itself to remain independent of environment, while at other times, it paints itself into a corner to match Microsoft WebForm functionality. One things Struts, when combined with the JSTL tags, does is that it picks what it wants to do, and does it well. In its current state, JSF seems to be completely unfriendly to developers unless they have a tool to handle all the nasty under-the-covers stuff, which may, perhaps, be the point (sell licenses of Project Rave). Another inevitable and unfortunate consequence is the pending arrival of <vendor>-faces-config.xml. I blame the vendors for this, mostly – both in their desire to lock you into their platform, and their influence in the JCP that leaves so many things intentionally ambiguous so that they NEED to provide vendor-specific deployment descriptors.
Perhaps JSF 2.0 will be ready for prime time, but unless you plan to start “Rave”-ing from Day 1, developers seem best served continuing work with their framework of choice – JSF doesn't buy you anything you need, and forces you into a whole lot that you don't.
A very good debunking of JSF
Question why didn’t Sun just accept Struts as the standard and be done with it?
I am interested in your experience with Liferay as we are looking at it at the moment trying to decide whether to use it or not. Did you get your project done with it? Sorry about posting this as a comment I could not find your email or a contact form.
Best regards
Anja Beckmann