Integrate the rich Internet application framework ZK with Informix to build real-world applications

Rapid web application development for Informix

This tutorial presents a real-world example that integrates IBM® Informix® and ZK, a rich Internet application (RIA) framework. Informix is a flagship IBM RDBMS product, while ZK is a Java-based web application framework supporting Ajax applications. This event-driven framework enables creation of rich user interfaces with minimal knowledge and use of JavaScript. ZK's unique server-centric approach enables synchronization of components and events across the client and server via the core engine.

Share:

Timothy Clare (timothyclare@zkoss.org), Technology Evangelist, Potix Corp.

Photo of author Timothy ClareTimothy 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.



Sachin K Mahajan (sachin.mahajan@in.ibm.com), Consultant, IBM  

Sachin Mahajan photoSachin graduated with a Masters degree from the University of Utah, Salt Lake City, U.S. He has worked in both small and large companies in the United States and India performing various technical and managerial roles. Sachin currently works in IBM Software Group's Lotus division.



18 August 2011

Also available in Portuguese

Before you start

Introduction

ZK is analogous to Ajax without JavaScript. It is a powerful framework composed of an Ajax-based event-driven engine, a rich set of XHTML and XUL components, and a markup language called ZUML for the purpose of creating feature-rich user interfaces. For a detailed example of the power of ZK and a real life example, see a link to the article Rich Internet applications using ZK in the Resources section.

The aim of this tutorial is to develop a rich sample application using the ZK framework and an Informix database. ZK is an open-source Ajax framework which facilitates the creation of Ajax-driven websites using Java. Developers can make use of ZK's event-driven framework and markup languages to create powerful applications quickly and effectively.

Prerequisites

This tutorial will guide you through every step of the process and is aimed at new users of ZK. Although no JavaScript experience is required, users should have some experience with Java before starting.

Before you begin, ensure that done the following:

  • You have installed a servlet container, for example Apache Tomcat in the Resources section.
  • You have installed ZK. The link to download ZK is located in the Resources section of this tutorial.
  • You have installed the JDBC driver for Informix. Check the Resources section for the link.
  • You have installed Informix 11.50 or later. The Resources section includes a link for downloading a trial or free version of Informix. This tutorial was developed using Informix 11.50.TC4 Developer Edition.

ZK application design

This application follows the model-view-controller (MVC) architectural pattern, separating business logic from the user interface, enabling separation of user interfaces (contained in zul files) from Java business logic. This separation of concerns leads to cleaner and more maintainable code.

Refer to the Download section of this tutorial for a link to the ZK-Informix-Article-src.zip file that contains numerous files. The following list categorizes these files with respect to the MVC pattern:

  • Model: Department.java, Employee.java, EmployeesDAO.java, DepartmentDAO.java, BaseDAO.java, DatabaseInformation.java, QuerySet.java, EmployeeQuerySet.java, DepartmentQuerySet.java, SqlPropertyLoader.java
  • View: main.zul, employees.zul, departments.zul
  • Controller: DatabaseSetupController.java, DepartmentController.java, EmployeeController.java, MainController.java

Note that the file DatabaseInformation.java contains all the settings that the application will use when accessing the database. If you choose you can manually change the settings of this file, and then access main.zul.


Implementing the model

This section introduces the implementation of the model using ZK. As you saw in the list in the previous section, the model contains nine files. However, the model is not complex and the increased volume of files is just the author's abstraction.

Designing the database schema

For the example used in this tutorial, two tables are required, one named employees and the other named departments. The attributes for the tables are listed as follows.

Table 1. Employees table
FieldType
Idvarchar(50)
Firstnamevarchar(50)
Lastnamevarchar(50)
AgeInteger
Departmentidvarchar(50)
Table 2. Departments table
FieldType
Idvarchar(50)
Namevarchar(50)

Libraries of the model

For the model layer, object/relational mapping (ORM) software such as Hibernate and TopLink were not used in order to keep the application as simple as possible. The example application utilizes pure JDBC with a sugar coating provided by DbUtils from apache.org.

As the Apache website states, DbUtils is, "A small set of classes designed to make working with JDBC easier. JDBC resource cleanup code is mundane, error prone work so these classes abstract out all of the cleanup tasks from your code leaving you with what you really wanted to do with JDBC in the first place: query and update data."

