July 22, 2008

Designing rich AJAX Web interfaces with ZK

Author: Ben Martin

ZK is an AJAX toolkit designed to make creating user interfaces that run in a Web browser as simple as creating event-driven interfaces for desktop applications. The interfaces created with ZK use an XML markup language to define the user interface and Java code to implement the Web application's functionality. ZK includes support for data-bound controls so that you do not have to worry about updating the user interface forms when you change your Java objects.

If you are wondering why you see AJAX but JavaScript is missing from the above description, the following quote from the ZK Web site reveals the philosophy of the project -- "Our belief is that the best way to use Ajax is not to know its existence." The idea is that all the client-side code is contained within the ZK framework, and all the code that you develop runs on the server side, so you don't have to worry about AJAX or interpreting XML at all.

There are three binary downloads of ZK for standard server installs: Standard, Professional, and Enterprise editions. Each download includes all of the features of the lesser distribution and some additional ones. For example, the Professional Edition includes everything in the Standard one plus CAPTCHA, JFreeChart, and other features. There are also two distributions targeting mobile clients, one using Mobile Interactive Language, and a specific download targeting Google's Android and the Handset Interactive Language.

For this article I used a 32-bit Fedora 9 machine and Enterprise Edition version 3.0.6 which is about 21MB as a tar.gz. To use ZK you need a servlet container such as Apache Tomcat on your Web server. There are two ways to install ZK on your server: either as part of your Web application or as a shared component available to all Web applications in your servlet environment. The former method allows you to move your site easily, because ZK is embedded in your Web app, while the second method saves administration if you are using ZK in many sites on the same server.

Tomcat is available in the tomcat6 package for Fedora 9 and openSUSE 11, and the tomcat5.5 package for Debian-based distributions. The steps shown below install ZK as a shared component, allowing all Web applications to use it.

# yum install tomcat6 tomcat6-webapp
# service tomcat6 stop
# cd /tmp
# tar xzf /.../zk-bin-3.0.6.tar.gz
# cd zk-bin-3.0.6/
# vi /etc/tomcat6/catalina.properties
# mkdir -p /usr/share/java/tomcat6/shared/lib
# cd ./dist/lib
# find . -name "*.jar" -exec \
install -m 644 {} /usr/share/java/tomcat6/shared/lib/ \;
# service tomcat6 start

To test that your installation of Tomcat and ZK is working, download the zk-demo zip file and put the minimal Web application archive (WAR) file into your Tomcat webapps directory as shown below. The minimal war file does not include ZK, so the demo must be able to find it as a shared install on your Tomcat server. Once you execute the commands below, opening the URL http://localhost:8080/zkdemo-min/userguide/ should show you a demo of ZK loaded from your server.

# cd /tmp
# unzip /.../zk-demo-3.0.6.zip
# cd ./zk-demo-3.0.6/
# install -m 644 zkdemo-min.war /var/lib/tomcat6/webapps
# service tomcat6 restart

Using ZK

The ZK Tutorial gives a mile-high overview of what it's like to use ZK with the nuts and bolts covered in the Developer's Guide. The Web interfaces are defined using an XML file that is similar to the Mozilla XML user interface file format (XUL). These ZK XML files are referred to as ZK User Interface Markup Language (ZUML) or ZUL files. A trap for those unfamiliar with developing applications with Tomcat is that you will need a WEB-INF/web.xml file under the directory of any ZUL files you create for testing. Copying the web.xml file from the Resort example will allow you to start loading raw ZUL files.

The ZUL files can also contain some behavior. Things are of course much cleaner if you separate the Java code from the ZUL interface descriptions, but embedding code is still useful for experimentation. The embedded code has to be quoted so that it is legal XML, so double quotes in your Java code must become " for things to work correctly. If you have installed the Enterprise version of ZK you can also embed code written in JavaScript, Ruby, and Groovy directly into your ZUL files. The zscript element can be used to include larger blocks of code in ZUL files, with the added benefit that you do not have to XML escape double quote characters inside zscript elements. A simple ZUL file Web interface is shown below. It uses embedded Java to open a message box when a button is clicked.

