Integrate the rich Internet application framework ZK with Informix to build real-world applications - Rapid web application development for Informix

antlertextureΛογισμικό & κατασκευή λογ/κού

14 Ιουλ 2012 (πριν από 5 χρόνια και 2 μήνες)

520 εμφανίσεις

Integrate the rich Internet application framework
ZK with Informix to build real-world applications
Rapid web application development for Informix
Skill Level:Intermediate
Timothy Clare (timothyclare@zkoss.org)
Technology Evangelist
Potix Corp.
Sachin K Mahajan
Consultant
IBM
18 Aug 2011
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.
Section 1.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
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 1 of 28
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
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 2 of 28
• 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.
Section 2.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
Field
Type
Id
varchar(50)
Firstname
varchar(50)
Lastname
varchar(50)
Age
Integer
Departmentid
varchar(50)
Table 2.Departments table
Field
Type
Id
varchar(50)
Name
varchar(50)
Libraries of the model
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 3 of 28
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.
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 4 of 28
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
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 5 of 28
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?
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 6 of 28
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.
Section 3.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
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 7 of 28
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
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 8 of 28
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.
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 9 of 28
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.
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 10 of 28
• 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
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"?>
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 11 of 28
<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
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.
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 12 of 28
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.
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 13 of 28
Section 4.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>
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 14 of 28
<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
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 15 of 28
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
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 16 of 28
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}"
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 17 of 28
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’sroot
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}"/>
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 18 of 28
<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
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 19 of 28
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 bycurrentEmployee.
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 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.
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>
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 20 of 28
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.
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 21 of 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);
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 22 of 28
}
}
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'}"
Section 5.Building the database and running the sample
application
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 23 of 28
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.
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 24 of 28
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.
Section 6.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.
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 25 of 28
Downloads
Description
Name
Size
Download
method
Example code for this tutorial ZK-Informix-Article-src.zip 10KB HTTP
Information about download methods
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 26 of 28
Resources
Learn
• Learn more about ZK in the article Rich Internet applications using ZK
(developerWorks,Jan 2010).
• Learn more about the Model-view-controller (MVC) software architecture.
• Learn more about ZK Open source Ajax.
• Check out some Live demos of applications using ZK.
• Get more details from the ZK Developer's Reference.
• Learn more about ZK Studio from the ZK Studio documentation.
• In the IBM Informix area on developerWorks,get the resources you need to
advance your Informix skills.
• Stay current with developerWorks technical events and webcasts focused on a
variety of IBM products and IT industry topics.
• Attend a free developerWorks Live!briefing to get up-to-speed quickly on IBM
products and tools as well as IT industry trends.
• Follow developerWorks on Twitter.
Get products and technologies
• Download Apache Tomcat for a servlet container as described in this tutorial.
• Download and install ZK to follow the instructions in this tutorial.
• Get the JDBC driver for Informix from ibm.com.
• Download a trial version or one of the free editions of Informix.
Discuss
• Participate in the discussion forum for this content.
• Get involved in the My developerWorks community.Connect with other
developerWorks users while exploring the developer-driven blogs,forums,
groups,and wikis.
About the authors
Timothy Clare
Timothy Clare is a Technology Evangelist for the Potix Corporation
which produces the ZK Framework.He has been working with various
ibm.com/developerWorks developerWorks®
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 27 of 28
web and mobile technologies for over 10 years.
Sachin K Mahajan
Sachin Mahajan graduated with a Masters degree from University of
Utah,Salt Lake City,Utah.He has worked in small and large-sized
companies in the U.S.and India performing various technical and
managerial roles.
developerWorks® ibm.com/developerWorks
Integrate the rich Internet application framework ZK with Informix to build real-world applications Trademarks
©Copyright IBM Corporation 2011.All rights reserved.Page 28 of 28