Having established the libraries needed, you will now learn about initializing the drivers, creating our domain model, and building a layer to access the database.

Initializing the Informix drivers

When the application starts, it is best to initialize the Informix drivers. ZK provides many points at which developers can inject code using interfaces. To achieve this, you need to implement the interface WebAppInit and initialize the driver in the overridden init method. Listing 1 shows the class which does the initializing.

Listing 1. Initializing the drivers
public class WebAppInitialization implements WebAppInit {
	
	@Override
	public void init(WebApp wapp) throws Exception {
		//let's initialize the class
		Class.forName("com.informix.jdbc.IfxDriver");
	}

}

After implementing the initializing class, you need to tell ZK about the implementation. You do this by editing the zk.xml file located in the WEB-INF directory. XML is used to describe the location of the custom initialization listener.

Listing 2. Initializing XML
	<listener>
	    	<listener-class>org.zkforge.utils.WebAppInitialization</listener-class>
	</listener>

Listing 2 shows the code needed to register the initialization class with ZK.

Having taken care of initializing the drivers, it is now time to start putting the database into practice, starting with the domain object.

Creating the domain object

In order to manipulate the database, you implement a domain object. Listings 3 and 4 are extracts from the two beans. The implementations of the data manipulation functions have been removed. Please consult the Download section of this tutorial for further details on the full source code.

Listing 3. Department bean extract
public class Department {
	private String _id, _name = "";
	
	public Department() {
		//Default construct for QueryRunner
	}
	
	public Department(String id,
					  String name) {
		this._id = id;
		this._name = name;
	}
	//mutators follow
}
Listing 4. Employee bean extract
public class Employee {
	private int _age = 0;
	private String _id, _firstName, _lastName = "";
	private Department _department = null;
	
	public Employee() {
		//default constructor for Employee
	}
	
	public Employee(String id, String firstName, String lastName, int age, 
    Department department) {
		this._id = id;
		this._firstName = firstName;
		this._lastName = lastName;
		this._age = age;
		this._department = department;
		}
	
	//mutators follow
	}

The domain objects are complete, so now you need classes to retrieve them from the database, enter the data access objects.

Creating the data access object

