JAX London 2014: A retrospective
Ajax without JavaScript

Tutorial – Introducing ZK

TimothyClare
zk

Timothy Clare introduces us to ZK – an open source enterprise level Java framework for web and mobile applications

 

ZK is a highly productive open source Java framework for building amazing enterprise web and mobile applications. This article introduces the reader to using ZK for development of dynamic and robust Java web applications. The author explores mainstay ZK features, which are employed for ZK development, and touched upon more complex patterns. 

ZK: History & Architecture

ZK has been renowned for its “Ajax without JavaScript” approach since 2005, enabling developers to build rich internet applications transparently, without any knowledge of Ajax and JavaScript. The client engine and update engine in ZK play the roles of pitcher and catcher, rendering Ajax communication transparent to developers. Events triggered by users are encapsulated and marshaled to event listeners running at the server.

In 2010, ZK introduced Server+client Fusion architecture which combines the server-centric approach with optional client-side control. The server-centric solution to Ajax brings a productivity boost, robustness, and security to Web application development; while client side solutions endow Web applications with greater controllability, and the ability to leverage client side resources. Throughout the years, ZK has provided developers which a highly productive way of building Java based web applications. The best way to show ZK’s power is to introduce a non-trivial example of working with ZK. The next section introduces an example application in digestible chunks.

Implementing a ZK Application

This example application follows the MVC architectural pattern, separating business logic from the user interface, enabling the separation of user interfaces (contained in zul files) from java business logic. This separation of concerns leads to cleaner and more maintainable code. The attached example contains numerous files. The table below categorizes these files with respect to the MVC pattern:

  • Model: Employee.java, EmployeeService.java
  • View: index.zul
  • Controller: EmployeeController.java

Model

This section introduces the implementation of the model using ZK. The model contains two files, Employee.java and EmployeeService.java. These files are a simplified version of the model and therefore do not include any database functionality. As ZK is predominantly server-side, database functionality is trivial to add. Server-side resources can be accessed directly without any need for connectors. In this example application the model’s implementation is kept simple using a synchronized list. The following code outlines the service.

 

package org.zkoss.jtjexample.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.zkoss.jtjexample.bean.Employee;
import org.zkoss.zul.ListModelList;

public enum EmployeeService {
  INSTANCE;
  
  private List<Employee> _employees = Collections.synchronizedList(new ArrayList<Employee>());
  
  private EmployeeService() {
    _employees.add(new Employee("Roger", "Charles", 21));
    _employees.add(new Employee("Gary", "Peters", 27));
    _employees.add(new Employee("Edward", "Daniels", 35));
  }
  
  public ListModelList getModel() {
    return new ListModelList(_employees, true);
  }
}

 

The service is basic Java except for the method getModel(). This method returns a class of type ListModelList which is used to provide ZK with a representation of data. The ListModelList is an intermediary between raw data in Java and ZK’s representation of the raw data. When constructing the model, a List is passed along with a boolean. This indicates whether ZK’s model will copy the available data into its own internal list or use the provided list. In this case, as the application is simple the model is instructed to use the _employees list directly. If this application was more complex it would be beneficial to add another layer between ZK’s representative model and the application’s model layer. A good example of this can be found in the ZK Essentials documentation.

View

In this section, we discuss the planning and implementation of the GUI using the vast array of Ajax controls provided by ZK.

Designing the interface: The ZK framework uses ZUML markup to describe GUIs; storing markup within *.zul files. ZUML is a powerful concept enabling developers to rapidly implement complex GUIs. In the following sections we will demonstrate using ZUML to implement powerful interfaces.

Using ZK components: Nowadays, most people are familiar with markup languages due to the extensive use of both HTML and XML, hence ZKs ZUML should instantly have a familiar feel. Firstly, a simple div is defined. As shown in Figure 1, attribute id is used to set certain properties of the window. id is ZKs reference to the control. One of the most powerful concepts in ZK is its component model; the model affords developers the ability to place components inside each other. In general terms the majority of components in ZK can be children of any other components. This is called the nesting of components”.

