JaVa
   

Dedicated Template Languages

If we're only using JSP pages for views, we're using JSP pages as templates. If we base our JSP usage on the JSTL, we're largely abandoning the original JSP idea of using Java as the scripting language. Since we don't want to use the request handling capability of JSP pages or the power of Java scripting JSP pages offer and believe that the availability of these features may actually be harmful, it's reasonable to question why we should be using JSP at all. There are many alternative template languages to JSP, available in open source (XSLT deserves its own section and is discussed later). Unlike JSP, these are designed purely as template languages. Each has its own merits and flaws, but there is much similarity between them. First let's consider the big picture, and the pros and cons of using a template solution, rather than JSP.

Common Concepts

The templating solutions we'll discuss in this section share the following basic concepts:

Why might we choose to use a template language for web tier views in place of JSP?

However, there are also disadvantages in using a dedicated template language:

While JSP pages, which are compiled into servlets, might be expected to outperform templating solutions, the reverse may be true in practice. We'll discuss view performance in .

Let's look at some popular templating solutions.

WebMacro

WebMacro is one of the oldest and best-known Java-based template languages. The following excerpt from WebMacro documentation, quoted with the author's permission from http://germ.semiotek.com/README.html, highlights the differences from JSP and makes the case for using a specialized templating solution instead of JSP: 'WebMacro is similar in many ways to JSP/ASP and other projects in many ways, but differs from those according to our biases:

WebMacro uses a simple syntax that doesn't require escaping into and out of scripts, as does JSP pages. Not being markup based, the syntax is more intuitive than using JSP custom tags. The following example shows how WebMacro can be used for a conditional statement, based on a JavaBean property. Note that the bean scripting variable is prefixed with a $:

 #if ($bean.GoldService) {
 <font size="4">Welcome to our Gold Service!</font>
 } #else {
 <font size="4">Welcome!</font>
 }


JavaBeans are made available to WebMacro templates by being placed in a WebMacro context, which contains objects used similarly to the use of HttpServletRequest attributes in JSP pages. Like JSTL, WebMacro supports nested property paths such as person.spouse.name. It is also possible to create new variables, perform iteration, calculations etc. While the syntax differs slightly, the concepts are virtually the same as those of Velocity, discussed below, so I won't discuss the WebMacro template language here. Please refer to http://webmacro.org/WebMacroBasics for more information. WebMacro is proven on real web sites. Since January 2001, AltaVista, one of the most heavily trafficked sites on the web, has been using WebMacro as its primary page generation technology. WebMacro is available from http://webmacro.org, and is free under the Gnu GPL.

Note 

