Skip to main content

skip to main content

developerWorks  >  Java technology | Web development  >

Struts-Velocity integration

A flexible alternative to JSP in five easy steps

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


New site feature

Check out our new article design and features. Tell us what you think.


Rate this page

Help us improve this content


Level: Intermediate

George Franciscus (george.franciscus@nexcel.ca), Principal, Nexcel

20 Sep 2005

Struts Recipes co-author George Franciscus walks you step-by-step through integrating the Velocity Template Engine into your Struts applications. The result is a fast, flexible alternative to JSP, but with all the creature comforts you expect from Struts.

Java™ ServerPages (JSP) technology is so ubiquitous that you almost forget you have other options when it comes to creating Web pages. Recently, however, some developers have been turning to template engines for a flexibility not found in JSP. While you can embed data in HTML with both JSP and template engines, each technology has its own way of going about it. The Velocity Template Engine is an especially popular alternative to JSP. Velocity offers a shallow learning curve and tremendous ease of use. Developers love its concise syntax and performance analysis has proven that it outperforms JSP. Velocity is also very easy to integrate into your Struts applications.

In this article, I'll show you how to integrate and use the Velocity Template Engine in your Struts applications. I'll give you the formula up front and then walk you through it, step-by-step. The resulting application will be one that combines Struts and Velocity -- a stellar combination that just might make you question your loyalty to JSP!

See the Download section to download the source code for this article, as well as the Struts, Velocity, and the Velocity Tools packages before you begin. Note that this article assumes you are familiar with MVC programming using the Struts framework.

About template engines

Before jumping into the simple task of integrating Struts and Velocity, let's be sure you understand template engines and their role in generating views. Template engines in general, and Velocity in particular, have a life outside of HTML. Velocity merges data into various spots in a body of text. The text can be a letter, an e-mail, XML, or HTML. In this way, the Velocity Template Engine is somewhat reminiscent of Microsoft Word's "mail merge" feature. Mail merge lets you easily merge dynamic data such as names, addresses, and phone numbers into a letter. In the early days, organizations used this feature to generate large mailings and haul them down to the post office, resulting in the birth of spam!

What is Velocity?

Velocity is a Java-based template engine that provides a simple template-based language for referencing objects in a script-like manner. Velocity facilitates a separation of responsibilities among team members by letting Web designers focus on views (that is, page look and feel) while Java programmers focus on backend code. Taking Java code out of the page layout results in Web applications that are more maintainable over time. Velocity is a viable alternative to JSP or PHP when combined with an MVC development framework such as Struts.

In a Web application, Velocity serves much the same purpose as a JSP: you can use it to generate HTML before sending it off to the HttpServletResponse's OutputStream. One way to use Velocity in a Struts application is to write to the response from inside a Struts Action and return a null ActionForward. While this technique works, it has a serious flaw: you can't use the struts-config.xml file to abstract the response. Having placed the view inside the Action means you must change the Action if you want to change the response.

Because this technique robs me of one of Struts's best features (namely its ability to abstract focus from the view), I prefer to direct all the responses to a servlet that is, in turn, dedicated to accessing the Velocity template, merging data in context, generating the response, and firing it off to the browser. As you'll learn in a minute, the folks at Velocity have already bundled all these steps together: all you need to do is follow my step-by-step recipe for implementing them. If you have yet to visit the Download section, now is the time to do it.



Back to top


Five steps to Velocity

The recipe for combining Struts and the Velocity Template Engine is simple and straightforward; in fact, you can do it in just five steps:

  1. Place the Velocity JARs in your classpath.
  2. Modify the web.xml file to recognize the Velocity servlet.
  3. Place the Velocity toolbox.xml under your application's WEB-INF directory.
  4. Modify your struts-config to point its views to Velocity templates instead of JSPs.
  5. Create a Velocity template for each page you want to render.

I'll use a familiar search use case to illustrate the Struts-Velocity integration recipe. In this example, a simple application lets a user search for a book by its ISBN number. The application's results page presents a book matching the ISBN number.

Ode to Struts tags -- not!

At this point, you may be wondering if you will need to give up all those nice Struts tags that have saved you so much coding in the past. If you're not using JSP, then surely you won't be using the Struts JSP tags! Fortunately, you'll have the Velocity Tools instead. Velocity's Struts tools provide all the creature comforts you're accustomed to from Struts, but with the added flexibility of Velocity.