Figure 1: Simple zul file
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" root="./employeediv"?>

<?page title="Employee manager" contentType="text/html;charset=UTF-8"?>

<div id="employeediv">

</div>

Nesting ZK components

In this example it is better to split the functionality between departments and employees and not have the two areas overlap. Therefore an easy method of separation is needed while enabling one to switch back and forth quickly. Luckily ZK has hundreds of components to choose from. In this instance it would seem like a tabbox would work best. Therefore the tabbox is nested inside the window as demonstrated in Figure 2.

Figure 2: Nesting ZK Components

 

<?page title="Employee manager" contentType="text/html;charset=UTF-8"?>

<div id="employeediv"
  apply="org.zkoss.jtjexample.controller.EmployeeController"
  hflex="true">

  <vlayout>
    <listbox>
      <auxhead>
        <auxheader label="Employees" colspan="4" />
      </auxhead>
      <listhead>
        <listheader label="ID" hflex="2" />
        <listheader label="First Name" hflex="3" />
        <listheader label="Last Name" hflex="3" />
        <listheader label="Age" hflex="1" />
      </listhead>

    </listbox>

    <groupbox hflex="true">
      <caption label="Employee" />
      First Name:
      <textbox id="txtFirstName" cols="20" constraint="no empty" />
      Last Name:
      <textbox id="txtLastName" cols="20"  constraint="no empty" />
      Age:
      <intbox id="intAge" cols="3"  constraint="no empty, no zero" />
      <button id="btnAddEmployee" label="Add" width="60px"
        height="24px" />
      <button id="btnUpdateEmployee" label="Update" width="60px"
        height="24px" />
      <button id="btnDeleteEmployee" label="Delete" width="60px"
        height="24px" />
    </groupbox>
  </vlayout>
</div>

 

Main.zul output

A couple of concepts needs to be highlighted here, first an observer will notice the apply and hflex attribute on the div.

An apply attribute is used when one wants to link the ZK UI to a GenericForwardComposer. The GenericForwardComposer will be discussed in detail in the next section. For now, all one needs to know is that it acts as the controller in the MVC paradigm for ZK.

The hflex attribute is used to layout components horizontally. This is complimented by vflex which enables vertical layout control. Both hflex and vflex inform ZK how the components parent should distribute the space among its children. In this case, the author used true as the tabbox is the only child of the window. Setting hflex to true indicates that the component should fill the entire space available. Using hflex and vflex one can create complicated layouts efficiently. Looking into hflex and vflex in more detail is beyond the scope of this article, for more information please refer to the ZK Developers Reference guide. Defining a UI as demonstrated is a simple affair when using ZK. This tutorial uses the XML option, however, it is also possible to define a UI entirely using Java. Havng introduced the basic view it is time to move on to discuss the controller and databinder.

               

Controller & databinding

This section provides a step by step guide of the Controller and its functions. The controller handles all the business logic of the application and responds to events fired from the user interface. Currently our sample application includes add, update and delete events for both the employees and the departments.

Defining a Controller

To create a controller the class org.zkoss.zk.ui.util.GenericForwardComposer should be extended. An example controller is shown in Figure 3. The composer then needs to be associated with a relevant view. Previously, the usage of apply was touched upon in Nesting ZK Components. In the following section the relationship is outlined in more detail.

Figure 3: Example Controller

 

public class EmployeeController extends GenericForwardComposer {

  /**
   * 
   */
  private static final long serialVersionUID = -9089818718875587898L;

}

 

Associating the Controller with the view

To implement the interaction between the View and Controller, data binding is used in this example. To implement data binding, the apply attribute of a component has to be set. Most components support the apply attribute. Figure 4 demonstrates the usage of the apply attribute. The EmployeeController is responsible for handling the user flow. The code of the EmployeeController is demonstrated in Figure 5. Figure 5 introduces two concepts firstly the ability to capture an event and secondly invalidating a component. These are outlined next.

