Gerd has posted 5 posts at DZone. View Full User Profile

ztemplates: Yet Another Web Framework?

04.07.2008
| 6906 views |
  • submit to reddit
Location: 
http://www.ztemplates.org

ztemplates logoztemplates is a small and easy to learn open source action web framework. Let's meet its author and find out what it's about!

ztemplates is based on JDK 1.5 or later. It integrates well with Apache Velocity, JSP, AJAX, Yahoo User Interface (YUI), Google APIsFreeMarker renderers. ztemplates comes with a separate sample package called ztemplates-yui, that shows how to access YUI, Google AJAX Search and netvibes from zt and can easily be extended to your preferred rendering technology.

What's the background of this web framework?

ztemplates is maintained by me, Gerd Ziegler. I studied Computer Science in Munich, Germany. I have about 12 years of experience as a Java programmer. Currently I work as a freelance contractor in the Munich area and have specialized on the Java platform. When not working I spend my time with my lovely daughters or go windsurfing...

ztemplates started 2 years ago as a hobby project and just for fun. The first approach was to declare POJOs with properties and operations and to map the operations to urls and the POJOs to templates. The approach soon ran into problems. Mapping POJO operations to URLs means the framework must create initialized POJOs before calling the operation. Because the framework had no control over how the POJOs were created, I tried to assign IDs to the POJOs and to cache the POJOs on the server side. The framework needed full control over the URL format. Well, because of the back/history button, the state could become corrupted. So I introduced version numbers, but now bookmarks would fail. And what if the user opened two browser windows?

So there were a couple of problems:

  • the URL did not carry enough information to create a fully initialized POJO
  • the framework claimed full URL format control
  • there was the server side state that was always hard to keep in sync with the client

But not all was bad. I really liked the fact that the render-POJOs exposed their data to the template. It was so easy and straightforward to write an HTML fragment and include it in another HTML file. Also the "autodiscovery" feature was cool: I did not have to edit any configuration files. So I dropped the first approach. I split the pojos into render and action POJOs. In fact, I found that the two are completely independent. Now you can use only the action-POJOs, or only the render-POJOs, or both.

Then I made the framework completely stateless. No more serverside IDs, versions or the like. But then the information must all come from the URL. I needed expressive URLs. Also I did not want to constrain the URLs. So I decided to create the URL-variables. Now the programmer can create URLs as he likes and can also conveniently match the URLs and extract values from the URL. The URL matching process also offers natural points for callbacks. So I introduced before and after callbacks on the whole process, as well as for each URL variable.

Now the action-POJOs contain the logic and access the data layer, the render-POJOs are passive view-data holders, the templates contain the layout skeleton. But what about css? So I added features for css fragments. And what about AJAX? Luckily this fitted very well with ztemplates. The render-POJOs declare in annotations which css/js they need and the framework collects the declarations and computes the script declarations. It turns out that you won't even see the AJAX when using a ztemplates component. In fact, components can be packaged completely selfcontained into one JAR file. A component programmer includes in his component-jar the css and js and the action-POJOs that return those js and css. Because ztemplates scans the classpath, it will find the POJOs and so will dispatch requests for js and css from the JAR to the action-pojo in the jar. Also, as mentioned before, ztemplates computes all <script> tags based on the render-POJOs it uses for a particular response, so the programmer using a component does not have to keep track of all these. Just drop the JAR into WEB-INF/lib and use it.

