I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

Simple HTML Output From Java Using renderSnake

03.16.2011
| 10944 views |
  • submit to reddit

renderSnake is another interesting project that I noticed through the JavaLobby announcements section. The idea is simple but effective - to produce HTML output from the creation of Java components. I spoke to the project owner, Ernest Micklei to find out more  

Ernest Micklei is a senior software developer/architect with 19 years of experience in software engineering practices. He holds a degree in advanced computer sciences and has a gained a broad knowledge of programming languages, tools, methodologies, architectures and practices. Mostly active in Java,Ruby,Flex and Smalltalk related projects for Insurance, Banking and E-commerce. He is owner of several open-source projects and contributes to others. His main interests are SOA, Concurrent Oriented Programming, Domain Driven Design, Cloud Computing and High Performance Websites. His current position is software architect at Bol.com.

DZone: What is renderSnake and how does it work?

Ernest Micklei: renderSnake is library of classes and interface that support the creation of Java components (as classes) that can produce HTML by rendering themselves using a HtmlCanvas object. This class provides methods to open and close HTML tags.

canvas.html().body()._body()._html();
<html><body></body></html>

A method name prefixed with an underscore will verify and close the element. Most such methods also accept an HtmlAttributes instance. This class provides methods to add attributes, key-value pairs.

canvas.div(id("header"));
<div id="header">

In addition to tags, an HtmlCanvas can also render components. A component is a POJO that implements the Renderable interface and typically encapsulates an HTML fragment from a page.

public class MyComponent implements Renderable {
public void renderOn(HtmlCanvas html) throws IOException {
html.h1().write("I am a component")._h1();
}
}

and you can use this component like this:

canvas.render(new MyComponent());

You can read more about how renderSnake works here

DZone: Where did the name come from?

Ernest Micklei: The name is just a combination of "render" and "Snake". Producing HTML is done by programmatic rendering the elements (tags,attributes) on a canvas (empty page). This metaphor is taken from the Seaside framework, a popular Smalltalk web component-based framework.
A good friend of mine suggested that I associate the project with some animal creature. If you look at the source code of the resulting renderOn method definitions then, with some imagination, you can see a vertical wave shape that looks like the movement of a snake. The "S" in the name is written in uppercase to emphasize this.

DZone: How long have you been working on the project?

Ernest Micklei: The project started in October 2010 and it was first called NoJSP (yes, I am following the NoSQL movement too) but that name was dropped because of its negative impression.
I was working on a big project that has seen an immense growth (400+) in the number of JSP pages and fragments, most of them following the old Model 1 architecture. (http://www.java-samples.com/showtutorial.php?tutorialid=349). Its out-of-control complexity, partly related to JSP technology, motivated me to experiment with a different approach that is more closer to what Java developers know and practice.

Having experience with the Seaside framework, that also let you write components in the same programming language as your domain logic, I started a proof of concept in Java to explore APIs and class designs. Then I converted part of an existing Web application to see what it would take to implement that using renderSnake. As expected, the implementation using components was much easier to work with; smaller components, composable, easy to refactor and better testable. Finally, I did some performance measurements and looked at memory allocation/garbage, page size and throughput. To results were promising and then I decided to continue this project and share it with the Java community.
 
DZone: Why did you choose Java as the project language?

Ernest Micklei: Java was chosen because the library is intended to be a alternative to JSP technology in web applications leveraging existing "business" logic to drive the rendering phase. Another motivation was to be as close as possible to an existing popular language for which numerous tools and libraries already exist. Developers that want to use renderSnake should not have to learn yet another language ; its all Java and HTML.
 
DZone: What integrations exist?

Ernest Micklei: With respect to the well-known MVC pattern, I consider renderSnake to be an alternative to implement the view layer for web applications that adopt this pattern. Although the library includes a RenderSnakeServlet (the controller part), it is designed with minimal dependencies such that it can integrate with other frameworks. If such a framework has a hook where you can create a HtmlCanvas then you can start rendering your components.

(1) An easy integration to start with is using JSP. In this approach, the JSP page is used as a controller that retrieves domain objects. It creates the HtmlCanvas object and starts rendering your Page component. The following is a scriptlet example that could be part of the accounts.jsp file.

<%
// fetch the list of accounts
....
HtmlCanvas canvas = new HtmlCanvas(request,response,out);
canvas.getPageContext().set("accounts", listOfAccounts);
out.clearBuffer();
canvas.render(new AccountListPage());
%>


(2) The Spring-MVC framework has much better support for integrating different view technologies. The renderSnake library includes both a ViewResolver and ArgumentResolver to provide two solutions for a seamless integration. Using the latter approach, by declaring an HtmlCanvas argument in your dispatch method of your Controller, you can prepare the PageContext and start rendering your components.

@RequestMapping("/example.html")
@ResponseBody
public void renderExample(HtmlCanvas html) throws IOException {

html.getPageContext().set("today", new Date()); // stick domain objects in the context
html.render(new SiteLayoutWrapper(new ExampleUI())));
}