Figure 4: A part of index.zul

 

<div id="employeediv"
  apply="org.zkoss.jtjexample.controller.EmployeeController"
  hflex="true">
Figure 5: EmployeeController.java

 

public class EmployeeController extends GenericForwardComposer {

  /**
   * 
   */
  private static final long serialVersionUID = -9089818718875587898L;

  private static final Log log = Log.lookup(EmployeeController.class);

  private Employee _currentEmployee;
  private ListModelList _model = EmployeeService.INSTANCE.getModel();

  Listbox lstEmployee;
  Textbox txtFirstName, txtLastName;
  Intbox intAge;

  public Employee getCurrentEmployee() {
    return _currentEmployee;
  }

  public void setCurrentEmployee(Employee currentEmployee) {    
    this._currentEmployee = currentEmployee;
  }

  public ListModel getEmployeeModel() {
    return _model;
  }

  // click events
  public void onClick$btnAddEmployee() {

    String firstName = txtFirstName.getText();
    String lastName = txtLastName.getText();
    int iAge = Integer.parseInt(intAge.getText());

    Employee employee = new Employee(firstName, lastName, iAge);

    if (!_model.add(employee)) {
      reportError(Messages.getString("EmployeeController.0"), employee);
    }

  }

  public void onClick$btnUpdateEmployee() {
    if (lstEmployee.getSelectedItem() != null) {

      Employee employee = (Employee) (lstEmployee.getSelectedItem()
          .getValue());
      
      employee.setFirstName(txtFirstName.getText());
      employee.setLastName(txtLastName.getText());
      employee.setAge(Integer.parseInt(intAge.getText()));
    } else {
      UiUtils.showMessage(Messages.getString("EmployeeController.2"));
    }
  }

  public void onClick$btnDeleteEmployee() {

    if (lstEmployee.getSelectedItem() != null) {
      Employee employee = (Employee) (lstEmployee.getSelectedItem()
          .getValue());

      if (!_model.remove(employee)) {
        reportError(Messages.getString("EmployeeController.3"), employee);
      }

    } else {
      UiUtils.showMessage(Messages.getString("EmployeeController.4"));
    }

  }

  private void reportError(String message, Employee employee) {
    StringBuilder sb = new StringBuilder(message).append(Messages.getString("EmployeeController.5")).append(employee);
    final String error = sb.toString();

    UiUtils.showMessage(error);
    log.error(error);
  }
} 

Capturing events

Event capturing in ZK is easy to implement, providing developers with enormous power. Figure 6 is a function signature to capture the onClick event from the button named btnAddEmployee. The onClick event is fired when a user clicks a button. The method signature in Figure 6 can be broken down into 3 parts. Firstly, the return type is void and method is public. The method name consists of the event name, followed by a dollar sign ($) and the name of the component whose event you want to trap. Then lastly, in this case the event type is a ForwardEvent. Using this technique it is possible to trap any event from any ZK component in a composer which is properly wired to the view.

Figure 6: Function signature for event capturing

 

public void onClick$btnAddEmployee(ForwardEvent fe)

 

Using databinding to load data from our service

The view is tied to the controller using the apply attribute as discussed in Associating the Controller with the view. Now ZK’s data binding mechanism needs to be activated for this page. Remember, due to the include mode being deferred each zul is considered a separate entity, thus, they can each have their own data binding instance. To initialize the Annotated data binder, use the line shown in Figure 7.

Figure 7:Initalise the databinder

 

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

 

               

index.zul and EmployeeController.java functionality step by step

To make it easier to explain how data binding works, Figure 8 contains the complete source of index.zul. This article will now step through each relevant part and include, where necessary the relevant parts of the applied controller.

Figure 8: index.zul complete code

 

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

<?page title="Employee manager" contentType="text/html;charset=UTF-8"?>