But... why yet another web framework?

  • ztemplates comes with a new and unique url processing module. If you imagine the URLs as a tree, in ztemplates not only the leaves carry information but also the path from the root of the tree to the leaf.
  • ztemplates has annotation-based AJAX support. You need not worry which css or javascript to import when using provided components. ztemplates computes all js/css declared on all POJOs that contributed to the page output, sorts the dependencies topologically, eliminates duplicates, and makes the declarations available in a variable called "zscript".
  • ztemplates is robust. It's hard to break urls by refactoring, moving or renaming files.
  • ztemplates is a filter. It passes through all urls it cannot match. So you can transparently add it to or remove it from your existing webapp.
  • Most frameworks have a steep learning curve and lots of xml files scattered around in different places. In contrast, ztemplates needs no configuration, just declare a filter in your web.xml and map it to '/*'.
  • With ztemplates you can define modular components. New modules are installed by just adding a jar to WEB-INF/lib. The jar contains all resources, like javascript and css and all code needed to access it. All files are kept in one place. You won't even see if the component uses ajax or not. See a complete tutorial for Google Search here.
  • ztemplates is statefree
  • it places no constraints on the url format
  • Can you show an application created using ztemplates?

    For an application using ztemplates and Yahoo YUI see tagger24.com. Here's a screenshot:

    tagger24.com frontpage

     

    Can you walk us through a "Hello World" scenario?

    To get a first feeling of what it all looks like, here's a "Hello World" example with Apache Velocity. Begin by creating an empty application. To show an important feature, the example will read a value from the URL and display it. The view consists of two parts, a render POJO and a template. The intention is to completely separate the layout from the view-data. The render-POJO contains the data to be displayed, in this case a simple String value called "message". Not only Strings are allowed here, but any type, including another render-POJO. The property-getter must be annotated with @ZExpose. The render-POJO is passive and does not access any data layer. The data is provided from the outside.

    @ZRenderer(ZVelocityRenderer.class)
    public class HelloWorld {

    private String name;

    public HelloWorld(String name) {
    this.name=name;
    }

    //make a property called 'message' available to
    //the rendering engine/template, in this case velocity
    @ZExpose
    public String getMessage() {
    return "Hello World " + name;
    }
    }

    In this case the template is a simple Velocity template that uses the exposed property from the render-pojo. By default the template file is placed at the same location as the render-pojo class.

    <html>
    <h1>${message}</h1>
    </html>

    The active part of a ztemplates application is the action-POJO. Action pojos match URLs. In our case the url contains a url-variable called "name". This is a placeholder for some arbitrary value (that cannot contain a '/'). Notice that the action-pojo declares a String property with the same name, and a getter and a setter method. At runtime, when matching the url, ztemplates will call the setter with the actual value from the url and then call the 'after' callback. So when calling "/helloworld/java" the name will have the value 'java'. In the after callback, which is called after the url is matched, the action-pojo creates the view-pojo, fills it with data, (in this case just the value from the url) and calls the ztemplates ServletService to render the view-pojo to the response.

    @ZMatch("/helloworld/${name}")
    public class HelloWorldAction {

    private String name;

    public void after() throws Exception {
    ZTemplates.getServletService().render(new HelloWorld(name));
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }
    }

    Tell us about the ztemplates controller. How is it special?

  • ztemplates is built around urls: /index
  • urls can contain url-variables: /blog/${author}/${date}/edit
  • annotate a action-pojo with @ZMatch("yourUrlPattern"): @ZMatch("/index")
  • url-variables are assigned to action-pojo properties
  • urls can be nested(included) in each other with url-references /page/#{menu}/#{content}.
  • the nesting supports inheritance (polymorphism)
  • the url defines a sequence of callbacks.
  • the callbacks contain the application logic and create the view (render-pojos).
  • Unlike other frameworks, where the url is used to instantiate one action handler, in ztemplates the url is used to select a sequence of action-handlers from a hierarchy of actionhandlers, defined by the url-references.

    What about the view?

  • define the view model in render-pojos
  • define the view layout in a template file (JSP, Velocity,...)
  • annotate the render-pojo with @ZRenderer to link the pojo to the template
  • annotate the pojo-properties with @ZExpose to expose them to the template
  • include views by exposing render-pojos with @ZExpose(render=true). This will expose not the value itself but will first render the value and expose the resulting String.
  • style the view with css by placing a css fragment next to the pojo. ztemplates will aggregate all fragments in the classpath to one style sheet available as ztemplates.css
  • declare JavaScript javascript/css files needed by your pojo/templates with annotation @ZScript
  • include the JavaScript and css needed in your page header by using the $zscript variable computed by ztemplates. ztemplates computes all css/js declared by all pojos that were used to render the page, in the correct order and exposes it as "zscript" to the renderer.
  • There is a strict separation between the action processing, the view model and the rendering. In fact the view model is transformed into an abstract representation that is made availabe to the renderer. You could mix Velocity with JSP or any other rendering technology in the same page without even noticing.

    What's the latest news from ztemplates?

    I have just released ztemplates 0.9.9.2 with AJAX support (YUI, Google Search).

    Where to look next?

    For an example on how to integrate ztemplates with AJAX components see Googles AJAX Search. See further details on ztemplates.org.

    Thanks Gerd, for telling us about ztemplates!

     

     

    0
    Average: 4 (1 vote)
    Published at DZone with permission of its author, Gerd Ziegler.

    (Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)