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.
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.