<div id="employeediv"
  apply="org.zkoss.jtjexample.controller.EmployeeController"
  hflex="true">

  <vlayout>
    <listbox id="lstEmployee" multiple="true" rows="5"
      model="@{employeediv$composer.getEmployeeModel, load-after='btnAddEmployee.onClick, btnDeleteEmployee.onClick'}"
      selectedItem="@{employeediv$composer.currentEmployee}">
      <auxhead>
        <auxheader label="Employees" colspan="4" />
      </auxhead>
      <listhead>
        <listheader label="ID" hflex="2" />
        <listheader label="First Name" hflex="3" />
        <listheader label="Last Name" hflex="3" />
        <listheader label="Age" hflex="1" />
      </listhead>
      <listitem self="@{each='employee'}" value="@{employee}">
        <listcell label="@{employee.id}" />
        <listcell label="@{employee.firstName}" />
        <listcell label="@{employee.lastName}" />
        <listcell label="@{employee.age}" />
      </listitem>
    </listbox>

    <groupbox hflex="true">
      <caption label="Employee" />
      First Name:
      <textbox id="txtFirstName" cols="20" constraint="no empty"
        value="@{employeediv$composer.currentEmployee.firstName save-when='btnUpdateEmployee.onClick'}" />
      Last Name:
      <textbox id="txtLastName" cols="20"  constraint="no empty"
        value="@{employeediv$composer.currentEmployee.lastName save-when='btnUpdateEmployee.onClick'}" />
      Age:
      <intbox id="intAge" cols="3"  constraint="no empty, no zero"
        value="@{employeediv$composer.currentEmployee.age save-when='btnUpdateEmployee.onClick'}" />
      <button id="btnAddEmployee" label="Add" width="60px"
        height="24px" />
      <button id="btnUpdateEmployee" label="Update" width="60px"
        height="24px" />
      <button id="btnDeleteEmployee" label="Delete" width="60px"
        height="24px" />
    </groupbox>
  </vlayout>
</div>

 

Loading the data from the controller

It is time to start populating data. This is done by binding our controller functions for retrieving the models data with our listbox. The complete listbox zul is outlined in Figure 9. The controller source code in model=”@{employeediv$composer.getEmployeeModel}” and selectedItem=”@{employeediv$composer.currentEmployee}” have return type of ListModelList (ZK’s data representation) and a bean of type Employee respectively. The code snippet for this is shown in Figure 10. The controllers method responsible for retrieving all employee data is named getEmployeeModel().This method can be accessed in the view by setting the listboxs model attribute to employeediv$composer.getEmployeeModel as outlined in Figure 11.

Figure 9: The listbox with databinding
<listbox id="lstEmployee" multiple="true" rows="5"
      model="@{employeediv$composer.getEmployeeModel, load-after='btnAddEmployee.onClick, btnDeleteEmployee.onClick'}"
      selectedItem="@{employeediv$composer.currentEmployee}">
      <auxhead>
        <auxheader label="Employees" colspan="4" />
      </auxhead>
      <listhead>
        <listheader label="ID" hflex="2" />
        <listheader label="First Name" hflex="3" />
        <listheader label="Last Name" hflex="3" />
        <listheader label="Age" hflex="1" />
      </listhead>
      <listitem self="@{each='employee'}" value="@{employee}">
        <listcell label="@{employee.id}" />
        <listcell label="@{employee.firstName}" />
        <listcell label="@{employee.lastName}" />
        <listcell label="@{employee.age}" />
      </listitem>
    </listbox>
Figure 10:  EmployeeController source snippet – getAllEmployees and Current Employee

 

private ListModelList _model = EmployeeService.INSTANCE.getModel();

public ListModel getEmployeeModel() {
    return _model;
  }

public Employee getCurrentEmployee() {
    return _currentEmployee;
  }

public void setCurrentEmployee(Employee e) {
    this._currentEmployee = e;
  }

 