Step 1. Place the Velocity JARs in WEB-INF/lib

If you haven't already done it, you'll need to download Velocity now. Velocity is great on its own, but its tools package will help you get the job done better and faster. In particular, the Struts tools mimic the Struts tags you've come to know. See the Download section to download the Velocity Template Engine and the Velocity Tools.

Note that the jars you need will change a little from time to time. Rather than publishing a list of JARs here, I recommend you visit the Velocity home page (see Resources) and read the installation instructions there. Once you've obtained the JARs you need, simply place them under WEB-INF\lib.

Step 2. Modify web.xml to recognize the Velocity servlet

The next step is to modify the Struts web.xml file to recognize the Velocity servlet and direct all resources request ending with .vm to the Velocity servlet, as shown in Listing 1.


Listing 1. Modify web.xml to declare the Velocity servlet

<servlet>
  <servlet-name>velocity</servlet-name> |(1)
  <servlet-class> |(2)
    org.apache.velocity.tools.view.servlet.VelocityViewServlet 
  </servlet-class>                                            

  <init-param> |(3)
    <param-name>org.apache.velocity.toolbox</param-name> 
    <param-value>/WEB-INF/toolbox.xml</param-value>      
 </init-param>                                                 

 <load-on-startup>10</load-on-startup> |(4)
</servlet>

<!-- Map *.vm files to Velocity -->
<servlet-mapping> |(5)
  <servlet-name>velocity</servlet-name>
  <url-pattern>*.vm</url-pattern>      
</servlet-mapping> 

Let's clarify what's happening in Listing 1:

  • At (1) I declare the Velocity servlet and give it a handle of velocity.
  • At (2) I declare the class name for the Velocity servlet.

The Velocity servlet takes a "toolbox" parameter. The toolbox is the place you declare the tools available to your application. Accordingly, in Listing 1, I also do the following:

  • At (3) I tell the VelocityServlet where the toolbox configuration is located.

  • At (4) I set the load-on-startup tag to ensure the Velocity servlet is loaded at the correct time. Any value greater than or equal to 0 will force the container to load the servlet by calling its init() method. The value placed in the body of the load-on-startup tag determines the order by which the init methods of the various servlets are called. For example, 0 is called before 1, which is called before 2. An omitted tag or a negative value empowers the servlet container to load the servlet whenever it chooses.

  • At (5) I declare a servlet mapping that forces all requests with resources suffixed with .vm to be directed to the Velocity servlet. Note that the <servlet-name> at (5) must match the <servlet-name> at (1). Interleaving declarations and mappings generate errors in the log.

Step 3. Place toolbox.xml under WEB-INF

With Velocity, you can use (or create) a toolbox of tools. The toolbox is used to register classes containing useful functions you will use time and time again. Fortunately, Velocity provides a number of prebuilt tools for you to use. Many Struts tools have been created to mimic the original Struts tags. If you find that you need to build your own tools, you're also free to do so. In Listing 2, I present toolbox.xml, which you'll find in the Velocity Tools download. This file should be placed with the Velocity JARs under WEB-INF.


Listing 2. toolbox.xml

<?xml version="1.0"?>
<toolbox>
  <tool>
     <key>link</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.StrutsLinkTool
     </class>
  </tool>
  <tool>
     <key>msg</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.MessageTool
     </class>
  </tool>
  <tool>
     <key>errors</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.ErrorsTool
     </class>
  </tool>
  <tool>
     <key>form</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.FormTool
     </class>
  </tool>
  <tool>
     <key>tiles</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.TilesTool
     </class>
  </tool>
  <tool>
     <key>validator</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.ValidatorTool
     </class>
  </tool>
</toolbox>

Step 4. Modify struts-config

The next step is to modify the struts-config.xml to point to Velocity views rather than JSPs. The new config file is shown in Listing 3.


Listing 3. struts-config.xml modified for Velocity views

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD
             Struts Configuration 1.0//EN"
          "http://jakarta.apache.org/struts/dtds/
            struts-config_1_0.dtd">

<struts-config>
    <form-beans>
        <form-bean name="searchForm" type="app.SearchForm"/> 
    </form-beans>

    <global-forwards>
        <forward name="welcome" path="/welcome.do"/>
    </global-forwards>
 
   <action-mappings>
        <action 
            path="/welcome"
            type="org.apache.struts.actions.ForwardAction"
            parameter="/pages/search.vm"/> |(1)

        <action 
            path="/search"
            type="app.SearchAction"
            name="searchForm"    
            scope="request"
            input="/pages/search.vm"> |(2)
            <forward name="success" 
              path="/pages/results.vm"/> |(3)
        </action>
    </action-mappings>