To interact with the database, you implement a DAO object. To give better abstraction, an abstract base class named AbstractDAO is created. This class is generic and provides the following functions:

  • getAll: Retrieves all entries from the relevant table and returns a list of beans of type T
  • get(String id): Retrieves the entry from the database where the ID of the entry matches the argument. The method returns a populated bean of type T.
  • delete(T entry): Deletes the database entry that matches type T
  • Insert(T entry: Inserts into the database the entry of type T
  • Update(T entry): Updates the relevant data in the database using type T

DepartmentDAO and EmployeeDAO then extend from AbstractDAO to inherit its base functionality. These two classes inherit the functionality of AbstractDAO.

EmployeeDAO provides additional customization to return an Employee bean that contains a populated Department bean.

Listing 5. EmployeeDAO customization
private EmployeeDAO() {
	super(Employee.class, _querySet, new 
    BeanListHandler<Employee>(Employee.class) {
	public List<Employee> handle(ResultSet rs) throws 
SQLException {
		final List<Employee> employees = new ArrayList<Employee>();		
	  		while(rs.next()) {
				employees.add(getEmployeeFromRow(rs));
						}
					return employees;
				}
			}, new BeanHandler<Employee>(Employee.class) {
			public Employee handle(ResultSet rs) throws SQLException {	
					if(!rs.next()) {
					return null;
				}					
				return getEmployeeFromRow(rs);
				}
			});
}

Listing 5 demonstrates this customization where customers BeanListHandler and BeanHandler are created for the employee. An implementation of handle is then provided which calls a method getEmployeeFromRow converting a ResultSet into an Employee. For more information please refer to the source code.

How do we provide queries to the AbstractDAO?

Having studied the DepartmentDAO and EmployeeDAO, you can see there are no queries present in the class. The queries have been abstracted and are passed to the AbstractDAO through its constructor using the interface QuerySet.

The interface, shown in Listing 6, defines basic methods which return queries for type T. In this case, DepartmentQuerySet and EmployeeQuerySet provide implementations of these methods for their respective beans.

Listing 6. QuerySet interface
public interface QuerySet<T> {
	String getAllQuery();
	String getQuery(String id);
	String getInsertQuery(T object);
	String getUpdateQuery(T object);
	String getDeleteQuery(T object);
	String getTableName();
}

As an interesting aside, the DepartmentQuerySet and EmployeeQuerySet classes use resource bundles to load queries from a property file.

You should now have a good knowledge of the implementation of the model. We can therefore move on to the view and discuss how it is implemented.


Implementing the view

In this section, you will learn about 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, and stores markup within *.zul files. ZUML is a powerful concept that enables developers to rapidly implement complex GUIs. In the following sections, you will see how to use ZUML to implement powerful interfaces.

Using ZK components

Most people are familiar with markup languages due to the extensive use of both HTML and XML, so ZK’s ZUML should instantly have a familiar feel. Firstly, a simple window is defined.

Listing 7. Simple zul file
<window id="win"  title="Welcome to the employee demo!" 
border="normal" apply="org.zkforge.controllers.MainController">
</window>

As shown in Listing 7, attributes id, title and border are used to set certain properties of the window. The id attribute is ZK’s reference to the control, title sets the text, and border sets the window’s border type.

One of the most powerful concepts in ZK is its component model. The model affords developers the ability to place components inside each other. Generally, the majority of components in ZK can be children of any other components. This is called the nesting of components.

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 Listing 8.

Listing 8. Nested components
<?page title="Welcome to the employee demo!" contentType="text/html;charset=UTF-8"?>
<window id="win"  title="Welcome to the employee demo!" border="normal" 
apply="org.zkforge.controllers.MainController">
		<tabbox hflex="true" id="tbTabs">
	        <tabs>
	            <tab label="Employees" />
	            <tab label="Departments" />
	        </tabs>
	        <tabpanels>
	        	<tabpanel>        		
	        	</tabpanel>
	        	<tabpanel>
	        	</tabpanel>
	        </tabpanels>
	    </tabbox>
	</window>

The output of Listing 8 is shown in Figure 1.

Figure 1. Main.zul output
screen shows welcom message and tabs for the 2 tables

A couple of concepts need to be highlighted here. First, an observer will notice the apply attribute for the window and an hflex attribute on the tabbox. An apply attribute is used when you want to link the ZK UI to a GenericForwardComposer. The GenericForwardComposer, which acts as the controller in the MVC paradigm for ZK, will be discussed in detail in the next section.

The hflex attribute is used to lay out components horizontally. This is complemented by vflex which enables vertical layout control. Both hflex and vflex inform ZK how the component's parent should distribute the space among its children. In this case the author used true as the tabbox as the only child of the window. Setting hflex to true indicates that the component should fill the entire space available. Using hflex and vflex you can create complicated layouts efficiently. Looking into hflex and vflex in more detail is beyond the scope of this tutorial. For more information please refer to the ZK Developer's Reference guide.

Having implemented the skeleton view for main.zul, it is now necessary to move on to designing the department and employee view.

Designing the department and employee view

The authors had a decision to make when deciding how to implement the views. First of all the two views could be placed directly into main.zul, or they could be split up into separate files and included using the include component of ZK.

It was decided to separate the department and employee logic into separate files and include those files using ZK's include component. The reasons for this decision are as follows:

  1. Main.zul will be cleaner. Not having to place all the XML markup into the main.zul is much nicer for you when trying to understand the code, and makes each section more maintainable.
  2. It separates UI concerns from data binding. Separation into two zul files provides excellent separation of UI concerns. It also enables dynamic loading of each zul as covered in the following controller section.

The second reason will be discussed in detail later in this section of the tutorial. At the moment the tutorial's focus is centered on the individual zul files - departments.zul and employee.zul.

Departments.zul

The Departments.zul is simple. It contains a listbox to show a list of departments. Underneath that is a groupbox with one textbox that represents the department name, as well as three buttons for triggering create, read, update, and delete (CRUD) operations.

Listing 9. Departments.zul
<?page title="new page title" contentType="text/html;charset=UTF-8"?>
<div id="departmentdiv" hflex="true">
	<listbox id="lstDepartment" multiple="false" rows="5">
	    <auxhead>
	 	<auxheader label="Departments" colspan="4" />
	     </auxhead>
		<listhead>
			<listheader label="ID" width="150px" />
			<listheader label="Name" width="300px" />
		</listhead>
		<listitem>
			<listcell label="" />
			<listcell label="" />
		</listitem>
	   </listbox>
     	   <groupbox>
		<caption label="Department" />
		Name:
		<textbox id="txtDepartmentName" cols="25"
			value="" />
		<button id="btnAddDepartment" label="Add" width="36px"
			height="24px" />
		<button id="btnUpdateDepartment" label="Update" width="46px"
			height="24px" />
		<button id="btnDeleteDepartment" label="Delete" width="46px"
			height="24px" />
	</groupbox>
</div>

Listing 9 shows an extract of departments.zul without data binding, which will be discussed in the controller section. Listing 9 should not cause any confusion; attributes id, height, width and label are the row of the attribute of the listbox that dictates how many rows are visible. The multiple attribute is a Boolean to specify whether or not selecting multiple items is necessary.

Regarding components, a Listbox is used to display a number of items in a list, and supports the selecting of said items. The group box is used to visually group components together and give them a title (in this case referred to as a caption). The only components which may cause confusion are as follows:

  • Auxhead/Auxheader: The control is used to display a header at the top of the list box. This can span as many columns as you require it to.
  • Listheader: The list header dictates the headings of each listbox column. Notice that there are four columns, hence four list header elements.
  • Listcell: Each listcell contains the information for each column. The number of listcells needs to match the number of list headers.

Figure 2 demonstrates the rendered output of Listing 9.

Figure 2. The rendered departments.zul
screen shows departments heading and column headers for ID and Name and field for inputting updates and deletes

As demonstrated, ZK uses zul to provide developers and designers with a simple XML-based syntax similar to that of HTML.

Describing the Employee.zul file

The Employees.zul is very similar to departments.zul except for two items: the intbox and the listbox shown in Listing 10. If you look carefully at the listbox, you will notice that it has an attribute called mold that is set as select.

A mold is a way of representing a control. Different molds can radically change the appearance of a component. A listbox can have two molds called default and select. The departments.zul demonstrated the default mold which looks and behaves in a similar fashion to a listbox appearing in Windows or Linux. However, a listbox in select mold behaves and looks like a combobox. For more information please refer to the ZK Component Reference.

Additionally, a keen observer will also notice the component intbox. An intbox is similar to a textbox, however, it only supports integers. If a string is entered then the validation of the box would fail.

Listing 10. Employee.zul
	<?page title="new page title" contentType="text/html;charset=UTF-8"?>
	<div id="employeediv" hflex="true">
		<listbox id="lstEmployee" multiple="false" rows="5">
			<auxhead>
				<auxheader label="Employees" colspan="4" />
			</auxhead>
			<listhead>
			  <listheader label="ID" width="150px" />
			  <listheader label="First Name" width="300px" />
			  <listheader label="Last Name" width="300px" />
			  <listheader label="Age" width="150px" />
			</listhead>
			<listitem>
			  <listcell label="" /><listcell label="" /><listcell label="" />
			  <listcell label="" />
			</listitem>
		</listbox>
		<groupbox>
			<caption label="Employee" />
			First Name:<textbox id="txtFirstName" cols="25"
				value="" />
			Last Name:<textbox id="txtLastName" cols="25"
				value="" />
			Age:<intbox id="intAge" cols="1"
				value="" />
			Department:<listbox id="lstDepartment" mold="select" model="">
				<listitem />
			</listbox>
			<button id="btnAddEmployee" label="Add" width="36px"
				height="24px" />
			<button id="btnUpdateEmployee" label="Update" width="46px"
				height="24px" />
			<button id="btnDeleteEmployee" label="Delete" width="46px"
				height="24px" />
		</groupbox>
	</div>

Figure 3 shows the rendered result of employees.zul as included in Listing 10.

Figure 3. The rendered employees.zul
screen shows employee heading, headers for each column in the table, and input fields for updates

Having explored both the separated files, the tutorial now moves back to main.zul to discuss how you can include these separate files in other zul files.

Including zul files in other zul files

ZK provides a special component named include. The include component is used to include output generated by another servlet. The servlet can be anything a JSF, JSP and even another ZUML page. In this application's case, another zul page needs to be included. The basic syntax of an include component is shown in Listing 11.

Listing 11. Include syntax
	<include src="/module/departments.zul" />

As demonstrated, the attribute src is used to specify the file you wish to include.

There are two ways to include another ZUML document: instant and defer. By default it is set to auto, meaning the real mode is decided automatically.

The auto mode (default) decides the mode based on the page that is to be included. If the page ends with a zul or zhtml extension, then instant mode is assumed. Otherwise, the defer mode is assumed.

In instant mode, the components defined in the included page are instantiated instantly and added as children of the include component. In the defer mode, the include component includes the page by going through the Servlet container. Thus, it is okay to include any kind of pages, and is not limited to ZUML documents.

Using defer mode means that an instance of Page will be created in ZK. When a ZK request is asked to render a new page, a new page will be created, and components that are created during this request will all belong to this page. The author uses this to the advantage of the application as it enables both departments.zul and employee.zul to function as completely separate entities from main.zul.

For use in this application, the include mode is set to defer as shown in Listing 12.

Listing 12. Using defer
<include mode="defer" src="/module/departments.zul" />

You benefit from this when you want to reload the included zul files. This brings the tutorial nicely on to talk about controllers, which is the glue that holds the model and view together.


Implementing the controller

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, the 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 Listing 13.

Listing 13. Example controller
public class MainController extends GenericForwardComposer {
	private static final long serialVersionUID = -3135206455666969851L;	
}

The composer then needs to be associated with a relevant view. Previously, the use of apply was touched upon in Nesting ZK components. In the following section the relationship is outlined in more detail.

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.

Listing 14 demonstrates the use of the apply attribute. The MainController is responsible for handling the user flow. In this example it was decided that a tabbox would be used, and the user would change between the department and employee tab. The code of MainController is demonstrated in Listing 15.

Listing 14. Main.zul
<?page title="Welcome to the employee demo!" contentType="text/html;charset=UTF-8"?>
<window id="win"  title="Welcome to the employee demo!" border="normal" 
apply="org.zkforge.controllers.MainController">
	<tabbox hflex="true" id="tbTabs">
        <tabs>
            <tab label="Employees" />
            <tab label="Departments" />
        </tabs>
        <tabpanels>
        	<tabpanel>
        		<include mode="defer" src="/module/employees.zul" />
        	</tabpanel>
        	<tabpanel>
        		<include mode="defer" src="/module/departments.zul" />
        	</tabpanel>
        </tabpanels>
    </tabbox>
</window>

Listing 15 introduces how to capture an event and invalidate a component.

Listing 15. MainController.java
public class MainController extends GenericForwardComposer {
	private static final long serialVersionUID = -3135206455666969851L;	
	Tabbox tbTabs;
	public void onSelect$tbTabs(ForwardEvent e) {
		Object o = e.getOrigin().getTarget();
		if (o instanceof Tab) {
			Tab t = (Tab)o;
			Tabpanel tp = t.getLinkedPanel();
			tp.invalidate();
		}
	}
}

Capturing events

Event capturing in ZK is easy to implement and provides developers with enormous power. Listing 16 shows a function signature to capture the onSelect event from the tabbox tbTabs. The onSelect event is fired when a user changes tabs.

The method signature can be broken down into three 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 who’s 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.

Listing 16. Function signature for event capturing
	public void onSelect$tbTabs(ForwardEvent e)

Why invalidate a component (reloading an include)?

The topic of why to invalidate is relevant in the scope of the application. However the question is based on a more significant question: How do you share the database information among different controls and make sure that they are all updated?

One of the best ways of doing this is to implement a shared list of database items among all concurrent clients accessing the resources. This implementation should be thread safe and is easily achievable in ZK. However, for the purposes of this tutorial it would introduce unnecessary complication that may cause confusion.

Therefore the decision was made to keep the departments and employees separated and to reload each tab's contents when switching. Thus, any information will be reloaded by the database.

Consequently, you need to bear this in mind when reviewing the decisions made in this section.

Listing 17. Switching tabs
	public void onSelect$tbTabs(ForwardEvent e) {
			Object o = e.getOrigin().getTarget();
			
			if (o instanceof Tab) {
				Tab t = (Tab)o;
				Tabpanel tp = t.getLinkedPanel();
				tp.invalidate();
			}
		}

Listing 17 shows the relevant code from the MainController. The first line of the method retrieves the original event and then retrieves the target of the event. In this case it is a Tab of the tabbox.

The Tabpanel of the Tab is then retrieved. A Tabpanel is the area where components are rendered in the tabbox, and each Tab has an associated Tabpanel. In this case the Tabpanel is then invalidated.

You should remember that the contents of the Tabpanel was in fact the include component which includes departments.zul and employee.zul respectively. In addition, as the include mode of each was set to defer, the zul is requested again through the servlet, and the data of each is reloaded.

Using databinding to load data from Informix

To fully explain data binding, only one of the two zul files, either departments.zul or employee.zul, are of relevance. For this tutorial employee.zul will be discussed because it is the more complex of the two.

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

Listing 18. Initialize the databinder
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" root="./departmentdiv"?>

Employee.zul and EmployeeController.java functionality, step by step

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

Listing 19. employees.zul complete code
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" root="./employeediv"?>
<div id="employeediv" apply="org.zkforge.controllers.EmployeeController"
	hflex="true">
	<listbox id="lstEmployee" multiple="false" rows="5"
		model="@{employeediv$composer.getAllEmployees, 
        load-after='btnAddEmployee.onClick, 
        btnDeleteEmployee.onClick, btnUpdateEmployee.onClick'}"
		selectedItem="@{employeediv$composer.currentEmployee}">
		<auxhead>
			<auxheader label="Employees" colspan="4" />
		</auxhead>
		<listhead>
			<listheader label="ID" width="150px" />
			<listheader label="First Name" width="300px" />
			<listheader label="Last Name" width="300px" />
			<listheader label="Age" width="150px" />
		</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>
		<caption label="Employee" />
		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}" />
		Department:
		<listbox id="lstDepartment" mold="select"
			model="@{employeediv$composer.getAllDepartments}"
			selectedItem="@{employeediv$composer.currentEmployee.department}">
			<listitem self="@{each='department'}"
				label="@{department.name}" />
		</listbox>
		<button id="btnAddEmployee" label="Add" width="36px"
			height="24px" />
		<button id="btnUpdateEmployee" label="Update" width="46px"
			height="24px" />
		<button id="btnDeleteEmployee" label="Delete" width="46px"
			height="24px" />
	</groupbox>
