Minjie Zha, Student, Software Institute specialising Software Engineering at Nanjing University, China.
October 30, 2006
Version
Applicable to ZK 2.1.1 and later.
In this article, I want to show you a small project called Contact List implemented with ZK and Spring. This Online Contact List stores users' contact lists, and provides functions like adding and deleting contact items. I wrote it to help me study the ZK framework. In order to highlight the essential ways of using ZK, I only keep its main part here.
The sample project use NetBeans5.0 as programming environment and Tomcat5.5 as Web Server. MySQL5.0 is the database system to store data. And about how to set up the environment for Tomcat, Spring, MySQL and JDBC, please refer ZK with Spring DAO and JDBC by Andrew Ho.
The user information and contact list data need to be persisted in the database. So we need two database tables: users and items. Simply, we created the two tables using the following DDL codes:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL auto_increment,
`username` char(30) NOT NULL,
`password` char(50) NOT NULL,
PRIMARY KEY (`id`)
) ;
CREATE TABLE `items` (
`id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL,
`name` char(30) NOT NULL,
`phone` char(15) default NULL,
`email` char(30) default NULL,
PRIMARY KEY (`id`)
) ;
Corresponding to the tables, we need two classes to represent rows in them. They are User.java and Item.java defined like this:
public class User {
private int id;
private String username;
private String password;
public User(){}
//getters/setters are omitted
}
public class Item {
private int id;
private int userId;
private String name;
private String phone;
private String email;
public Item(){}
// getters/ setters are omitted
}
Now that we have set up the database, we are going to write some DAOs which handle the boring database operations.
For each table, one DAO is required. We define the following interfaces:
public interface UserDAO {
public User insert(User user); // add user
public List findByUsername(String username);
}
public interface ItemDAO {
public Item insert(Item item); // add new item
public Item update(Item item); // update item
public void delete(Item item); // delete item
public Item findById(int id);
public List- findAll(); // get all items
public List
- findAllByUser(int user_id);
}
Then, we implement two concrete classes, UserDAOImpl and ItemDAOImpl, which do the actual functions provided by DAOs. Here, we use JdbcTemplate as provided by Spring to access the database. The JdbcTemplate requires a datasource to connect to the database. We give a DriverManagerDataSource to it. So, we have to put these lines in Spring configuration file contact-config.xml.
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/contact_list</value>
</property>
<property name="username">
<value>contact</value>
</property>
<property name="password">
<value>contact</value>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg>
<ref bean="dataSource"/>
</constructor-arg>
</bean>
Now, we can use jdbcTemplate in DAOs. Because the codes are too boring, I won't list them here. Please read the source code if you want to know more.
Till now, we have finished all the tasks related to database. Then, we are going to write pages which interact with users. First, let's consider the process that user may use this Contact List. They need to register to the system first, then login, and then they will see their own contact list. So, we need three pages, one for Login window, one for Register window, and the other for Contact List window.
Now, let's write the ZUL files.
<?xml version="1.0" encoding="UTF-8"?>
<?page title="Contact List" ?>
<window id="loginWnd" title="User Login" border="normal"
width="350px" use="hysteria.contact.ui.LoginWindow" >
<grid>
<rows>
<row>Username: <textbox id="username"/></row>
<row>Password: <textbox id="password" type="password"/></row>
<row>
<button label="Register" onClick="loginWnd.onRegister()" />
<button label="Login" onClick="loginWnd.onLogin()" />
</row>
</rows>
</grid>
</window>
<?xml version="1.0" encoding="UTF-8"?>
<window id="registerWnd" title="User Registeration" border="normal"
width="400px" use="hysteria.contact.ui.RegisterWindow">
<zscript>
void reset(){
...
}
void register(){
...
}
</zscript>
<grid>
<rows>
<row>Username: <textbox id="username" />*,a-zA-Z,0-9</row>
<row>Password: <textbox id="password" type="password"/>*</row>
<row>Confirm Password: <textbox id="con_password" type="password"/>*</row>
<row>
<button label="Reset" onClick="reset()"/>
<button label="Register" onClick="register()"/>
<button label="Back to Login" onClick="registerWnd.back()"/>
</row>
</rows>
</grid>
</window>
<?xml version="1.0" encoding="UTF-8"?>
<window id="contactWnd" title="Contact List" border="normal"
use="hysteria.contact.ui.ContactWindow">
<zscript>
void reset(){...}
void add(){...}
void delete(){...}
</zscript>
<tabbox width="900px">
<tabs><tab label="Item List"/><tab label="New Item"/></tabs>
<tabpanels width="400px">
<tabpanel>
Contacts:
<listbox id="items" width="700px" onCreate="contactWnd.showList()">
<listhead>
<listheader label="Name"/>
<listheader label="Phone"/>
<listheader label="Email"/>
</listhead>
</listbox><separator/>
<button label="Delete" onClick="delete()"/>
</tabpanel>
<tabpanel>
<grid>
<rows>
<row>Name: <textbox id="name"/>*</row>
<row>Phone:<textbox id="phone"/></row>
<row>Email:<textbox id="email"/></row>
<row>
<button label="Reset" onClick="reset()"/>
<button label="Add" onClick="add()"/>
</row>
</rows>
</grid>
</tabpanel>
</tabpanels>
</tabbox>
</window>
Note that we use tabpanel component in myContact.zul. And this provides both add item function and delete item function to the user at the same time.
With the use attribution in each ZUL file, we create one JAVA file for each of them. In these JAVA files, we will write codes to handle events fired by users.
Now, we have set up persistent layer and presentation layer. Next, we will write a business layer to connect them. In the Contact List , we have register, login, add items, delete items, and view items functions. So, in the business layer interface, we will have these methods:
public interface ContactBusiness {
public boolean register(User user);
public int login(User user);
public boolean addItem(Item item);
public List- getAllItem(int user_id);
public boolean deleteItem(Item item);
}
The concrete class for this interface will interact with persistent layer to finish the above functions. And the JAVA classes in presentation layer will invoke its methods in order to achieve the users' requests. This class will be treated as a bean in Spring configuration file.
We have implemented presentation layer with ZK and business and persistent layer with Spring. But we still don't know how to integrate the two frameworks. How can we access Spring beans in ZK?
ZK provides an easy way to access Spring beans. We only need to put these lines in zscript element or JAVA files:
ApplicationContext ctx =
WebApplicationContextUtils.getRequiredWebApplicationContext(
(ServletContext)getDesktop().getWebApp().getNativeContext());
ContactBusiness contact = (ContactBusiness)ctx.getBean("contactBusiness");
So, we can access Spring beans in JAVA files for each of the ZUL files, and finish what users want to do.
ContactBusiness contact = (ContactBusiness)SpringUtil.getBean("contactBusiness");
grant all on contact_list.* to 'contact'@'localhost' identified by 'contact';
Add function to the program which will let user modify items.

Minjie Zha is a bachelor's student in Software Institute specialising Software Engineering at Nanjing University, China. He did several projects with J2ME and J2EE. He is interested in new technologies and open source projects such as Tapestry, Spring, Lucene, Ruby, and also ZK.