devxlogo

View Rendering in Java: Templates Out, Groovy Builders In

View Rendering in Java: Templates Out, Groovy Builders In

he rationale for using template engines to render views in Java web development is generally two-fold:

  1. Templates can be created and maintained by HTML coders.
  2. Templates are easy for HTML coders to read, as they are based on HTML formatting.

In my experience, both arguments are flawed. The first one rarely happens, and the second holds true initially but becomes seriously compromised as soon as any presentation logic is introduced. Groovy builders, a literate solution for bringing view rendering back into your code, provide a better alternative to the template engine.

This article explains the issues inherent in using template engines, and then shows how to use Groovy builders for view rendering.

Template Engine Issues
When using template engines for view rendering, you will encounter two main issues that make templates less than ideal:

  • Testability
  • Limited design options

Testability
Templates are hard to test. Imagine you are implementing some presentation logic to highlight alternate rows in a table (this will serve as the view-rendering example in upcoming sections). Depending on the template technology you’re using, you will face different costly and time-consuming requirements. With JSP, you would need to take one of two approaches:

  1. Out-of-container compilation (assuming your servlet container allows it)
  2. Within-the-container compilation (when your servlet container doesn’t allow out-of-container compilation)

For the first approach, you must:

  • Compile the JSP into a servlet class that can be executed.
  • Execute the compiled JSP, providing your data is in the correct scope.
  • Parse the output to ensure the correct rows have been given the highlight class.

For the second approach, you must:

  • Deploy your application to your servlet container.
  • Make sure the container and application is running.
  • Use a testing library like HTMLUnit to call your page.
  • Check the correct rows have been given the highlight class.

Given the high cost of these options, it is no surprise that presentation logic in JSP is rarely tested.

Testing is a little easier if you use another template language, such as FreeMarker. In that case, you will at least be testing the page in the same environment as it is executed. However, you still have to render the view template file and parse the output to verify that the rows had the correct classes applied.

Limited Design Options
When using templates for view rendering, you are limited to your framework’s implementation when you decide how to make sections of your view reusable. With JSP, you must use tags to create view components. With FreeMarker, you are able to implement macros. While SiteMesh uses the decorator pattern. If you were able to use code to implement the view, you would have the full power of object-oriented techniques and be able to use whichever design pattern you wish.

Both the testing and design options problems stem from the fact that template solutions are external rather than internal domain-specific languages (DSLs). As such, templates are developed outside of the scope of your programming language and therefore are likely to lack flexibility.

Enter Groovy Builders
A builder is a type of DSL that allows object structures to be constructed in a syntax that is expressive within a particular problem domain. Groovy has builder support based on closures and meta-programming that provides a much more expressive syntax than has previously been available in the Java platform (see Listing 1 for an example).

The structure of the document created in Listing 1 is very clear and easy to understand. Here is the markup of the output it produces:

      My Page        

Put the table here:

col1 col2
col1 col2

The downloadable source code for this article provides all the code for the simple builder example.

Testing Builders
So far, you have seen an expressive piece of code that can generate XHTML output. To test the code, you would still have to execute it and parse the output to ensure it is correct. To do this, you will need to refactor the example into a testable class that will implement the table-highlighting logic (see Listing 2).

Listing 2 implements the presentation logic to highlight alternate rows in a table, but because the builder is being constructed outside of this class, it also is now possible to test whether the correct logic is being performed by passing in a testing builder. There are a number of options for this:

  1. Use a basic NodeBuilder and then assert that the builder had the expected nodes in your test.
  2. Pass in a MarkupBuilder and use the Groovy XmlSlurper to verify that the correct XHTML had been constructed.
  3. Implement your own builder, upon which you can define expectations and then verify that the expectations have been met, in a similar approach to the EasyMock project.

Using the NodeBuilder would mean navigating through lots of child nodes just to get to the information you needed. XmlSlurper provides a very simple interface for parsing XML, which you can then perform GPath queries on to verify the structure is as expected (see Listing 3). While this approach is more elegant than using NodeBuilder, it is still much less clear than defining expectations and verifying them through your own builder (as the code in Listing 4 does).

In the first test (Listing 3), where the XML output is parsed, you can see that it is extremely simple to use Groovy to parse XML. However, this does not necessarily make the test easy to read. In the second example (Listing 4), the test is defining an ordered subset of the nodes you expect to be called and then using the builder for the execution and the verification that your expectations have been met.

You can download the source of AssertableBuilder in the source code for this article.

Extracting Page Components
So far, you have some expressive code that can generate XHTML, and you can test the presentation logic. However, the page you are working with is still extremely simple and trivial. If the page gets much bigger, your test is going to become cumbersome, as it has to set the expectations for each section of the page. Using the “zebra table” from the example, the following listings show how easy it is to extract page components now that you are using code to render the view.

