30 November 2009

JSP Considered Harmful

Why JSPs aren't good in Model 2 web applications

Model 1 is a design approach for web applications. In this approach, one servlet is responsible for handling a browser request from beginning to end - it receives the request, runs the business logic that performs the necessary operations (which more often than not involves database access), and generates output in HTML (or possibly in other forms such as XML, PDF and image data; for the purposes of this article I'm concerned primarily with HTML).

Model 1 is okay for small web applications but it really isn't very well suited to larger ones; because the view - the part that generates the HTML - is embedded in the same servlet that performs the business logic, making modifications to the view risks damaging the business logic. Imagine that you have a fairly large application and you decide to update the look and feel of the whole website; you'd have to modify every servlet.

Early Model 1 applications written as servlets had another problem in that the generation of HTML was performed by Java code. That meant that the servlet developers had to write code to generate that HTML, usually working with a web designer who provided the HTML. Obviously this wasn't a very efficient way of working.

The answer to this was JSP, which has often been described as 'inside-out servlets'. The idea is simple: instead of writing servlets that perform business logic and embed the HTML, a JSP is essentially an HTML file that has the business logic embedded as 'scriptlets' of explicit Java code. At run time a JSP compiler translates the JSP to Java source then compiles that source to class binaries that are then loaded in the normal way. (In some systems the JSP compiler generates bytecodes directly, without the intermediate Java source). This means that HTML designers can produce basic JSPs then hand the result over to a Java developer who can add in the scriptlets to perform the business logic.

However the business logic and the view are still contained in one file, which can still lead to the same kinds of problems - if you change the page layout you risk damaging the business logic and vice-versa.

Model 2 is intended to solve this problem. Model 2 decouples the business logic from the view, minimising the dependencies and making it possible, at least in principle, to make changes to the business logic or to the view without requiring changes on the other side of the fence.

This is where the problems begin for JSP. It's very easy to embed business logic in a JSP - that's the whole point when you consider that JSP is a Model 1 technology. However it's this very same point that makes JSP a bad fit for Model 2; it's simply too easy to drop code that really belongs in the business logic into a JSP. As a result novice developers often do just that and even seasoned developers do it from time to time, especially when a quick'n'dirty fix is needed to cure a production problem in a hurry. The result is business logic that's split between the servlet where it belongs and the JSP that should really contain only view logic. Ideally the scriptlets in a JSP for a Model 2 application should be doing no more than pulling data from the model and formatting it for presentation; any more than that probably belongs in the business logic. Maintaining this separation is a matter of discipline on the part of the developer because there's nothing in JSP to enforce it.

Struts was probably the first Model 2 framework for Java web applications although it's difficult to be certain. According to an article I read a year or two ago (I don't remember where I read it or who wrote it, and I haven't been able to find it through Google, so I can't back any of this up...), the people who developed Struts recognised that this was a problem. However they released Struts and advocated JSP as the view layer, for a number of reasons: first, there was no other mature view technology available at the time. They could have developed a more suitable package as part of Struts but getting something like that into a stable condition would have delayed the release of Struts by close to a year. Further, it would have meant that web developers wanting to use Struts would have had to learn the new view technology, making Struts a less attractive package. By using JSP, Struts would allow Model 1 developers to continue using a technology they were familiar with - they'd just have to take a more disciplined approach to JSP development.

The way I understand it (and again, I can't substantiate this), the Struts developers expected a more suitable view layer to become available before too long after Struts was released. Unfortunately it didn't work out quite that way; the first really useful package to fit the need was probably Velocity and that wasn't on the scene until something like two years later. In the meantime the JSP snowball had been rolling down the hill and picking up speed. Thanks to that momentum, JSP is still being used even today for new applications using Struts 2, Spring MVC and others, regardless of the problems it continues to cause in Model 2 environments.

The Alternatives

If JSP isn't a good fit for Model 2 applications, then what is?

The answer is quite simple: templating software. The idea is that you create HTML templates which contain embedded markers that tell the templating engine how to get dynamic data from the data model produced by the business logic and format it for presentation. The templating engine merges the template with the data model to produce the HTML and deliver it to the client browser.

Velocity and FreeMarker are probably the two most commonly used templating packages in current use. Integrating Velocity and/or FreeMarker is pretty simple. Both packages include ready-to-use servlets that fit with Struts 1, so in both cases all you have to do is configure your application to forward the request/response to the relevant servlet instead of the JSP servlet. Struts 2 has "Results" classes to provide Velocity and FreeMarker views; similarly Spring MVC includes view resolvers and views for Velocity and FreeMarker.

Which is better, Velocity or FreeMarker? I'll probably be writing an in-depth article comparing the two quite soon, but as a short answer... both have their own advantages and drawbacks. Velocity is simpler to learn, but FreeMarker offers more built-in functionality. Velocity is a bit more forgiving than FreeMarker but that may not be such a good thing, especially for larger applications. If I were asked to lay my cards on the table right now, I'd have to say that while I've used Velocity extensively over the last few years, I will almost certainly be using FreeMarker in the future.

In Summary...


  • Don't use JSP for Model 2 applications.

  • Use Velocity or FreeMarker instead.

  • Once you've developed a web application with Velocity or FreeMarker, I can almost guarantee you'll never want to write another JSP again.

Labels: ,