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
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