JSF - Productivity vs. Scalability

2009-03-11

In my everlasting quest to find the perfect web framework (it’s futile, I know!) I spent a few more weekends, this time with Java Server Faces. I first got acquainted with JSF two years ago when I played around with Java Studio Creator and I remember being quite impressed by it. I even used it in a small project, which taught me a lot about the practical side of JSF. However, I did not get a deeper understanding until recently when I read Java Server Faces in Action by Kito D. Mann and Core Java Server Faces by David Geary and Cay Horstmann, both excellent books by the way.

I like RAD tools ever since I worked with Delphi more than a decade ago. In many ways, Delphi was the perfect solution for creating Windows GUI applications. It allowed me to create high-performance apps with great ease and tremendous productivity. When I first came across JSF, I realised it holds a similar promise for the field of web development. In my view, RAD is the most attractive way to create applications. It many not be the best choice for every type of application, but I am sure it is the best choice for a large percentage of run-of-the-mill commercial apps. The UI-centred approach of RAD tools makes prototyping very easy and it gives development projects a certain “users first” bent which I always found useful in project management.

When communicating with customers, a quick mock up screen always beats a bunch of UML diagrams. In addition, I like the idea of high-level encapsulation offered by the visual component concept that RAD tools are known for. This high-level encapsulation, if properly implemented, should be able to be extended to non-visual components, so that business logic might benefit from the same mechanism. Of course, in Java all you need are Java Beans (POJOs) for this purpose.

JFS is the attempt to apply a GUI-like component model to web applications. It has an extensible set of visual components, such as text boxes, list boxes, tabs, AJAX widgets, and data-aware widgets. Strictly speaking, the widgets themselves sit on top of JSF. JSF defines the component architecture and an application framework that includes things such as validators, converters, events, listeners and navigation rules. Like GUI widgets, JSF widgets are stateful. The JSF architecture makes this completely transparent to the application. This means, the application is oblivious of the stateless HTTP protocol, or whatever other protocol might be used. It doesn’t need to take care of preserving and/or restoring state. Sounds a bit like magic, doesn’t it? If you look into the internals of JFS, however, it becomes clear that this magic is created at a heavy cost. The first thing to look at is the 6-phase JSF request lifecycle:

  1. Restore View
  2. Apply Request Values
  3. Process Validations
  4. Update Model Values
  5. Invoke Application
  6. Render Response

Most of these phases do event processing. Quite a bit of additional processing compared to an average web app. But that is only part of the problem. The reasons for doubt lie in the first phase called “restore view”. It implies that the server maintains an internal representation of the view. When the view is restored, JSF creates a component tree in memory that represents the client view.

If you think, this might be a bit memory-intensive, you are probably right. Unfortunately, JSF doesn’t stop there. Component state is typically stored in what is called managed beans. A managed bean is merely an conceptual extension of a JSP backing bean. “Managed” means that the bean is declared in an XML file and that it is allocated automatically when needed by the JSF framework. However, it is not automatically deallocated, unless it is in page or request scope. Sounds like a memory eater? To me it does. Since managed beans are typically allocated in session scope, I imagine that a single client can quickly gobble up many Megabytes or more on the server.

Of course you need session data in any web app. In this regard, JSF isn’t different from other web apps. However, with dozens or hundreds of beans floating around in session memory and new ones being added without direct application intervention, I’d argue that the programmer loses fine-grained control over memory requirements. I can’t help asking: does JSF scale?

Many people think it doesn’t. One might even ask further, whether replicating client state on the server is scalable at all. Is it the right approach? I can’t answer the last question, but I’ll think twice about using JSF in future projects. Probably one doesn’t need to be concerned about applications that don’t go beyond the departmental level with a few dozen concurrent users. But what about a few hundred or a few thousand concurrent users? Even if you create an application for small scale use, it’s not an attractive choice to use a non-scalable architecture. Who knows how the application will eventually evolve and who will use it? As things stand now, JSF seems like a trade-off to me. You get RAD productivity at the expense of scalability. Or isn’t this the case? I think the burden of proof is with the JSF camp.