</div>

Data binding initialization in employees

Initialization of data binding is the first line that is needed. However, there is a difference between the line demonstrated in Listing 18 and the one outlined in Listing 19. Notice the addition of an extra attribute named root. This root attribute takes a component name and states that the data binder is only initialized for that component and its children. Thus in this situation the annotated data binder’s root component is the div component with id of departmentdiv. Listing 20 demonstrates the relevant line.

Listing 20. Initialize the databinder
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" root="./departmentdiv"?>

Loading the data from the controller

It is time to start populating data. This is done by binding t controller functions for retrieving the model’s data with our listbox. The complete listbox zul is outlined in Listing 21.

Listing 21. The listbox with databinding
<listbox id="lstEmployee" multiple="false" rows="5"
model="@{employeediv$composer.getAllEmployees, load-after='btnAddEmployee.onClick, 
    btnDeleteEmployee.onClick, btnUpdateEmployee.onClick'}"
		selectedItem="@{employeediv$composer.currentEmployee}">
		<auxhead>
			<auxheader label="Employees" colspan="4" />
		</auxhead>
		<listhead>
			<listheader label="ID" width="150px" />
			<listheader label="First Name" width="300px" />
			<listheader label="Last Name" width="300px" />
			<listheader label="Age" width="150px" />
		</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>