The framework code with the sample app includes an implementation of the View interface, com.interface21.web.servlet.view.webmacro.WebMacroView, which allows the MVC framework we discussed in to be used with WebMacro templates. Use this class (remembering to include the WebMacro JAR file in your WAR's /WEB-INF/lib directory) to use WebMacro templates with this framework without any need to change controller or model code. This view implementation is very similar to the Velocity implementation we'll discuss below, so I won't discuss it here.

Velocity

Jakarta Velocity is essentially a re-implementation of WebMacro with a distinct codebase and some new features. For a discussion of Velocity's relationship to WebMacro, see http://jakarta.apache.org/velocity/differences.html. Velocity has more comprehensive documentation than WebMacro, is published under a different license and the Velocity project seems more active. In this section we'll look at Velocity's basic concepts, and see how our example view can be rendered by a Velocity template.

Velocity Concepts

Velocity is purely and simply a template engine. This makes Velocity easy to learn and avoids the common problem of a framework providing its own implementations of concepts that are already well handled by other products. The Velocity template engine does not depend on the Servlet API, meaning that it can be used for apps other than web apps, and that Velocity templates can be tested outside a servlet container (a significant advantage over JSP). The heart of Velocity is the Velocity Template Language (VTL), Velocity's equivalent of the WebMacro language. VTL looks very like the WebMacro template language. There is no need to escape expressions or "scriptlets". The # character is used to prefix directives (control statements), and the $ character to prefix variables. Both these characters can be escaped if they are part of static template data. Velocity has a slightly different philosophy to WebMacro, aiming to keep the set of core directives to a minimum, while allowing users to extend Velocity's capabilities for their apps by defining Velocimacros: reusable template segments that can be used like Velocity directives. Macros can define any number of arguments to be passed on invocation. The following simple macro, with a single argument, outputs an HTML-formatted list of squares from one up to a given maximum value, and illustrates the basic Velocity syntax:

 #macro( squareList $upTo )
 <ul>
 #foreach ( $item in [1..$upTo] )
 #set ($square = $item * $item)
 <li>$square
 #end
 </ul>
 #end


This macro can be invoked within a Velocity template as follows:

 #squareList(6)


Velocity macros can be declared "inline" in Velocity templates (although this can be disabled if desired) or collected in template libraries, analogous to JSP tag libraries. Velocity macros are in some respects what JSP custom tags should have been: simple and defined without the need to program in Java (JSP 2.0 will introduce simpler tag extension definitions that are closer to this). As with WebMacro, model objects used in Velocity templates must be made available to Velocity in a Velocity context object. Templates can easily expose bean properties, including nested properties, for objects placed in a Velocity context. Unlike JSP pages, but like WebMacro templates, Velocity templates don't declare model objects required in their context using a comparable mechanism to <jsp:useBean>. Variable references that can't be resolved in the context will appear as literals, making it easy to rectify typos (for example, if there is no model object called nothing, $nothing will appear as a string literal in the template output). The absence of variable declarations and type checks may be off-putting to a Java developer, but web tier presentation templates aren't intended for Java developers to edit. Velocity comes with a JSP custom tag that interprets its body content as VTL. When using Velocity, there's little reason to use JSP as a wrapper, and mixing JSP and VTL allows all the negatives of JSP plus a mixture of technologies to make maintenance still harder. However, there are a few situations when the Velocity tag library might be useful:

I won't attempt to describe VTL syntax in detail here. A good, concise VTL reference guide is included with the Velocity distribution. Instead, let's look at using a Velocity template to display our sample view.

A Velocity Template for our Example

Our MVC web framework provides standard support for Velocity views. We can define a Velocity view bean for the sample page in /WEB-INF/classes/views.properties using the com.interface21.web.servlet.view.Velocity.View standard View implementation. This standard View implementation will obtain and cache the associated Velocity template on startup. When asked to render a model to the response, it creates a Velocity context with an attribute corresponding to each entry in the model. This is analogous to the way in with the InternalResourceView copies model entries to request attributes. It then uses Velocity to write output to the response, given the template and context data.

Note 

See Appendix A for information on how this view is implemented, and how to install and configure Velocity.

The most important bean property to set on the VelocityView class is the templateName property, which identifies a Velocity template within the WAR. We can define our sample view as follows:

 showReservation.class=com.interface21.web.servlet.view.velocity.VelocityView
 showReservation.templateName=showReservation.vm
 showReservation.exposeDateFormatter=true
 showReservation.exposeCurrencyFormatter=true


Note that this bean definition also sets the two format helper properties to true, which causes the VelocityView class to add DateFormat and NumberFormat helpers with the names simpleDateFormat and currencyFormat to the Velocity context, which the template can use to format dates and currency amounts. This functionality, provided by the VelocityView framework class, is necessary since Velocity 1.3 (surprisingly) provides no standard support for date and time formatting (this issue is discussed further in Appendix A). The first task in writing the Velocity template (found in the sample WAR at /WEB-INF/classes/showReservation.vm) is to set the pattern used by the date helper and to create variables containing the formatted dates and times. As we're reliant on Java support for this, the code we'll use is similar to that used in our JSP example:

 <!--
 $simpleDateFormat.applyPattern("EEEE MMMM dd, yyyy")
 #set ($formattedDate = $simpleDateFormat.format($performance.when) ) 
 $simpleDateFormat.applyPattern("h:mm a")
 #set ($formattedTime = $simpleDateFormat.format($performance.when) ) 
 -->



Note that I've placed the Velocity "scriptlet" in an HTML comment. It won't actually generate output, but this will avoid it upsetting HTML editing tools. The #set directive enables us to declare variables used later in the template. Once this is out of the way, the rest of the template is easy and intuitive to write. Note the simple access to nested properties. Our model objects, once placed in the Velocity context, can be accessed by name:

xs
 <html>
 <head>
 <title>Seats reserved for $performance.show.name</title> 
 </head>



We can now output our formatted date and time:

 <body>
 <b>$performance.show.name:
 $formattedDate at $formattedTime 
 </b>
 <br/>
 <p>



Although Velocity allows us to invoke methods, as well as get property values (by using parentheses, even if methods take no arguments), it doesn't allow us to find the length of an array. Fortunately the number of seats is also available from the quoteReservation property of the Reservation object, so we can take a roundabout route:

 $reservation.quoteRequest.seatsRequested
 seats in
 $priceband.description
 have been reserved
 for you for
 $reservation.minutesReservationWillBeValid minutes to give you time to complete your purchase


Velocity shines in iterating over the seat array. Like JSTL (but not JSP scriptlets) Velocity exposes each item in turn as a variable, making this code very simple. Velocity's syntax is simpler and more intuitive than the JSTL markup-based syntax:

 The seat numbers are:
 <ul>
 #foreach ($seat in $reservation.seats)
 <li>$seat.name
 #end 
 </ul>



Note 

Velocity also allows us to find the position in the list through the value of the velocityCount predefined variable, although we don't need this capability in the example.

We use the NumberFormat helper object to format the currency amounts, meaning that we don't need to supply currency symbols. The NumberFormat class will always return the one appropriate for the request locale:

 The total cost of these tickets will be
 $currencyFormat.format$reservation.totalPrice). 
 This includes a tutorialing fee of
 $currencyFormat.format($reservation.quoteRequest.bookingFee). 



