Accelerating JSP Tag Development with Jakarta Velocity

Accelerating JSP Tag Development with Jakarta Velocity

by Gregory Gerard
05/01/2002

Writing JSP tags can be tedious, even under the best of circumstances. Often, I merely wish to push out lightly-parameterized HTML to, for instance, control the layout of an intricate (but often used) table format.

While you might assert that this is precisely the purpose of Java Server Pages, with its directive for including JSPs through the <jsp:include .../> or <%@include ...%> elements, it can often be overkill and cumbersome to maintain. With a simple framework, you can quickly churn out JSP tags that provide compile-time type checking and near-normal Java calling semantics.

Here is a simple, if contrived, example comparing the JSP include method with the custom tag method. Because parameters of the tag are strongly typed, if you try to pass anything but a Collection to the tag, the JSP compiler will flag the error. In addition, required parameters that are missing are flagged at page compilation time, rather than at page evaluation time; earlier is better. Finally, <jsp:include/> can only pass a string directly to the included page. So if you wish to pass an object of your own creation, you must put it somewhere in the request or session and pass the name of it to the included page, a level of indirection that's simultaneously clumsy and ugly. The <%@include ...%> directive cannot pass anything on, so it's back to well-known names.



Listing 1. Iteration by Inclusion: The Includer

...

<%  java.util.List l = new java.util.LinkedList();

    l.add("first");

    l.add("second");

    l.add("third");

    l.add("fourth");

    request.setAttribute("myCollection", l);

%>



<jsp:include page="/IncludedPage.jsp" flush="true">

    <jsp:param name="collection" value="myCollection"/>

</jsp:include>

...

Here is the IncludedPage.jsp file, referenced above.

<%  String theCollectionName = request.getParameter("collection");

    java.util.Collection c = (java.util.Collection)

            request.getAttribute(theCollectionName);

    if (c != null)

    {

%>



collection name: <%=theCollectionName%>

collection value: <%=c.toString()%>



<%

    }

    else

    {

        // they forgot to set the parameter... *sigh*

    }

%>



Listing 2. Iteration by Inclusion: The Included Page

...

<ora:SomeCustomIterator collection="<%=mylist%>"/>

...

Tags are cool. Tags are, however, a pain to write for the same reasons Servlets are a pain to write; namely, putting HTML inside of Java code, which is neither pretty nor maintainable even in the short term. JSP was supposed to make mixing Java and markup easy.

To make things better and give an added dimension of power, we can add Jakarta Velocity to the mix. Velocity is a templating language, the philosophy of which is, "Keep the simple things simple." It sports a very concise syntax for inserting variable references into pretty much any type of textual material, from plain text to HTML to XML. It's not too picky or fussy. Moreover, it has some very convenient constructs for iterating over just about everything, and it can talk to everything from JavaBeans to custom objects to the lowly workhorse java.util.Map.

Why not use Jakarta Velocity as is? Because it's not JSP. So if you have a mandate to use JSP, Velocity by itself isn't a solution. Why not use the Velocity Tag Library? While this approach gives direct access to Velocity's macros, it doesn't solve many of our problems. First, it's no better than JSP in exposing business logic to an HTML author. Second, it doesn't provide any sort of interpage reusability like JSP taglibs do, other than <jsp:include .../>. Third, it doesn't provide any sort of type checking for the HTML author.

Instead, we factor out the HTML into a separate resource that is palatable to many more HTML editors and tools. Obviously, these tools cannot expand any runtime macros, but neither will they hide behind JSP-isms so much as to be useless. The solution is a very simple boilerplate you can use to crank out useful tags as quickly as you need them. We'll make four files in total: one Java class that is our tag code, one XML file that is our tag descriptor, one template HTML file, and one JSP file that will serve as a demo page.

One extra benefit from this setup is that the taglib author can test the markup generation largely outside of the application server. Those who know the woes of appserver redeployments will appreciate this.

The Java class is relatively short. First, it validates its tag parameters. This is where you embed your custom business logic. Once satisfied with the validity of tag parameters, we put them all into the Velocity Context object to make them accessible to the markup template. Finally, we let the tag engine know to "paint" the tag to the JSP output stream.

VelocityContext myVelocityContext = getVelocityContext();
myVelocityContext.put("title", title);
myVelocityContext.put("subtitle", subtitle);
myVelocityContext.put("images", images);
myVelocityContext.put("ingredients", ingredients);

StringWriter myStringWriter = new StringWriter();

Velocity.mergeTemplate(myResource,
org.apache.velocity.runtime.RuntimeSingleton.getString(Velocity.INPUT_ENCODING,
Velocity.ENCODING_DEFAULT),
myVelocityContext, myStringWriter);
pageContext.getOut().print(myStringWriter);

return EVAL_PAGE;

The taglib control file is an XML file that lets the JSP engine know what tags we are publishing. It declares the tag name, what Java class is associated with it, and whether a parameter is required or not.

The markup file is anything you like. It's put in the class path and loaded accordingly. You can use Velocity macros in this file as you'd like. You have full access to all objects you placed into the Velocity Context object. You can create more advanced macros within this file as well.

<table border="0" cellspacing="2" cellpadding="2" title="$title">

#foreach ( $key in $ingredients.keySet() )

<tr>

    <td>$key</td>

    <td>$ingredients.get($key)</td>

</tr>

#end

</table>



## This handy macro will only print out an attribute if there is a value

## provided.  This prevents HTML from having things like

## class="" and instead suppresses the entire attribute.

## <div #condAttribute("class" $class)> ... </div>

#macro (condAttribute $name $value)

#if ( $value )

#if ( $name )

${name}="${value}"#end#end#end



#condAttribute("summary" $subtitle)

Finally, we have our test JSP to host our sample tag.

<%@ taglib uri="eztag-sample" prefix="ora"%>

<%  java.util.Map myIngredients = new java.util.HashMap();

    myIngredients.put("polenta", "1 cup");

    myIngredients.put("milk", "2 cups");

    myIngredients.put("water", "2 cups");

    myIngredients.put("moscarpone cheese", "1/2 cup");

%>

<ora:sample title="Baked Polenta" ingredients="<%=myIngredients%>"/>

Give it whirl! You'll find managing your content generation and template to be far more convenient.

References

  • Jakarta Velocity Home
  • Jakarta Velocity Tags Documentation
  • Suns JSP Documentation
  • Suns JSP Tag Libraries Documentation
  • Suns JSP Tag Libraries Syntax Reference

Gregory Gerard is an engineer, though not the cool kind that drives a train. He is a managing partner of Southgate Consulting Group.


Return to ONJava.com.

Close    To Top
  • Prev Article-Java:
  • Next Article-Java:
  • Now: Tutorial for Web and Software Design > Java > Java Servlets > Java Content
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Geek Tutorial
     

    Blogging Tutorial

      RSS Tutorial
      Podcasting Tutorial
    Graphic Design Tutorial
      Coreldraw Tutorial
      Illustrator Tutorial
      3D Tutorials
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial/ Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial/ Articles
     

    XML Style

      AJAX Tutorial
      XML Mobile
    Flash Tutorial/ Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial/ Articles
      Linux Tutorial
      Symbian Tutorial
      MacOS Tutorial
    Personal Tech
      Hardware Tutorial
      Software Tutorial
      Online Auction