The controller source code in model="@{employeediv$composer.getAllEmployees}" and selectedItem="@{employeediv$composer.currentEmployee}" have returned a list of type Employee, and a bean of type Employee respectively. The code snippet for this is shown in Listing 22.

Listing 22. EmployeeController source snippet - getAllEmployees and CurrentEmployee
public List<Employee> getAllEmployees() {
		try {
			return _empDAO.getAll();
		} catch (SQLException e) {
			UiUtils.showMessage(e.getMessage());
			log.error(e);
		}
		
		return null;
	}

public Employee getCurrentEmployee() {
		return _currentEmployee;
	}

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

The controller’s method that is responsible for retrieving all employee data is named getAllEmployees(). This method can be accessed in the view by setting the listbox model attribute to e mployeediv$composer.getAllEmployees, as outlined in Listing 23.

Listing 23. Binding for getAllEmployees
model="@{employeediv$composer.getAllEmployees}”

The data binding expression can be broken down. Note that the expression beginning with employeediv, which is the name of the root component, also contains the apply attribute. It is then followed by a dollar sign and composer.

When ZK evaluates this, it means it is looking for the component with id employeediv and retrieving its composer.

A period (.) is then appended and followed by the function name that is to be accessed. This will assign the model to the result of the getAllEmployees function in the controller.