The renderSnake library also provides integration with template based sources. The classes StringResource and StringTemplate can be used to encapsulate snippets of multi-line texts or embedded Javascript that must be included in the page. StringResource is meant for wrapping static content, StringTemplate is meant for wrapping content that has only a few content placeholders.

DZone: Can you give a code snippet showing how to use it?

Ernest Micklei: Below is an example of the Logo component of the renderSnake site itself.
It encapsulates the HTML fragment responsible for displaying the title and a subtitle.
The html object has methods for all HTML elements such as div, h1, a and style.
These methods optionally take an HtmlAttributes argument which are created by factory methods such as id, href and class_.
Because every HtmlCanvas element method returns itself, you can use a fluent programming style by "dotting the methods".

public class Logo implements Renderable {
public void renderOn(HtmlCanvas html) throws IOException { //@formatter:off
html
.div(id("logo"))
.div(id("logo_text"))



.h1()
.a(href("index.html"))
.write("render")
.style().write(".snake { color:yellow; }")._style()



.span(class_("snake")).write("S")._span()
.write("nake")
._a()
._h1()
.h2().write("lean and mean HTML page writing machine")._h2()._div()



._div();
}
}



By using proper indentation of the source, you can visually verify that elements are closes properly (this is checked at runtime).
To test this component in isolation, all you need to do is create a HtmlCanvas and render an instance of this Logo.  

 
DZone: Could you provide us with an architecture overview?

Ernest Micklei: Here are two diagrams that illustrate the use and internal design of renderSnake.
The MVC example shows how the renderSnake components can be used to implement the View layer in the MVC pattern.

 

The class diagram shows the essential classes to work with when building components.



DZone: Why do you say renderSnake is efficient ?
Ernest Micklei: renderSnake is designed with minimal object creation in mind resulting in low garbage colllector activity. Instead of creating a DOM tree of Html element objects, all output is directly written on the outputstream as (encoded) Strings. The same design is applied to the HtmlAttributes class. Instead of maintaining a Dictionary of attributes with encoding information, attribute key-value pairs are written directly on a StringBuilder. Most render components are small and short-lived ; they are only needed during the rendering phase of handling a request.

Comments

Aaron Digulla replied on Fri, 2011/03/18 - 5:27am

This looks promising. I'm just wondering: Why don't you use

div(id("content"),
    a(href("..."),
        text("link")
    )
)

 that is:Why do you use _div instead of nested parameter lists?

E Micklei replied on Mon, 2011/03/21 - 4:31am

That design would result in building a complete DOM-like tree object in memory before it can be written to output (creates many objects -> lots of garbage per request). In addtion, the canvas api would become more complex because parameters can be attributes, elements or your components.

If Java had closures (like Smalltalk blocks) then I would reconsider such a design. Until then the more verbose _div() message sends are needed. At least this has one advantage, you don't have to count brackets ; by proper indentation you visually verify the correctness of your XHTML.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.