Getting Started with ZK - Part 2

The Persistent Layer

In the following paragraphs, the database schema, domain object, and DAO object will be introduced.

DataBase Schema

A database table to hold our application data would need the following attributes: event id, event name, event priority ,and event date. The database schema is listed below.
FieldType
idvarchar(50)
namevarchar(50)
priorityint
datedate

Domain Object

For the above table, we create a corresponding domain object, as follows:

public class Event {
 private String id;
 private String name;
 private int priority;
 private Date date;
 
 public Event(){}
 public Event(String id,String name,int priority,Date date){
  this.id = id;
  this.name = name;
  this.priority = priority;
  this.date = date;
 }
 //getter and setter methods are ommited, please refer to the source code.
}

DAO Object

In order to easily access the data in our database we need a DAO object with the following methods: findAll(),delete(),insert(),and update().

public class EventDAO {
 private String url = "jdbc:hsqldb:file:/hsqldb/event";
 private String user = "sa";
 private String pwd = "";
 
 public EventDAO() {
  try {
   Class.forName("org.hsqldb.jdbcDriver");
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
 }
 //The implementation is ommited, please refer to the source code.
 public List findAll(){} 
 public boolean delete(Event evt){} 
 public boolean insert(Event evt){} 
 public boolean update(Event evt){}
 }



Interaction between UI, and the Database

According to our requirements, we want to be able to display events, add, edit, and delete an event. In the following paragraphs, we are going to implement the interaction between our web application page and the application's database.

Using Java Code to Interact with ZK Components

One of the most fancy characteristics of ZK is that you could use Java code to interact with ZK Components defined in a page. ZK provides you three options: embed the Java code directly in the page; put the Java code in a separate file; or interact with the page using pure compiled Java classes. However, we will focus on the first option in this tutorial for better explanation.

Embedding Java Code into the Page

First, we have to load event data from our database, and we could embed Java code into this page by declaring a pair of enclosing <zscript> tags.

The zscript element is a special element for defining scripting codes that will be evaluated each time a ZUL page is rendered. It is typically used for initialization, and for declaring global variables and methods. We'll declare an instance of eventDAO for database access, and we'll store the query result into a List.

Global variables defined within a zscript element could be accessed by using El-expression. As in JSP, you could use El-expressions in any part of a ZUML page, and the syntax for EL expressions is: ${expr}.

The initialization of database access is as follows:


<window title="To do list" width="640px" border="normal">
 <zscript>
    import events.Event;
    import events.EventDAO; 
    import java.util.ArrayList; 
    
    //fetch all events from database 
    EventDAO evtdao = new EventDAO(); 
    List allEvents = evtdao.findAll();  
  </zscript>      
      
 <listbox id="box" multiple="true"  rows="4">
  <listhead>
   <listheader label="Item" />
   <listheader label="Priority" width="50px" />
   <listheader label="Opened" width="90px" />
  </listhead>
  <listitem>
   <listcell/>
   <listcell/>
   <listcell/>
  </listitem>
 </listbox>
    <groupbox>
       <caption label="New" />
       Item: <textbox id="name" cols="50" />
       Priority: <intbox id="priority" cols="1" />
       Date: <datebox id="date" cols="8">
       <button label="Add" width="36px" height="24px"/>
       <button label="Update" width="46px" height="24px"/>
       <button label="Delete" width="46px" height="24px"/>
    </groupbox>
</window>

Using forEach loop

The next step is to render data stored in an allEvents variable into the listbox component using a forEach loop within the listitem component. The forEach attribute is used to control the number of components that should be created.

If you specify a collection of objects to it, ZK Loader will create a corresponding number of components according to the specified collection. And, the each variable represents an object instance stored in the collection. We could use El-expressions to invoke getter methods of the object to retrieve its attributes as follows:


<window title="To do list" width="640px" border="normal">
 <zscript>
  import events.Event;
  import events.EventDAO; 
  import java.util.ArrayList; 

