Browse DevX
Sign up for e-mail newsletters from DevX


Rapid Template-Driven Development with Jakarta Velocity : Page 4

Increase your efficiency and lower your stress in developing Web applications by using templates.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Approach 3: Using the Jakarta Velocity Template Engine
Both the servlet and PHP approaches shown earlier give you the results, but they come with a large set of problems. These problems stem from that fact that the developer and the designer are both collaborating on a single file using two completely different skill sets. With outsourced or offshored employees, the problem becomes more marked. Not only are you trying to collaborate on the same file from two completely separate directions (implementation and design), but you may have to do it across different time zones, languages, and cultures too.

The solution comes from making a cleaner separation between the design description for the file (the mockup) and the code necessary to run the file, using some kind of automated process that knits the two together. And that's where the template-driven approach spearheaded by Jakarta Velocity comes in.

Using Jakarta Velocity, a designer designs the file as before, but this time, the designer's HTML forms the template for the finished product. Velocity doesn't have to produce HTML, it can be used for any kind of text output including e-mail or even code generation, but for now I'll stick with the scenario and show how Velocity helps there. In the case of HTML, the Velocity template is virtually identical to the original HTML, except that the designer enters special tags to show where and how the generated content is to be put into the file. To illustrate, here's a snippet of the original HTML mockup amended so it can be used as a template by Velocity.

<tr> <td class="ms-classic4-tl">Name</td> <td class="ms-classic4-top">Company</td> <td class="ms-classic4-top">Sales details</td> <td class="ms-classic4-top">Amount</td> </tr> #foreach ($Item in $theList) <tr> <td class="ms-classic4-left">$Item.PersonName</td> <td class="ms-classic4-even">$Item.CustomerName</td> <td class="ms-classic4-even">$Item.ContractDescription</td> <td class="ms-classic4-even">$Item.Amount</td> </tr> #end

You can see that, similar to the PHP implementation, the original HTML has been modified and some tags have been added to it. However, the important difference here is that no information other than placeholders is present in the file. With PHP you still had to do the database connection, the SQL query, and recordset generation and if necessary, any business logic within the PHP-from-HTML file. With Velocity, all you need to do is add the placeholders. The simplicity of the Velocity Template Language makes that process straightforward. In the preceding code:
  • #foreach sets up a loop, pulling each $Item from $theList of items
  • $Item.PersonName outputs the string containing the personname field of the item, etc.
  • #end closes the loop
A number of other commands are available; check the Velocity documentation at http://jakarta.apache.org/velocity/ for details.

Next, you write a separate code model that infuses the template and populates it according to the instructions in the placeholders. You can find a servlet that does this in the download. The Velocity code is in the doServletWithVelocity method.

The first thing that you do is initialize Velocity and load the template specified above, and then set up a Velocity context. This context is like a workspace where you define everything that Velocity should do. You'll see this in action a little later—it's pretty self-explanatory. The context is where you put the items associated with placeholders in the template. Velocity works out how to output them.

Velocity.init(); // get the template Template template = Velocity.getTemplate("report.vm"); VelocityContext context = new VelocityContext();

Author's Note: In the preceding code snippet, .report.vm is the original HTML file with the placeholders set as mentioned earlier, renamed with the .vm extension.

Next, you iterate through the Java resultset and add the results of the query to an Item object. This object is a supporting class (available in the download) that has methods and properties corresponding to the columns returned from the query. In addition, another bean, of type ItemList, is a simple implementation of a list of Items.

ItemList theList = new ItemList(); while(rs.next()) { Item theItem = new Item(); theItem.setAmount(rs.getObject( "amount").toString()); theItem.setContractDescription( rs.getObject("contractdescription").toString()); theItem.setCustomerName(rs.getObject( "customername").toString()); theItem.setPersonName(rs.getObject( "personname").toString()); theList.addItemToList(theItem); } context.put("theList",theList.getList()); Writer writer = new StringWriter(); template.merge(context, writer);

As the loop goes through the recordset, it creates and populates a new Item for every row. Each completed item is then added to the ItemList. When the loop completes, the code adds the entire item list to the Velocity context giving it the name theList. If you look at the template, that's the variable name mentioned.

(#foreach ($Item in $theList))

And as your class of object in theList is of type 'Item', Velocity is smart enough to parse out the members of that object if you tag them correctly. This is a little confusing, but just remember that when you provide Velocity with a placeholder called $Item.PersonName, Velocity will in fact use the results of a call to the getPersonName method of the Item object to populate the resulting output.

And that's it! For an example like this, that's all you have to do—generate the template from the HTML file and write Java code that sets up the velocity engine, loads the template, and generates a context. You then fill in the placeholders in the template by passing the desired values to the context. At runtime, you can then write out the HTML using the following code:

Writer writer = new StringWriter(); template.merge(context, writer); // write out out.println(writer.toString());

Now, there's only one out.println in the entire servlet. Much cleaner!

You can easily see why this separation of design and implementation make change control much easier—designers can do whatever they like with the template, and as long as they don't change the "placeholder" text that interfaces the template to Velocity, your code doesn't need to change. It's worth noting that because some of the placeholder text is code-like in nature (loops, macros, and the like), there's a learning curve required of designers. Overall, however, using Velocity still greatly simplifies the process.

This article barely scratched the surface of Velocity's capabilities, but it demonstrated the need for and advantages of template-driven development. As the development world moves towards the seemingly conflicting forces of ever more sophisticated Web applications coupled with ever more diverse and distant workforces (thanks in part to offshoring and outsourcing), the development methodologies and tools need to catch up. Velocity is a great start in this regard, allowing you to cleanly separated design and implementation. Initiatives such as XAML from Microsoft are heading in the same direction. All in all, Velocity is highly recommended, and would make a great addition to your toolbox!

Laurence Moroney is a freelance enterprise architect who specializes in designing and implementing service-oriented applications and environments using .NET, J2EE, or (preferably) both. He has authored books on .NET and Web services security, and more than 30 professional articles. A former Wall Street architect, and security analyst, he also dabbles in journalism, reporting for professional sports. You can find his blog at http://www.philotic.com/blog.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date