The ZK Framework

ZK is a framework that introduces event-handling programming—backed by an AJAX engine—to web applications.


January 15, 2008
URL:http://www.drdobbs.com/global-developer/the-zk-framework/205800349

Andrzej is a systems developer in Oslo. He can be contacted at [email protected].


ZK is a framework for building web applications. It was developed by Potix (www.potix.com) and distributed under both GNU and commercial licenses. The main idea behind ZK is to introduce event-handling programming—backed by an AJAX engine—to web applications. This lets you focus on designing forms and programming reactions on possible events. Low-level HTTP communication between the browser and server is therefore the exclusive duty of the framework.

Another ZK feature is the use of the XML User Interface Language (XUL) as a description language of graphical forms. (ZK refers to the description language as "ZUL.") XUL lets you define forms as XML documents where individual tags correspond to controls on a form, simplifying the process of designing web interfaces. You can also create forms in Java using a dedicated API, somewhat like using the Swing library. ZK refers to this method as using"richlets."

Using the Framework

To use the framework, copy libraries from the ZK distribution (directories dist/lib and dist/zkforge) into a directory WEB-INF/lib in your project. Then configure file web.xml by defining:

The servlets zkLoader and auEngine (Listing One) are responsible for "double-track" service of HTTP requests arriving from a browser. A program configured this way is available online; it also collects all samples from the article (see code at http://www.ddj.com/code/).

 
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="ZKdemo" version="2.4" 
  xmlns="http://java.sun.com/xml/ns/j2ee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
   <display-name>ZKdemo</display-name>
   <welcome-file-list>
      <welcome-file>index.html</welcome-file>
      <welcome-file>index.zul</welcome-file>
   </welcome-file-list>
   <servlet>
      <description>ZK loader for evaluating ZK pages</description>
      <servlet-name>zkLoader</servlet-name>
      <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
      <!— Must. Specifies URI of the update engine (DHtmlUpdateServlet). —>
      <init-param>
         <param-name>update-uri</param-name>
         <param-value>/zkau</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup><!— MUST —>
   </servlet>
   <servlet>
      <description>The asynchronous update engine for ZK</description>
      <servlet-name>auEngine</servlet-name>
      <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet
        </servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>zkLoader</servlet-name>
      <url-pattern>*.zul</url-pattern>
   </servlet-mapping>
   <servlet-mapping>
      <servlet-name>zkLoader</servlet-name>
      <url-pattern>*.zhtml</url-pattern>
   </servlet-mapping>
   <servlet-mapping>
      <servlet-name>auEngine</servlet-name>
      <url-pattern>/zkau/*</url-pattern>
   </servlet-mapping>
   <listener>
      <description>Used to cleanup when a session is destroyed</description>
      <display-name>ZK Session Cleaner</display-name>
      <listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
   </listener>
</web-app>


Listing One

Figure 1 is the typical flow control in ZK-based applications. To start, users initiate connection with a server by entering the address of a requested page in a browser. On the server side, the ZK engine loads the ZUL or ZHTML page (or passes control to a richlet, if it is responsible for rendering the page). A method from your page controller is called for handling the pageinit event. This method collects data from a database for visualizing to users. Next, on the basis of the page definition, the framework creates a tree of components describing the page, which displays the data collected in the previous stage. The tree of components is responsible for recursively rendering HTML code that ZK sends to the browser.

[Click image to view at full size]

Figure 1: The ZK Framework architecture.

Let's say users clicked a button on the page displayed in the browser, or modified a field on a form. If a handler for this event was registered, the ZK AJAX engine notifies the server about the event. ZK receives the event on the server side, and actualizes a state of components representing page elements. Changes made by users on the form are introduced to the component tree reflecting form elements. An appropriate event handler is then called. The method can read updated data from the form, perform some operations on the database, then decide about modification of displayed data or page structure, displaying validation messages or some question directed to the user. ZK passes these orders back to the JavaScript engine working on the browser side, which executes appropriate modifications of HTML DOM.

Defining of Forms

The most convenient way of describing web pages in the ZK environment is via the ZUL language—a subset of XML for describing web UIs. ZUL document tags correspond to graphic controls on forms and are nested in the same way as the controls are embedded on the page. This is an idea borrowed from XUL and developed by Mozilla. A similar concept is XAML implemented in the most recent version of Windows. Compared to traditional methods of creating UIs via specialized APIs (as in GWT), such a declarative solution results in shorter, more lucid code, reducing development time and making maintenance easier.

Listing Two is a ZUL document, and Figure 2 is a page rendered on its basics (with some enhancements). This page consists of a window that embodies page content, a label for displaying messages, and a button triggering server-side action. On a display request, ZK creates a page initiator object of the type HelloWorldInit and window controller HelloWorldCtrler. The identifier helloWindow is a reference to the controller object and allows for calling its methods inside scriptlets placed on ZUL pages.

[Click image to view at full size]

Figure 2: Example MDI interface in ZK.

<?xml version="1.0" encoding="utf-8"?>
<?init class="zkdemo.ui.controler.HelloWorldInit"?>

<window id="helloWindow" title="Welcome window" border="normal"
  use="zkdemo.ui.controler.HelloWorldCtrler">
   <label id="messageBoard" value="${helloMsg}"/>
   <button label="What's the time on a server?" onClick="helloWindow.showTime()"/>
</window>
Listing Two

Listing Three (available online) is the initiator of this page. Its task is to set up the helloMsg variable in the page context before rendering. The variable is accessible for EL ("Expression Language"), the same language as in standard JSP.

The HelloWorldCtrler class (Listing Four, online) enhances the component definition org.zkoss.zul.Window. Its showTime method invokes getFellow from the base class to find a Label component. A change of state of this component is automatically reflected on the client side, without the need to reload the whole page and without web developers writing a single line of JavaScript code.

Beautifying the Page

You can modify the appearance of ZUL components using Cascading Style Sheets (CSS), in a way similar to HTML documents. For instance, you can make the font of the message thicker with:


<label id="messageBoard" 
   value="${helloMsg}" 
     style="font-weight: bold"/>


However, directly defining the style for each control is not the best practice. As with HTML, you can define sets of styles for ZUL documents that can be used by passing identifiers (see Listing Five, also online).

Multiple Document Interface

Displaying child windows is an important technique for constructing complicated UIs in rich client applications. For example, the process allows the separation of some controls into wizards, which help to fill out a form. Unfortunately, such techniques are unavailable in classic web applications. ZK supports the concept by allowing for one page to consist of many nested windows, which also can be modal. Each of these windows is placed in a separated CSS layer and, with help of a mouse, users can move, resize, or close them. For each window, a server creates its own event-handling thread. To use this technique in ZUL, you apply the <window> tag declared with parameter mode set to overlapped or modal; see Listing Six (online).

Visualizing Tabular Data

Creating tables in ZK is simplified using the forEach attribute, which can be applied to any ZUL component. It accepts values of type java.util.Collection or arrays. Using this attribute causes a tag that is owner of the attribute to be displayed multiple times. Listing Seven (available online) is an example of this technique.

Listing Seven includes a script that prepares data for tables (the default scripting language in ZK is BeanShell, which mimics Java; you can also use Groovy or Ruby). It is executed each time ZK loads the page. Then, Listing Seven defines a table and its headers (tags <grid> and <columns>) followed by a definition of table rows. Every control that has a <row> tag as its parent is interpreted as a definition of one table cell. The forEach attribute causes multiplication of the row definition for every element of array tabularData. The variable each takes subsequent values from the array backing the loop. This variable is defined in zscript, but it also accessible from EL expressions.

Tables With Dynamic Content

Now assume that you want to display a list of objects with mutable content; for instance, a list controlled by user-defined filtering. In Swing applications, you define a model and a view. Then you modify only the model, which automatically notifies the view about its changes, allowing the view to update displayed data. This is a benefit of the MVC pattern, implemented by JTable. In ZK, you proceed in a similar way, and a table is updated without reloading the whole page—only the necessary fragment of HTML code is changed (see Listing Eight, available online).

Tables With Nested Controls

You often need to add more interactivity to the UI table cells than just plain labels provide. For example, you might want to edit data directly in a table, or add special columns with edit or delete buttons. If you assume that a table will have invariable data, you can embed controls as in Listing Nine (available online).

Figure 3 shows the result of running this page. In this example, you can see some other techniques that are characteristic of the ZK environment. Similar to JSP, some default objects are available on ZUL pages. In the example, I used:

Another defined variable inside the forEach loop is forEachStatus.index, which counts loop iterations. ZUL also offers the ability to define values of any component attribute in a special tag named <attribute>. In the example, I used it to simplify a script that reacts to an onClick event. For every ZUL component, it is possible to define its own new attributes with the help of a <customattributes> tag. Such attributes can bear any Java objects as values. In the example, it allowed me to store the number of a row, and then identify it when the Delete key was clicked.

[Click image to view at full size]

Figure 3: Table with buttons embedded in its cells.

An interesting functionality of the ZK framework is a class imitating the JOptionPane from the Swing library, which displays standard dialogs. In ZK, you can use org.zkoss.zul.MessageBox for this purpose. It is especially helpful in web programming because it lets you mix program logic with basic user interaction. Anyone who wants to ask for confirmation of a current operation after checking some conditions in business logic will appreciate this functionality.

At the end of the example code handling the onClick event, there is a redirection to another page (in this case, to force refresh, it is the same page). Here, I use a static sendRedirect method of the org.zkoss.zk.ui.Executions class, which is analogous to sendRedirect from javax.servlet.http.HttpServletResponse.

Tables, Nested Controls, and Dynamic Content

By defining a model, you make the ZK table responsible for visualization. In this case, however, you can't specify in ZUL which controls you want to use. ZK can still help with a technique that defines a custom renderer of the table rows view (Listing Ten, available online).

The method render of class zkdemo.ui.view.GridRowRenderer is responsible for typesetting an individual table row. For that purpose, it must create child components for the org.zkoss.zul.Row object, which visualizes cells in this row. In the example program, this takes place in the beginning of this method, where labels are created inside a for loop. The rest of the method creates an additional button together with its ON_CLICK event handler. To complete the example, you only need the ZUL table that will set the type of its rows (Listing Eleven, available online).

In this example, I also used an alternative method for building a UI in ZK, based on a specialized API. For every ZUL tag, there is a corresponding class with properties that reflect the tag attributes, making it possible to create whole pages in Java alone. Sometimes, this technique offers more flexibility than using XML.

Your Own ZUL Components

JSP technology lets you define custom tags by writing JSP fragments in a separated file. In a similar way, you can create new ZUL components by encapsulating pieces of ZUL or ZHTML code into a file. Then you can import such definitions to your own page, name them by some alias, and use them in the same way as standard ZUL components. Similar to JSP custom tags, you can pass parameters to a component defined in such a way by setting up attributes of the tag. These parameters are available in the code of the component—as variables with the same names as the attributes, but preceded by the prefix arg. Listing Twelve is a ZHTML example component, while Listing Thirteen (available online) shows its use on a ZUL page.

Integration with HTML, JSP, and JSF

ZUL code can be easily merged with HTML; for instance, to arrange ZUL controls with the help of HTML tables, or to use specific functionality such as sending e-mails from web pages. There are two methods for mixing together ZUL and HTML code. First, XHTML tags can be embedded into ZUL documents after declaring their appropriate namespace (see Listing Fourteen; available online). The second technique relies on using a special ZUL <html> tag and with a fragment of HTML pasted in as its content (Listing Fifteen, available online).

Today's applications are usually built using many different technologies. ZUL pages allow easy integration with the existing code of the view layer, created via JSP or JSF. This is possible by applying <include> tags on JSP pages, which incorporate ZUL fragments; for example:

<jsp:include page="/my/embedded.zul"/>


ZUL pages can also include other resources served by a web container, such as servlets, JSP or JSF pages, or other ZULs or richlets. This is also accomplished by applying the <include> tag:


<include src="/my/servlet"/>


Integration with External AJAX Components

Several open-source packages supporting the creation of advanced web interfaces are distributed with the ZK framework. Among them are an interface for Google Maps, JFreeChart (for generating advanced diagrams), the HTML graphic FCKEditor, and a border layout manager from the Ext JS library. They are integrated with the framework by being wrapped in ZUL tags. Listing Sixteen (available online) is an example of creating data presentations with the help of the <chart> tag, which gives access to JFreeChart functionality.

Conclusion

ZK seems to be one of the more interesting frameworks to come along and make web programming easier. Its strong suite includes browser interoperability, an event-handling paradigm, MDI functionality, and a set of neat standard controls. And, according to test results, its performance looks decent. Emerging features include a ZK client for mobile devices and an expected Eclipse plug-in for the graphic design of ZULs. Lastly, ZK is intuitive and easy to use.

Among the disadvantages, there is incomplete support for keyboard navigation over a GUI (for instance, for a menu component) and occasional problems with the localization of standard messages hidden in JavaScript files.

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.