JSP Nightmares

jsp-nightmare.jpgOnce upon a time as a Java newbie, I thought that Java Server Pages were great. Back then I had done web development in Perl and PHP and I was pleasantly surprised by the similarity of the development process. It's as simple as write and run. No bothersome compiler runs and deployment cycles. Java Server Pages seemed like PHP on steroids. Actually, I still think this is a fairly accurate description. It's what the designers of JSP intended – Java's answer to dynamic web scripting languages. The question is whether the JSP design is sound. After having spent several years in the Java Enterprise world, and having maintained large amounts of JSP code, I am convinced that it isn't. So I am writing this article to tell you the untold nightmares of JSP programming.

Before we are going into that, let's briefly look at the bright side. JSP technology is tempting for several reasons. First, it is mainstream and it bears the official stamp of approval by Sun. Second, it is an integral part of JEE and widely supported by application servers and tools. Third, it it is relatively easy to whip up dynamic content with JSP. So, why not use Java Server Pages? Well, there are several problems, the biggest of which are scriptlets. Scriptlets are embedded Java code. Because JSP allows you to mix Java code with markup, you get hybrid files which tend to become messy and difficult to maintain. Few HTML designers understand what's going on in a JSP file. Few programmers are comfortable with mixing their code with reams of markup.

The typical production process for a JSP-based application looks like this: the UI designers finish their protoypes and hand over the resulting markup to the programmers. The programmers tear apart the HTML to make it easier to insert code, repeat  sequences, and insert display logic. Once the programmers are finished, there is absolutely no chance that the designers will recognise the markup they produced. It is therefore also unlikely that they will ever touch it again. Even if the finished product contains no scriptlets, JSTL, expression language and (God help us) custom tags will confuse the hell out of designers. This means that the entire process has to be repeated,  everytime a change of visuals is requested. This is however not the worst problem.

The biggest drawback is that there is absolutely no way to prevent application logic from creeping into the JSPs which ultimately leads to spaghetti code. You might think, “Oh well, I know how to code my JSPs properly.” At this point you should remember Murphy's law, especially the part that says: “if something can go wrong it will go wrong.” Perhaps you are a disciplined individual who wouldn't even dream about putting application logic into a JSP file. But can you say the same about the other programmers in your team? What if work needs to be completed under time pressure? Can you resist the temptation to solve a problem quick-and-dirty by putting a hack into a JSP file along with a “will fix this later” note? I have seen way too many “will fix this later” notes in JSPs and most of them were several years old.

My project consisted of an application with roughly 1.5 million LOC where about half of the code was implemented in JSPs. That's about 1500-2000 JSP files. Most files were less than 500 lines, but some were in excess of 2000 lines. Once you hit upon an XL-sized JSP, it's a safe bet that some crucial functionality is buried in it. Reading and understanding a 2000 line JSP can take several hours. Modifying and maintaining it is quite another deal. The project did not attempt to separate business logic from display logic in JSPs, thus XML was liberally mixed with scriptlets. While this approach works OK for narrow functionality that can be coded  in a single JSP, it becomes very unwieldy for functionality that spans a larger problem space and, hence, many JSPs.

The “solution” for this was to use scriptlet fragments which are shared by multiple JSPs. This isn't a real solution, however, because it forgoes almost all advantages of using an OOP language, such as abstraction, encapsulation, inheritance, and as a side effect it produces “ultra-tight coupling” between JSPs that use the same fragments. In theory, this can be made slightly less painful by defining inner classes in fragments for shared functionality. These class fragments are then included in the consuming JSPs at compile time. However, inner classes have their own limitations and compile time includes bulk up the resulting byte code. Since inner classes can access variables and methods in the outer scope, they lack proper encapsulation. Tying them to multiple consumers can lead to some weird dependencies and logical errors. Finally, there is no way to produce unit tests for scriptlets. The only way to test scriptlets is by inserting the test code directly into the JSP, which is obviously insane. In summary, there is no way to code scriptlets cleanly, so it's best to avoid them.

But even without scriptlets, there's plenty of trouble. For example, there is the Java standard tag library (JSTL) and the expression language (EL) which are supposed to replace scriptlets as coding instruments. In particular, the EL has been praised as enabling clean coding for MVC applications with Java Server Pages as view component. – Well, I disagree. – JSTL+EL are neither very clean nor very concise. What is worse, they are too powerful for their own good. JSTL+EL are Turing-complete, just like XSLT which they resemble, which means that replacing scriptlets with JSTL+EL is like jumping from the frying pan into the fire. In addition, JSTL provides tags that allow programmers to access a database and execute queries. If you see MVC going out of the window at this point, you have recognised the problem. In summary, JSTL+EL produce the same problems as scriptlets, but with an XML syntax.

In conclusion, Java Server Pages can lead to maintenance nightmares, especially when used in a large project. While it is possible to code JSPs cleanly, it is apparently not a widespread practice, which is probably Murphy's law taking its toll. Hence, if you are building a new Java web application, think twice about using JSP. If you have a legacy application, you might want to replace JSPs by something more appropriate. In most cases, this can be done gradually whereas legacy JSPs can run side by side with an alternative view technology.

JSF – Productivity vs. Scalability

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.