Figure 11: Binding for getEmployeeModel

 

model="@{employeediv$composer.getEmployeeModel

 

The data binding expression can be broken down. Readers should note that the expression beginning with employeediv is the name of the root component, which also contains the apply attribute. It is then followed by a dollar sign and composer. ZK evaluates this as look for the component with id employeediv and retrieve its composer. A ‘.’ is then appended and followed by the function name that is to be accessed. This will assign the model to the result of the getEmployeeModel function in the controller.

Secondly, the line shown in Figure 12 uses the same mechanism to retrieve the reference for employeedivs composer. It is then followed by currentEmployee. Readers should also note that Figure 10 outlines a function and a bean named currentEmployee. This demonstrates that data binding the syntax to access beans and functions differ. This is outlined in Table 1. The attribute selectedItem is set to keep track of which bean is selected from the Listbox. When the selection is changed, ZK will automatically update the bean accordingly.

Figure 12: Databinding Selected Item
selectedItem="@{employeediv$composer.currentEmployee}"

Access identifier

Description

fullFunctionName

To access a function in the controller through data binding, it is necessary to use the full function name

beanName

When accessing a bean from the controller, it is only required to use the bean name, there is no need to include “get” or “set”. However, the bean in question must have both a getter and setter.

       Displaying The Data

To display the data within a listbox a template is needed. By creating a template, such as the one outlined in Figure 13, the listbox can effectively represent the data. The data is bounded to and rendered within the listbox. This is achieved by utilizing the self attribute of the listitem to assign variables which would each represent an Employee. The data binder will then loop through each employee and output the template code shown in Figure 13 below. Each listcell will therefore be bounded to the respective bean and its mutators. A similar methodology is applied to the components in the group box which represent the selected item. Each one of them is bounded to specific data of the currentEmployee bean using techniques discussed throughout this chapter. Therefore, as the currentEmployee changes when selecting on a different employee in the listbox, the relevant textboxes are also updated. These techniques apply throughout ZK. The relevant extract is shown in Figure 14. Having loaded and displayed the data, it is time to start manipulating it.

Figure 13: Listbox display template

 

<listitem>
  <listhead>
    <listheader label="ID" hflex="2" />
    <listheader label="First Name" hflex="3" />
    <listheader label="Last Name" hflex="3" />
    <listheader label="Age" hflex="1" />
  </listhead>
  <listitem self="@{each='employee'}" value="@{employee}">
  <listcell label="@{employee.id}" />
  <listcell label="@{employee.firstName}" />
  <listcell label="@{employee.lastName}" />
  <listcell label="@{employee.age}" />
</listitem>
Figure 14: Extract showing currentEmployeeInformation

 

First Name:
    <textbox id="txtFirstName" cols="25"
      value="@{employeediv$composer.currentEmployee.firstName}" />
    Last Name:
    <textbox id="txtLastName" cols="25"
      value="@{employeediv$composer.currentEmployee.lastName}" />
    Age:
    <intbox id="intAge" cols="1"
      value="@{employeediv$composer.currentEmployee.age}" />

CRUD operations on the UI

So far the data has been loaded and displayed, but the whole point of web applications is to manipulate data. Hence add, create, update and delete methods need to be created. This is achieved via 3 buttons displayed in Figure 15. These buttons are tied to functions in the controller which capture the events. The functions are outlined in Figure 16. Figure 16 highlights the business logic behind the crud operations, most of these are self explanatory and are of basic Java calls. One item readers may notice is that each component is referenced directly from the code. To enable this function, a developer only needs to specify the component type and its id in the controller and ZK will do the rest through automatic wiring. For example, Figure 17 shows that declarations are enough to make access to components possible in Figure 16.

The last talking point is how ZK <span lang="en

Author
TimothyClare
Timothy Clare is a Technology Evangelist for the Potix corporation which produces the ZK Framework. He has been working with various web and mobile technologies for over 10 years.
Comments
comments powered by Disqus