Secondly, the line shown in Listing 24 uses the same mechanism to retrieve the reference for employeediv’s composer. It is then followed by currentEmployee.

Listing 24. Databinding selected item
	selectedItem="@{employeediv$composer.currentEmployee}"

You should also note that Listing 24 outlines a function and a bean named currentEmployee. This demonstrates the data that binds the syntax to access beans and functions differs. This is outlined in Table 3.

Table 3. Data binder access to the controller
Access identifierDescription
fullFunctionNameTo access a function in the controller through data binding, it is necessary to use the full function name
beanNameWhen 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.

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.

Displaying the data

To display the data within a listbox, you will need a template. By creating a template, such as the one outlined in Listing 25, the listbox can effectively represent the data.

Listing 25. Listbox display template
<listhead>
	<listheader label="ID" width="150px" />
	<listheader label="First Name" width="300px" />
	<listheader label="Last Name" width="300px" />
	<listheader label="Age" width="150px" />
</listhead>
<listitem self="@{each='employee'}" value="@{employee}">
	<listcell label="@{employee.id}" />
	<listcell label="@{employee.firstName}" />
	<listcell label="@{employee.lastName}" />
	<listcell label="@{employee.age}" />
</listitem>

The data is bound 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 Listing 25. Each listcell will therefore be bound 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 bound to specific data of the currentEmployee bean using techniques discussed throughout this section. Therefore, as the currentEmployee changes when selecting a different employee in the listbox, the relevant textboxes are also updated. Also note that there is a listbox in the select mold that follows the same conventions we have discussed in Employee.zul. These techniques apply throughout ZK.