<window title="Hello" border="normal">
<button label="Say Hello" onClick="Messagebox.show(&quot;Hello World!&quot;)"/>

If you want to keep the embedded code in ZUL files small, the two main features you are likely to use are EL expressions, where you can embed a small snippet of code to access a property of a Java object or perform a simple comparison, and the forEach statement, to populate listboxes and other repetitive ZUL elements. For reacting to events that the user interface creates, you can define your own subclasses of objects and explicitly use those subclasses in your ZUL files. This allows you to change your Java code, and thus how your Web app reacts to events, without having to touch the ZUL interface definition files. To avoid subclassing buttons just to react to them being pressed, you can route their press events to their parent object using the forward attribute.

ZK includes support for what is called "live data" models. Using live data, you implement the org.zkoss.zul.ListModel interface, and the data exposed through that interface can be viewed by different controllers on the Web page. In the following example, the Bookmark class is used as the tuple level, storing the URL, page title, and time the page was last visited. Accessor methods are not shown.

public class Bookmark
private String m_title;
private String m_earl;
private Date m_lastVisit;

public Bookmark() {}
public Bookmark( String title, String earl, Date lvisit )
m_title = title;
m_earl = earl;
m_lastVisit = lvisit;

To render Bookmark objects in a grid you need to provide a Renderer subclass that knows how you want to render these objects. The Renderer shown below renders each interesting piece of data into its own cell.

public class BookmarkRenderer implements RowRenderer {

public void render(Row row, java.lang.Object nastyDataRef)
Bookmark bm = (Bookmark)nastyDataRef;

new Label( bm.getTitle() ).setParent(row);
new Label( bm.getURL() ).setParent(row);
new Label( bm.getLastVisitTime().toString() ).setParent(row);


ZK provides a mutable implementation of org.zkoss.zul.ListModel in the ListModelList class. The controller object shown below creates a few example bookmarks in the data model, which could easily be fetched from JDBC or another source.

public class BookmarkController extends Window {
ListModelList m_bookmarks = new org.zkoss.zul.ListModelList( new ArrayList() );
Bookmark m_selected = new Bookmark();
public BookmarkController() {
m_bookmarks.add( new Bookmark( "Slashdot: News for nerds, stuff that matters",
"http://linux.com", new Date() ));
m_bookmarks.add( new Bookmark( "Linux.com :: Feature",
"http://slashdot.org", new Date() ));
m_bookmarks.add( new Bookmark( "The libferris VFS!",
"http://www.libferris.com", new Date() ));

Finally, the following ZUL file creates the Web interface shown in the screenshot below. Notice the use attribute for the window element, which tells ZK to use our custom Java class for this widget. For the grid, the model is specified as the Bookmarks member of our window class; more specifically the model will be m_bookmarks from the BookmarkController class. The renderer has to be specified so that ZK knows how to present our custom Java object in the grid.

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>

<window id="win" use="com.linux.zk.example.bookmark.ui.BookmarkController"
title="Bookmarks" width="800px" border="normal">
<grid model="@{win.Bookmarks}" rowRenderer="com.linux.zk.example.bookmark.ui.BookmarkRenderer" >
<column label="Title" width="70px"/>
<column label="URL" width="250px"/>
<column label="Last Visited" width="100px" />
<timer id="timer" delay="3000" repeats="false"

Wrap up

Although ZK is a finalist in the SourceForge.net Community Choice Awards, it is not prepackaged for mainstream distributions. While ZK is not extremely difficult to install, it is always nice to be able to automatically track updates to Web software through your Linux distribution's package manager.

Although interaction between the Web browser and the Web server is done using asynchronous calls, things like sorting a data grid displaying a custom Data model which require interaction with the server to complete may make the network latency noticeable to users when they click to sort a grid. Whether this becomes an issue depends upon the latency of the network link between your server and the client.

If you are using Java and want to provide a Web interface, using ZK can free you from having to worry about browser-dependent JavaScript code or creating sophisticated widgets to execute in a Web browser. ZK's event-based programming model is also a breath of fresh air compared to having to constantly think about either page loads or issuing and responding to AJAX calls from your own custom JavaScript code.


  • Programming
  • Internet & WWW