To enable reuse and simplify future tests, you can extract the generation of the table to another class:

package viewbuilderclass ZebraTable {    def render(builder, rows) {        builder.table {            rows.eachWithIndex {row, i ->                tr('class': (i.mod(2) == 0) ? 'highlight' : '') {                    td("col1")                    td("col2")                }            }        }    }}

You can move the tests for determining whether the rows are styled correctly to the table component (see Listing 5).

You can simplify the table page to use the table component:

package viewbuilderclass ZebraTablePage {    def render(builder, rows) {        builder.html {            head {                title("My Page")            }            body {                p("Put the table here:")                new ZebraTable().render(builder, rows)            }        }    }}

You can see from the code listings above that it is extremely simple to extract the presentation logic still further into reusable components. The real benefit of this approach over the usual template ‘include’ approach is that these components are easy to test independently.

Flexible Design
The other benefit of using code for view rendering is that you are not restricted to any single presentation design pattern. This provides you the flexibility to implement views using whichever design patterns you choose, rather than being constrained to the patterns enforced by your template engine.

For example, it is just as easy to implement a decorator pattern as it is to create presentation components. With the code in Listing 6, you can define a layout class (MainLayout) to decorate page classes with a common page layout and title structure.

You can see that the MainLayout class defines the common layout elements for your site:

  • Title prefix
  • Primary navigation
  • Main content pane
  • Footer

A home page class can then use the layout class as its decorator and provide page details for the title and body content:

package viewbuilder.decoratorexampleimport viewbuilder.ZebraTableclass HomePage extends MainLayout {    def render(rows) {        builder.html {            head {                title("Home")            }            body {                new ZebraTable().render(builder, rows)            }        }    }}

The page defines its layout by extending a layout class. The page starts using the builder and passes off construction of the majority of the page to its layout through the title and body method calls.

The implementation of your individual pages now starts to become very simple. You can separate presentation logic out into components, the layout handles common page elements, and the page needs to handle only very specific page details.

For testing, you can test the home page class in the code examples above using the same approach as defined previously (see Listing 7).

Added Pros and Cons of Groovy MarkupBuilder
Two additional benefits of using the Groovy MarkupBuilder may not be immediately apparent. The first is that it is almost impossible to produce invalid markup because the builder opens and closes the nodes for you. As long as your code compiles, you will have well formed XML. The second benefit is that MarkupBuilder handles XML encoding of special characters (e.g., , etc.), which are a constant source of trouble in normal template-based development. This reduces your vulnerability to cross-site scripting attacks without you having to even think about it.

However, if you use the Groovy MarkupBuilder to render your HTML, you will eventually find that it does not allow text elements to intermingle with structured elements as children. Currently, you could not produce the following, although it is legal and very common in XHTML:

Some highlighted text

You would need to output this using the MarkupBuilder as follows:

Some highlighted text

This is not ideal, but it is possible to create a specific HTML builder to solve the current issues with the Groovy MarkupBuilder while keeping all the existing benefits (which is beyond the scope of this article).

Performance Penalty
One negative aspect of Groovy builders is their slow performance, caused by their heavy dependency on Groovy meta-programming. Groovy builders redirect a lot of method calls behind the scenes to provide the nested closure syntax. In fairly small pages, this isn’t cause for much concern. However, web pages that contain a large number of markup tags and require fast response times over the Internet tend to be slow if they are produced with a Groovy builder.

To gauge the difference between Java and Groovy performance for rendering HTML, the downloadable code provides a test called PerformanceTest.whichIsFaster. Run this test to see how the performances compare on your machine. The test generates an HTML table of results with 300 rows. Table 1 presents some results from my development machine.

Table 1. PerformanceTest.whichIsFaster Results from Author’s Machine
Run NumberJava HTML Builder
Using Proxy
MarkupBuilder
Without Caching
GroovyMarkup Builder
with Caching
Run 1
84 ms
753 ms
201 ms
Run 2
51 ms
539 ms
199 ms
Run 3
51 ms
535 ms
199 ms
Run 4
51 ms
533 ms
195 ms
Run 5
52 ms
529 ms
199 ms

The MarkupBuilder has two results per run because Groovy has such a high startup cost for the first execution. Subsequent executions are much faster, but still nowhere near as fast as Java’s.

The Internal DSL Approach
Groovy builders bring a level of expressiveness within code that previously was unavailable for the Java platform. This gives you the freedom to move away from the external DSL approach of template engines to the simpler, more powerful and testable internal DSL approach. There are performance problems when rendering large pages, but in these instances you can drop into Java to reduce response times.

As a final thought for improving the usage of builders, it would be great to be able to define the usage of a builder, either through a schema or programmatic constraints. This was discussed recently on the Groovy DZone, StateMachine: A Builder-Builder for Groovy, Part 1.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist