JSF is an immature technology. As such, JSF developers need to deal with lack of best practices, realistic sample code, or clear workarounds to common problems.
Last year's Berkeley Pilot Gradebook project wrestled with a number of design and usability issues after mimicking what little sample code we found.
That code emphasized JSF's "pull" approach to MVC, with backing beans concentrating on business logic rather than slavishly modeling individual web pages, and JSF tags and backing beans both making direct reference to domain objects. Such an emphasis was understandable in a way, since it underlined a key difference between JSF and Struts, and went along with Sun's hopes for a Microsoft-like blending of web and non-web components. Unfortunately, it didn't help much with near-term web application development. Results included:
- Unpredictability - Our backing beans would do database queries (sometimes) when a getter gets called and the code hits a null value. That meant we could't really be sure when the queries are being done or for what. Some DB queries were being done in the Apply Request Values phase, some in the Process Validations phase, and some in the Render Response phase. We'd unexpectedly display old data instead of freshening from the DB. Or we'd add a "rendered" check to a button and find that submits had stopped working.
- Tangled classes - We'd start off assuming that individual pages shared a great deal of underlying logic, have them share backing beans, and then slowly clutter the bean code with page-specific logic.
- Loss of request threads (aka "page flows") - Over and over again, we found ourselves unable to maintain request-to-request page states in what seemed like a "normal" web way, and were forced to move beans to session scope. This led to...
- Loss of normal browser functionality - Because we kept page state in a session-wide context, users could no longer take advantage of many of the usual benefits of a web application, such as multiple data views (one browser window shows how Section 1 is doing, another browser window shows Section 2, and the user compares the two) and "what if?" or preview support.
- Stale data - Since the session-scoped data wouldn't automatically disappear at the end of a request thread, by default that data would hang around till the session died. We would need to explicitly clean it up on every navigation path.
- Extra memory consumption - Since session-scoped data was maintained by the server, memory consumption increased and scalability decreased as beans were moved into session scope.
For a pilot, all this was tolerable (barely). We wanted to avoid these problems in the Sakai 2.0 Baseline Gradebook, since it needs to be a fairly firm foundation for future development.