The relevant extract is shown in Listing 26.

Listing 26. Extract showing currentEmployee information
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}" />
Department: <listbox id="lstDepartment" mold="select"
			model="@{employeediv$composer.getAllDepartments}" 
            selectedItem="@{employeediv$composer.currentEmployee.department}">

You have loaded and output the data, so it is time to start manipulating it.

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 by using the three buttons shown in Listing 27.

Listing 27. CRUD buttons
<button id="btnAddEmployee" label="Add" width="36px"
			height="24px" />
		<button id="btnUpdateEmployee" label="Update" width="46px"
			height="24px" />
		<button id="btnDeleteEmployee" label="Delete" width="46px"
			height="24px" />

These buttons are tied to functions in the controller that capture the events. The functions are outlined in Listing 28.

Listing 28. Controller click events
//click events
	public void onClick$btnAddEmployee() {
		if(lstDepartment.getSelectedItem() != null) {
			String firstName = txtFirstName.getText();
			String lastName = txtLastName.getText();
			Department dep = null;
			int iAge = Integer.parseInt(intAge.getText());
			
			Selectable selectable = (Selectable)lstDepartment.getModel();
			Set<?> selectedSet = selectable.getSelection();
			
			if (selectedSet.size() == 1) {
				dep = (Department)selectedSet.toArray()[0];
			}
			
			Employee employee = new Employee(firstName + lastName + 
            UUID.randomUUID(), //id
									  firstName,
									  lastName,
									  iAge,
									  dep);
			
			try {
				_empDAO.insert(employee);
			} catch (SQLException e) {
				UiUtils.showMessage(e.getMessage());
				log.error(e);
			}
		}
		else {
			UiUtils.showMessage("Please select a department!");
		}
			 
	}
	
	public void onClick$btnUpdateEmployee() {
		if((lstDepartment.getSelectedItem() != null)
			&& (lstEmployee.getSelectedItem() != null)) {
			
			Employee employee = 
              (Employee)(lstEmployee.getSelectedItem().getValue());
			
			try {
				_empDAO.update(employee);
			} catch (SQLException e) {
				UiUtils.showMessage(e.getMessage());
				log.error(e);
			}
		}
		else {
			UiUtils.showMessage("Please select an employee and department!");
		} 
	}
	
	public void onClick$btnDeleteEmployee() {
		
		if(lstEmployee.getSelectedItem() != null) {
			Employee employee = 
              (Employee)(lstEmployee.getSelectedItem().getValue());
			
			try {
				_empDAO.delete(employee);
			} catch (SQLException e) {
				UiUtils.showMessage(e.getMessage());
				log.error(e);
			}
		}
		else {
			UiUtils.showMessage("Please select an employee!");
		}
			 
	}

