Rapid Template-Driven Development with Jakarta Velocity

eveloping Web applications has come a long way since the first days of HTML when everything had to be coded by hand. I remember the days before there were smart server-side capabilities such as PHP or JSP when, if you wanted your Web site driven from a database, you had an application read the data and create static pages that you then linked into a navigation system. It was unwieldy, because every time your database changed, you had to regenerate the entire site.

As server-side technologies such as CGI, ASP, and others evolved, these pre-generated pages became a thing of the past. Instead, you could generate pages ‘on-the-fly’ by having the page query your database for you, based on the current context, and create the HTML code to display the information on-demand. This was a beautiful thing, separating your implementation from your data, so that changes in your data set (as mentioned above) wouldn’t break your site.

This then led to the next issue?pages written with these technologies were either written in code (such as C with CGI, or Java with Servlets) which contained lots of HTML-writing code snippets, or written with numerous code segments embedded in HTML (such as PHP or ASP). This led to problems as increasingly sophisticated Web page designs got harder and harder to ‘activate’ with data, and become increasingly brittle when dealing with change requests.

Here is where Jakarta Velocity comes in?making it so you can have ‘active’ Web pages, but where the design and the implementation details are kept neatly separate through the use of templates. Using Velocity, a designer can design a page and put inactive placeholders on the page that the developer will use to activate the page. You’ll see this by example a little later. It should be noted that this isn’t the only use for Velocity?it is in fact a generic template engine that can be used for outputting any kind of text, but Web pages are obviously a very useful example.

The problems that Velocity will help you to solve are perhaps best demonstrated with an example. Using a data-driven, Web-based report generation scenario, you’ll work through the various methods that have been used to fully understand the drawbacks of doing it with the HTML-in-code approach of a servlet, the code-in-HTML approach of JSP or PHP, and the new option of template driven development that Jakarta Velocity offers.

Figure 1. Sample Sales Report: This is a report mockup, intended to show developers what a finished report should look like.

Scenario: Sales Report
The typical scenario for building a Web application is that the business owners for the application specify what they want, and how they want it to appear. A designer or artist then usually generates a mockup of the application’s pages using an HTML design tool such as Microsoft FrontPage or Macromedia Dreamweaver, or a graphic editor such as Photoshop. In this example, the business owner wants an application to generate a sales report from a customer relationship management (CRM) database and an order tracking system, and he wants it to look similar to Figure 1.

This report was mocked up with Microsoft FrontPage, so the sensible thing for a developer to do is to use its HTML as a starting point and embed the required on-demand data-driven information in it at runtime. You can see the mockup HTML in Listing 1.

Approach 1. Using a Servlet
Once upon a time, servlets were (along with CGI) the most popular way to generate content. They’re still compelling, when you consider all the freebies that come along with using an application server running a servlet, such as load balancing, clustering, etc., but is very ungainly when it comes to change control.

The download contains a servlet called SalesReport.java that contains the “traditional” server methodology in a method called doServletWithStandard. The following code snippet shows a portion of the method.

private void doServletWithStandard(HttpServletRequest request, HttpServletResponse response) throws IOException  {    Statement stmt = null;     ResultSet rs = null;     String strSql = "";    int nColCount = 0;          response.setContentType(CONTENT_TYPE);    PrintWriter out = response.getWriter();    out.println("");    out.println(       "SalesReport");    out.println("");    out.println("");    out.println("");...    out.println(       "Amount");    out.println("");    while(rs.next())    {          out.println("	");      for(int i=1;i<=nColCount;i++)      {         out.println("" +             rs.getObject(i) +");      }      out.println("	");...   out.println("");   out.close();

You can see that this code is full of out.println statements that output the HTML from the mockup, and in the “meat” of the page that presents the list of sales report line items, a loop iterates through a recordset writing out the items embedded within the

HTML classes. The servlet works nicely?you can see its output in Figure 2 (generated from a MySQL database?for which the create scripts are available in the download).

Figure 2. The Sales Report Generated by a Servlet: The servlet code generates the report table, using “out.println” statements to integrate the data into the mockup HTML.

The servlet result is pretty close to the mockup; only the “Amount” information is off due to the fact that no formatting was done on the item in the code?it simply outputs the raw data from the database. This highlights the first problem?custom formatting of data, where the value 1200000 should be presented as $1,200,000, in bold print, and right-aligned. To fix the problem, the “Amount” style could be specified in the HTML as a CSS style, and that style applied to the data, or the servlet could output custom HTML containing the formatting information for that column. The point is that small snags like this can add up to many problems in managing change control. Generally, projects like this one have a high friction rate between the business and the developers?particularly when changes are necessary. How many times have you heard a question along the lines of: “It’s easy for me to change it in FrontPage, why it is so hard for you to change it in your servlet?” This friction is made even worse when you understand how some tools (such as FrontPage) make changes to the HTML code underlying a page when a change is made (for example) to some of the CSS style definitions.

Approach 2. Embedding Smart Code in the HTML
This is the approach used by technologies such as PHP, ASP, or JSP, where you embed tags in the HTML document that the server interprets and executes, changing or generating HTML for you on the fly. For the purposes of this example I’ll use PHP, but the approach using ASP or JSP is similar.

Name

Company

Sales details

Amount

As you can see, the preceding code closely resembles the original HTML file, except that the hard-coded values have been removed in favor of code that generates the values from the database.

Figure 3. PHP Report Output: Here’s the report output generated by the PHP example.

Figure 3 shows the output generated from the PHP page. Pretty good, huh?

The problem here is similar to that with the previous approach. You had to take the HTML off the designer, and amend it to “activate” it. This approach is less intrusive, as the developer needs only to add to the existing mockup HTML, rather than taking all the code and line-by-line putting it into out.println statements as in the servlet example?but the problem is, what happens when the HTML changes? You get an all-new document without your PHP tags in it, and have to start again. There are workarounds, such as making the designer work with your PHP when tweaking their design, but from experience this has led to more problems that it has solutions as WYSIWIG designer tools such as FrontPage can end up overwriting your code.

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.

  Name  Company  Sales details  Amount#foreach ($Item in $theList)  $Item.PersonName  $Item.CustomerName  $Item.ContractDescription  $Item.Amount#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 templateTemplate 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 outout.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!

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

The Latest

homes in the real estate industry

Exploring the Latest Tech Trends Impacting the Real Estate Industry

The real estate industry is changing thanks to the newest technological advancements. These new developments — from blockchain and AI to virtual reality and 3D printing — are poised to change how we buy and sell homes. Real estate brokers, buyers, sellers, wholesale real estate professionals, fix and flippers, and beyond may

man on floor with data

DevX Quick Guide to Data Ingestion

One of the biggest trends of the 21st century is the massive surge in internet usage. With major innovations such as smart technology, social media, and online shopping sites, the internet has become an essential part of everyday life for a large portion of the population. Due to this internet

payment via phone

7 Ways Technology Has Changed Traditional Payments

In today’s digital world, technology has changed how we make payments. From contactless cards to mobile wallets, it’s now easier to pay for goods and services without carrying cash or using a checkbook. This article will look at seven of the most significant ways technology has transformed traditional payment methods.