ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Migrating to Velocity Migrating to Velocity

by Jason R. Briggs
04/14/2004

There are a variety of choices when it comes to producing dynamic web content. Typically, most projects will go with the accepted or de facto standards, so chances are, if the platform choice for your project is Java, you're likely to be using JSPs. This makes sense for a number of reasons: new staff are more likely to have experience with a standard; a number of web servers support JSPs, thus giving you a wide choice of web platforms; there is plenty of documentation available since people have usually "done it before"; and so on. However, sometimes using the standard isn't the best choice. Perhaps you need or want more direct control over the code producing your content; perhaps you have performance issues with JSPs; or maybe it's just that a new technical direction within your company is pushing away from that paradigm. Velocity is a simple, yet powerful, templating engine that can be used to generate dynamic content as an alternative to the incumbent standard. In some cases it provides a performance advantage over JSPs, and it certainly forces a web developer to think differently about separating content from code.

The one major downside is that if you already have a JSP-based project, or have a less experienced team that is already skilled in JSPs, switching to Velocity presents its own set of challenges. In this article, I try to remove some of these obstacles, using some simple Velocity extensions that I hope will reduce some of the pain you might experience in migration.

A Bit of Background

Almost two years ago I inherited an average-size, servlet-based system that had been (badly) written by a Northern European company (proving that not everything that comes out of Northern Europe is of Linux quality). The software used a very basic template engine, but there was also a lot of HTML embedded in the code as well. In fact, there was a rather long list of poor design decisions, and nasty pieces of ineptly managed code (including the huge-method-that-does-everything style of development) just waiting to ensnare the unwitting developer in a maintenance nightmare of twisting spaghetti code.

Considering the limitations of the system as it was then, and the requirements my company had for a more fully featured suite, I made the decision to scrap 99 percent of the code, and start fresh, designing a new J2EE system from scratch. The new system has been running for almost a year now, with fairly few hiccups. It is an order of magnitude more maintainable, and, with one exception, has been enjoyable to work on.

Of late, and despite the fact it may be considered an unfashionable viewpoint, I have found myself becoming dissatisfied with my original decision to go with JSPs for the web and WAP interfaces. The original design endeavored to be as close to the MVC pattern as possible, which isn't all that simple considering how tempting it is to embed Java code in your web pages. The task was made easier by the use of the JSTL (standard tag library), but inevitably, you find there is something you just can't do with JSTL, so you write your own taglib to do the task. And then there are the objects you need to use in the page that, through some quirk of fate, simply will not work properly with JSTL unless you wrap them with a bit of Java code. Or, more commonly, there are methods that have to be called and, due to time constraints during that part of development, were just easier to call directly with Java. Suffice it to say that the final result, while perfectly functional, is less elegant than one might have hoped for at the beginning of development.

Enter the Challenger

Re-evaluation of the web part of our technology set has recently become more important due to an issue with our servlet container and the way it handles JSPs under heavy load (the infamous "Too Many Open Files" problem), and after examining some of the myriad choices available, I settled on Velocity due to a couple of important considerations:

  1. Open Source — whether or not it's an important concern for others, I run a Linux shop, so open source software is usually our first port of call.

  2. Performance — my initial tests indicated that for simpler pages, Velocity outperforms JSPs by between 35 percent ad 45 percent. For more complicated pages, the difference starts to diminish (and after you add all the other factors that go into an average dynamic web page, it can sometimes drop to only a 5 percent difference), but the improvement is there for the taking.

  3. Elegance — Velocity's syntax is simple and effective. It's also pretty straightforward to add new commands (or directives as they're called) without violating that convention of simplicity.

I also happen to agree with the Velocity point of view that suggests if you hand a JSP/JSTL page over to a designer they will have a much harder time than if you hand them a Velocity template (the disadvantage of the JSP/JSTL approach being that if you're already looking at XHTML, having XML tags for the dynamic content doesn't make life any easier for a non-technical web designer).

How It Works

In Velocity, for each page (or if you prefer, for each group of pages), you write a servlet. Your servlet marshals all the data you need for that page, places it in a context, and finally, you tell Velocity to render that context using a template. The template contains your HTML markup and Velocity directives — no Java code.

This is, of course, why it is so effective; by forcing you to severely limit the code in the template, you simplify your pages — in effect enabling you to hand them off to a web designer in a way that I don't personally believe you can do as well with JSPs.

Contrast this with our JSPs: we use JavaBeans to hide our Java code away as much as possible. We then include these beans in our pages using the JSP tag useBean, and set properties against those beans before we retrieve the data using JSTL tags:

<jsp:useBean id="comp" scope="session" 
    class="com.lateralnz.comp.view.CompDefBean" />
<jsp:setProperty name="comp" 
    property="someprop" value="someval" />

...
...

<c:forEach var="comp" items="${comps.iterator}">
  <tr>
    <td class="list">
      <c:out value="${comp.compCode}" />
    </td>
...

As you can imagine, a straight conversion from JSP to Velocity represents a significant amount of footwork, not to mention the learning curve involved if you are leading a relatively inexperienced team. Time is always an issue with any project, and while our system isn't huge by any stretch of the imagination, we still didn't have the resources to convert a few hundred JSPs to an alternate technology, especially when that technology requires you to work with significantly different methods. Accordingly, I made the decision to do a gradual migration to Velocity, taking a more measured approach.

Adding the Missing JSP Functionality

Step one is to allow Velocity templates to be called in the same way as a JSP. To start with I created a basic servlet (VMServlet) and then set up a mapping with the url-pattern "*.vm":

<servlet-mapping>
    <servlet-name>vm</servlet-name>
    <url-pattern>*.vm</url-pattern>
</servlet-mapping>

This means that http://mydomain.com/mypath/test.vm will be passed through as a standard servlet call to VMServlet. The main method of VMServlet, processRequest, is called by the standard servlet methods (doGet, doPost), and performs the operations required to add a number of implicit objects to Velocity's context, load the template, and produce the actual output.

protected void processRequest(
    HttpServletRequest request, 
    HttpServletResponse response) 
  throws ServletException, IOException {

Here the template is loaded using standard Velocity methods (templates are cached by the engine):

  String templateName = request.getServletPath();
  Template tmp = ve.getTemplate(templateName);
  VelocityContext ctx = new VelocityContext();

The web context path, session, jsessionid, and servlet request all go into the context (these are the most common objects we use in our JSPs):

  HttpSession session = request.getSession(true);      
  ctx.put("contextPath", 
          request.getContextPath());
  ctx.put("session", session);
  ctx.put("jsessionid", JSESSIONID_STR + 
          session.getId());
  ctx.put("request", request);

The final step is to render the output, using a PrintWriter, the Velocity Context, and the template:

  response.setContentType(contentType);
  PrintWriter out = response.getWriter();
  tmp.merge(ctx, out);

Pages: 1, 2

Next Pagearrow