Conditionals such as our check as to whether the seats are adjacent use the Velocity if directive. Note the closing #end directive:

 #if (!$reservation.seatsAreAdjacent) 
 <b>Please note that due to lack of availability, some of the
 seats offered are not adjacent.</b>
 <form method="GET" action="payment.html">
 <input type="submit" value="Try another date"></input>
 </form>
 #end 



Displaying the seating plan image URL involves another nested property. Note the use of what Velocity documentation calls formal notation (with the variable name enclosed in curly brackets), which enables us to distinguish the part of the string that is a variable from literal text in the same way as we used the JSTL ${} expression delimiter:

 <img src="static/seatingplans/${performance.show.seatingplanid}.jpg" />


Comparing this with the JSTL alternative shows the similarities between accessing bean properties in JSTL and Velocity and the disadvantages of markup-based scripting. The JSTL version involves nested <img> and <c:out> tags, while the output, of course, will include only the <img> tag we're actually trying to generate:

 <img
 src="<c:out
 value="static/seatingplans/${performance.show.seatingPlanId}.jpg" />"
 />


Note how both are less verbose and error-prone than the standard JSP way, which is awkward, even when broken into one scriptlet and an expression:

 <% String seatingPlanImage = "static/seatingplans/" +
 performance.getShow().getSeatingPlanId() + ".jpg"; %>
 <img src="<%=seatingplanimage%>" />


Velocity Summary

Velocity offers a very simple, high-performance, template language that is well suited to exposing JavaBean properties. Velocity isn't web-specific. Property navigation syntax in Velocity is much like that in the JSTL. The simple Velocity scripting language uses special characters to identify directives, rather than escaping to and from embedded code, as in JSP scriptlets, or markup, as in JSP custom tags. Thus the Velocity template for our example is more concise and easier to read than even the JSP version using JSTL. While the J2EE-standard argument for JSP is compelling, personally I find that comparing at a Velocity or WebMacro template with a JSP presenting the same information shows how verbose and unintuitive the JSP syntax is, and that custom tags (and the prospect of JSP 2.0) merely reduce the gap. While Java developers tend not to question the readability of JSP pages, in my experience HTML developers, who will have to work with them, find them awkward and alien.

Both WebMacro and Velocity are good, usable solutions that enforce a clean separation between control logic and view template. Although I've chosen to use JSP as the main view technology for the sample app, as the above example shows, using Velocity would probably result in simpler, more readable view templates.

FreeMarker

FreeMarker is conceptually similar to WebMacro and Velocity in that a template is obtained using the provided API and used to render a model constructed using method calls. The FreeMarker template language has a more markup-oriented syntax to WebMacro and Velocity, but is comparable in power. However, unlike WebMacro, Velocity, andJSP, FreeMarker attempts to avoid the use of reflection to obtain model values, presumably because of concerns about the performance of reflection. This means that adapters must be written as part of app code to expose data to FreeMarker (these adapters are analogous to Swing models). While it's possible to add anyJavaBean into a WebMacro or Velocity Context and access its properties and methods without writing any additional Java code, FreeMarker requires explicit coding. The FreeMarker equivalent of a WebMacro or Velocity context is a "data model tree",in which the root must implement the freemarker.template.TemplateModelRoot interface and each subnode must implement another subinterface of freemarker.template.TemplateModel. What this means is that, when exposing an object graph, an adapter class will need to be written for each app class. String data can be exposed more easily, using the freemarker.template.SimpleScalar convenience class. The Guestbook sample app supplied with FreeMarker shows the use of adapters for each app class. There are 114 lines of code in adapter classes in this trivial app. I've yet to see reflection prove a performance problem in this kind of situation, so I think that forcing such additional work on app developers to avoid using reflection in a framework is a poor design trade-off. However, not everyone agrees: see http://www.javaworld.com/jw-01-2001/jw-0119-freemarker.html for an article praising FreeMarker's design. The FreeMarker download includes separate packages that enable FreeMarker templates to access XML documents and JavaBeans using reflection, like templates in other products.

FreeMarker is also open source, and is published under the Gnu GPL. It is available at http://freemarker.sf.net/.

JaVa
   
Comments