</struts-config>

Listing 3 looks like a very typical Struts application, except for one small difference. Instead of forwarding the client to a JSP, the response is directed to a .vm file (see references 1, 2, and 3 in Listing 3). In most cases, migrating a Struts application from JSPs to Velocity views requires nothing more than a global search and replace from .jsp to .vm. Everything else can stay as is! The templates are stored in the same place you would store your JSPs; all you need to do is use Velocity commands instead of JSP tags.

Step 5. Create a Velocity template

In Listing 4, you can see the Velocity template for the example application's search page.


Listing 4. Velocity template for the search page

<HTML>
  <HEAD>
    <TITLE>Search</TITLE>
  </HEAD>
  <BODY>
    $!errors.msgs()||(1)
    <FORM method="POST" 
      action="$link.setAction('/search')"> |(2)
      <h2>Book Search</h2>
      ISBN:<INPUT type="text" name="isbn">
      <INPUT type="submit" value="Submit" name="submit">
    </FORM>
  </BODY>
</HTML>

Listing 4 is a typical HTML page without any JSP or Struts tags. The following elements may not look so familiar, however:

  • At (1) I use $!errors.msgs() to get any error messages on the error-message queue.
  • At (2) I use $link.setAction('/search') to obtain the URL for the search forward.

And that's it -- the rest of this template should look nearly the same as what you're used to. Listing 5 shows the Velocity template for the application's results page.


Listing 5. Velocity template for the results page

<html>
  <body>

  <h1>Book Details</h1>
  <a href="$link.setForward("searchEntry")">Search
    again</a> |(1)

  <h3>$book.title</h3> |(2)

    <b>ISBN:</b>$book.isbn<br>|(3)
    <b>Title:</b>$book.title<br>|(4)
    <b>Author:</b>$book.author<br>|(5)
    <b>Price:</b>$book.price<br>|(6)
    <b>No Pages:</b>$book.pages<br>|(7)
    <b>Description:</b>$book.description<br>|(8)
    <b>Publisher:</b>$book.publisher<br>|(9)
  </body>
<html>

You'll note that Listing 5 does not contain JSP tags or Struts tags. Let's look at it in greater detail:

  • At (1) I set the <a> tag's href to a Struts forward by using the Struts Link tool.
  • At (2) I access the $book title property.
  • At (3) I access the $book isbn property.
  • At (4) I access the $book title property, again.
  • At (5) I access the $book author property.
  • At (6) I access the $book price property.
  • At (7) I access the $book pages property.
  • At (8) I access the $book description property.
  • At (9) I access the $book publisher property.


Back to top


Discussion

That's all there is to it for integrating Struts and the Velocity Template Engine. It's simple enough on the surface (and genuinely straightforward), but think for a minute about what makes the integration work.

A Struts action mapping can define any view, not just JSPs. In this article, I simply changed the action mappings to return files with the suffix of vm instead of jsp. Next, I declared a Velocity servlet and told the Servlet container to send any files with the suffix of vm to the VelocityViewServlet.

The VelocityViewServlet renders Velocity commands into HTML responses. In this way, the VelocityViewServlet acts as an interceptor to the view response. The Struts controller forwards the view to the VelocityViewServlet, which in turn processes the vm file before sending the response to the client. See Resources for more on how Velocity views are integrated into Struts applications.



Back to top


Conclusion

As you've seen here, Struts-Velocity integration is straightforward. This recipe lets you get everything wired up with just five simple steps. The advantages of using a template engine rather than JSP varies for different engines and scenarios. In the case of Velocity, the advantages are simplicity, a short learning curve, and better performance.




Back to top


Download

DescriptionNameSizeDownload method
Sample codej-sr1-source.zip3 MBHTTP
Information about download methods


Resources

Learn

Get products and technologies

Discuss


About the author

George Franciscus is a Java Enterprise consultant and Struts authority. He is a coauthor of Manning's Struts Recipes and Struts in Action. George offers technical and management consulting services through nexcel.ca.




Rate this page


Please take a moment to complete this form to help us better serve you.



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top