Listing 28 highlights the business logic behind the CRUD operations. Most of these are self explanatory and are basic Java calls. One item you may notice is that each component is referenced directly from the code.

To enable this function, you only needs to specify the component type and its id in the controller and ZK will do the rest through automatic wiring. For example, Listing 29 shows that declarations are enough to make access to components possible from Listing 28.

Listing 29. Component declarations
Listbox lstEmployee;
	Listbox lstDepartment;
	
	//text boxes
	Textbox txtFirstName;
	Textbox txtLastName;
	
	//int boxes
	Intbox intAge;

The last talking point is how ZK would know to update the listbox model after updating, adding, or deleting an item. This is simply a matter of assigning load-after in the model attribute on the listbox to the relevant button events that update the model. When one of these events are fired, the model will be reloaded. Listing 30 demonstrates the code necessary for this. Breaking it down, it is as simple as specifying the component id followed by a period (.), and the event name.

Listing 30. Load-after
model="@{employeediv$composer.getAllEmployees, 
load-after='btnAddEmployee.onClick, btnDeleteEmployee.onClick, 
btnUpdateEmployee.onClick'}"

Building the database and running the sample application

Building an employee database

The premise of the application is to build a basic personnel department application. The application will contain two main objects called employees and departments. Each employee must belong to only one department, but a department can have many employees.

To make it easier to construct the database, the SQL is provided in Listing 31.

Listing 31. SQL describing necessary database and tables
create database employeedb;
	create table departments(
		id varchar(50),
		name varchar(50),
		primary key (id) );
									 
	create table employees(
		id varchar(50),
		firstname varchar(50),
		lastname varchar(50),
		age integer,
		departmentid varchar(50),
		primary key (id),
		foreign key (departmentid) references departments(id));

Running the sample application

The example application is available from the Download section of this tutorial. Download the file and extract it to the folder of your choosing.

Running the sample application without an IDE

To run the example application without using an IDE (Eclipse), please perform the following procedures.

  1. Copy zkinformix.war to $TOMCAT_HOME\webapps.
  2. Start Apache Tomcat
  3. Navigate to http://localhost:8080/zkinformix

Running the sample application with an IDE

To run the example application using an IDE (eclipse), please perform the following procedures.

  1. Copy the Informix driver (ifxjdbc.jar) to $TOMCAT_HOME\common\lib.
  2. Start Eclipse.
  3. Click File > Import.
  4. In the dialog, select Web > WAR file and then click Next.
  5. Use the browse button to locate zkinformix.war.
  6. Click Finish to import the Web Project.
  7. Right click zkinformix in the project explorer and select Run As > Run on Server.
  8. Select Apache > Tomcat v6.0 Server in the server type dialog, and click Finish.
  9. A browser will automatically start showing the zkinformix example.

Conclusion

This tutorial introduced the fundamental concepts and best practices for using ZK with Informix. There are many more in-depth topics that can be covered in another tutorial. By the end of this tutorial, you should have gained a good understanding of how ZK works, and how easy it is to interface with Informix to create a feature-rich web application.


Download

DescriptionNameSize
Example code for this tutorialZK-Informix-Article-src.zip10KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Information management on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management, Open source, Web development, Java technology, DevOps
ArticleID=752700
ArticleTitle=Integrate the rich Internet application framework ZK with Informix to build real-world applications
publish-date=08182011