  //fetch all events from database 
  EventDAO evtdao = new EventDAO(); 
  List allEvents = evtdao.findAll();
  </zscript>
<listbox id="box" multiple="true"  rows="4">
  <listhead>
   <listheader label="Item" />
   <listheader label="Priority" width="50px" />
   <listheader label="Opened" width="90px" />
  </listhead>
  <listitem forEach="${allEvents}" value="${each}">
   <listcell label="${each.name}" />
   <listcell label="${each.priority}" />
   <listcell label="${each.date}" />
  </listitem>
 </listbox>
    <groupbox>
       <caption label="New" />
       Item: <textbox id="name" cols="50" />
       Priority: <intbox id="priority" cols="1" />
       Date: <datebox id="date" cols="8">
       <button label="Add" width="36px" height="24px"/>
       <button label="Update" width="46px" height="24px"/>
       <button label="Delete" width="46px" height="24px"/>
    </groupbox>
</window>

Save User's Input Data into Database

First, let's try to declare an add() method within the enclosing tags of <zscript>.

<zscript>
 ....
 void add(){}
</zscript>
In the add() method, we have to complete the following three tasks,
  1. Retrieve User's Input Data
  2. Save Data into Database
  3. Refresh the View in Ajax

Retrieve User's Input Data

ZK allows you to access UI components in Java code. You could access a component by its identifier specified in its id attribute. In this example, user's input data are stored in three input components, textbox(id ="name"), intbox(id ="priority"), and datebox(id="date"). Thus, we could get user's input data by accessing the value attribute of these components, as follows:


 name.value;    //event name
 priority.value;   //event priority
 date.value;     //event date

Save Data into Database

Once we've retrieved user's input data we can save it into our database simply as follows:


 Event newEvt = new Event(UUID.randomUUID().toString(),name.value,priority.value.intValue(),date.value);
 evtdao.insert(newEvt);
 
 //synchronized data object with database 
 allEvents = evtdao.findAll(); 

Refresh the View in Ajax

Incredibly, ZK allows you to refresh the view in Ajax simply by using Java code. In this case, we insert a new listitem into the listbox in Java code as follows, and the job of refreshing the page is handled by ZK automatically.


//insert a new Event into the listbox 
Listitem li = new Listitem(); 
li.setValue(newEvt); 
li.appendChild(new Listcell(name.value)); 
li.appendChild(new Listcell(priority.value)); 
li.appendChild(new Listcell(new SimpleDateFormat("yyyy-MM-dd").format(date.value)));
box.appendChild(li);
  • appendChild(), to insert a child component into itself

The complete code is listed below,


<window title="To do list" width="640px" border="normal">
 <zscript>
  import events.Event;        
  import events.EventDAO;       
  import java.util.ArrayList;   
  import java.text.SimpleDateFormat; 
  import java.util.UUID;

  //fetch all events from database 
  EventDAO evtdao = new EventDAO(); 
  List allEvents = evtdao.findAll();
  
  void add(){ 
      //insert into database 
      Event newEvt = new Event(UUID.randomUUID().toString(),name.value,priority.value.intValue(),date.value);
      evtdao.insert(newEvt);
      
      //synchronized data object with database 
      allEvents = evtdao.findAll();
      
      //insert a new Event into the listbox 
      Listitem li = new Listitem(); 
      li.setValue(newEvt); 
      li.appendChild(new Listcell(name.value)); 
      li.appendChild(new Listcell(priority.value)); 
      li.appendChild(new Listcell(new SimpleDateFormat("yyyy-MM-dd").format(date.value)));
      box.appendChild(li);
    }  
  </zscript>

<listbox id="box" multiple="true"  rows="4">
  <listhead>
   <listheader label="Item" />
   <listheader label="Priority" width="50px" />
   <listheader label="Opened" width="90px" />
  </listhead>
  <listitem forEach="${allEvents}" value="${each}">
   <listcell label="${each.name}" />
   <listcell label="${each.priority}" />
   <listcell label="${each.date}" />
  </listitem>
 </listbox>
    <groupbox>
       <caption label="New" />
       Item: <textbox id="name" cols="50" />
       Priority: <intbox id="priority" cols="1" />
       Date: <datebox id="date" cols="8">
       <button label="Add" width="36px" height="24px"/>
       <button label="Update" width="46px" height="24px"/>
       <button label="Delete" width="46px" height="24px"/>
    </groupbox>
</window>

Register Event Listener in ZK Components

Almost 90% of the reaction from a page is triggered by user’s activities. The add() method is no exception, and it should be invoked only when the user presses the “add” button. The way to determine whether or not this button is clicked by the user is to declare an onClick event listener within the declaration of the button component, and specify the add() method in this onClick event listener.

ZK will invoke the add() method if this button is clicked by a user. Quite intuitive, right? Again! ZK provides the simplest way for you.


<button label="Add" width="36px" height="24px" onClick="add()" />

Other Control Codes

The rest of the control codes are listed below,

  • delete(), delete an event from database, updating the data model, and listbox.
  • update(), update an event from database, updating the data model, and listbox.
  • move(), move data from listbox to input components in the group box
  • cleargp(), clear data of input components in the group box

 <zscript>
  import events.Event;        
  import events.EventDAO;       
  import java.util.ArrayList;   
  import java.text.SimpleDateFormat; 
  import java.util.UUID;        

  //fetch all events from database 
  EventDAO evtdao = new EventDAO(); 
  List allEvents = evtdao.findAll();

  void add(){ 
  //insert into database 
  Event newEvt = new Event(UUID.randomUUID().toString(),
    name.value,priority.value.intValue(),date.value);
  evtdao.insert(newEvt);

  //synchronized data with database 
  allEvents = evtdao.findAll();

  //insert a listEvent into the listbox 
  Listitem li = new Listitem(); 
  li.setValue(newEvt); 
  li.appendChild(new Listcell(name.value)); 
  li.appendChild(new Listcell(priority.value.toString())); 
  li.appendChild(new Listcell(new SimpleDateFormat("yyyy-MM-dd").format(date.value)));
  box.appendChild(li);
  }
  void update(){
      //update database
      Event editEvt = (Event)box.selectedItem.value;
      editEvt.setName(name.value);
      editEvt.setPriority(priority.value);
      editEvt.setDate(date.value);
        evtdao.update(editEvt);
      
      //update listbox
      List children = box.selectedItem.children;
      ((Listcell)children.get(0)).label = name.value;
      ((Listcell)children.get(1)).label = priority.value.toString();
      ((Listcell)children.get(2)).label = new SimpleDateFormat("yyyy-MM-dd").format(date.value);
  } 
  void delete(){
      evtdao.delete((Event)box.selectedItem.value);
      box.removeItemAt(box.getSelectedIndex());
      cleargb();
  }
  void move(){
       name.value = ((Event)box.selectedItem.value).getName();
       priority.value = ((Event)box.selectedItem.value).getPriority();
       date.value = ((Event)box.selectedItem.value).getDate();
  }  
  void cleargb(){
      name.value = null;
      priority.value = null;
      date.value = null;
  }
 </zscript>

Register Corresponding Event Listeners

The last step is to register corresponding event listeners in ZK components to invoke those methods.
  • Register onClick event listener in delete button
  • Register onClick event listener in edit button
  • Register onSelect event listener in listbox

 <window title="To do list" width="640px" border="normal">
 <zscript>
   //the implementation part is ommited, please refer to the above listing.
   void add(){}
   void delete(){}
   void update(){}
   void move(){}
   void cleargb(){}
 </zscript>
 
 <listbox id="box" multiple="true" rows="4"
  onSelect="move()">
  <listhead>
   <listheader label="Item" />
   <listheader label="Priority" width="50px" />
   <listheader label="Opened" width="90px" />
  </listhead>
  <listitem forEach="${allEvents}" value="${each}">
   <listcell label="${each.name}" />
   <listcell label="${each.priority}" />
   <listcell label="${each.date}" />
  </listitem>
 </listbox>
 <groupbox>
  <caption label="Event" />
  Item: <textbox id="name" cols="25" />
  Priority: <intbox id="priority" cols="1" />
  Date: <datebox id="date" cols="8" />
  <button label="Add" width="36px" height="24px" onClick="add()" />
  <button label="Update" width="46px" height="24px" onClick="update()" />
  <button label="Delete" width="46px" height="24px" onClick="delete()" />
 </groupbox>
 <window>


Summary

This tutorial has covered the basics of writing a simple web application with ZK.

Further readings are listed below.

.