An AvailableCourse is an aggregate of Course, Room, and Faculty. It represents a specific course offering for the current semester. A StudentCourse links a Student instance with a particular AvailableCourse. A collection of StudentCourse objects will comprise a student's schedule. I used the NetBeans IDE to develop this sample application. In addition to the domain classes mentioned above, I created a simple Data Access Object in Dao.java that event handlers can use to access sample data. You can download this sample application, including the source code and .war file, here. All .jar files necessary for building ZK applications are included in the ZK distribution. After adding these libraries to your project, you will need to modify the web.xml configuration file to add Servlet mappings that allow ZK to process requests. The ZK download includes a demo application and the easiest way to get started on a new application is to copy its web.xml file and customize as necessary.
Start Page
As mentioned earlier, ZK provides two different component sets, XUL or XHTML. You can actually use both in the same page using XML namespaces. This application will utilize XUL components. ZUML (ZK User Interface Markup Language) is used to specify page components. With ZUML, you can arrange the layout of components on a page, modify attributes for these components, and wire component events to event handlers. It is also possible to handle events directly in the page using the <zscript> element. Zscript lets developers embed Java code in a page, similar to Java scriptlets in JavaServer Pages. Of course, the more robust option is to handle events inside Java classes but we will take a look at both options.
Index.zul contains all the components used in the sample application. You have the option to break up the interface into smaller, reusable files and include them in the main page as you might do with the include directive in JavaServer Pages. The <window> component is a top level component that will normally encapsulate several components on a given page. Like all components, you can modify a window's attributes to modify its appearance and name event handlers. A convenient way to handle component events is to extend the component class. This 'use' attribute in ZUML enables you to specify a custom subclass to represent the component. As an example, the main window in index.zul uses the Java class MainWindow which can be found in the 'web' package:
<window id="winMain" use="web.MainWindow" border="normal"
width="800px" height="500px">
...
<window>
MainWindow can access child components as well as handle window events. For example, by overriding the onCreate Window event, we have the opportunity to customize the title according to the student accessing the application:
public void onCreate() {
//Personalize the window for the current user...
Student currentStudent = this.getDao().getStudent(this.getDao().getCurrentStudentId());
this.setTitle("Welcome " + currentStudent.getFname() + " " +
currentStudent.getLname() + ", This is the Student Enrollment Application.");
}
As it turns out, the MainWindow class is a convenient place to handle other component events as well. Really any Java class can be used to respond to user actions. The screenshot below shows the page tab where most user interaction takes place. This tab panel consists of a tree component that displays course offerings, a list representing the student's current schedule, and a label that displays the total credit hours for a schedule. In the spirit of a rich client application, students add courses to their schedules by selecting a course from a tree node and dragging it onto the schedule list. This is just one of many examples in which ZK can provide functionality that a typical web application cannot. All of it accomplished too, I might add, with very little code.
Create schedule through drag and drop
Some components defined in index.zul markup file are static in nature. For example, the <html> component is a special component that allows you to add HTML to a page:
<html>
<attribute name="content"><![CDATA[
<br/>
<h3>Adding a course to your schedule</h3>
<p>To add a course to your schedule, locate an available course on the left.
<br>
Then, drag it onto your schedule.
</p>
<br/>
]]></attribute>
</html>
Other components, such as the tree component shown below, will generate its content dynamically. It uses some helpful attributes that ZK provides to iterate through a Java Collection as well as EL expressions. When the component is first loaded, the tree will loop through a collection of Course objects and display one node for each course name that the university offers. Then, when the user expands a node, an event handler,showAvailableCourses, in class MainWindow executes and generates a node representing all available courses that a user may add to his or her schedule.
<tree height="300px" width="150px" style="background-color: white">
<treechildren>
<treeitem open="false" forEach="${winMain.dao.courseList}"
onOpen="winMain.showAvailableCourses(self)" id="${each.id}">
<treerow>
<treecell label="${each.name}"/>
</treerow>
<treechildren>
<!--Content will be dynamically added in user event handler!-->
</treechildren>
</treeitem>
</treechildren>
</tree>
Explore the MainWindow code and the index.zul file. Examine how the .zul page wires component events to event handler methods in the Java class. I think you will find this an intuitive programming model, one that most web developers should find refreshing.
If you prefer in certain situations to handle event logic directly in your ZUML page, you can easily do so with the <zscript> element. There are virtually no limitations to what you can do in the zscript portion of a page. As an example, look at the following toolbar component for the main window:
<toolbarbutton label="Contacts" onClick="showContacts()"/>
The onClick event method in this case will be written within a <zscript> element. The particular event handler displays a popup window with contact information for questions about student enrollment. Before it displays the window, however, it programmatically creates components and adds them to the window:
void showContacts() {
Label primaryContact = new Label();
primaryContact .value="Primary: John Smith - (502) 545-1900";
Label secondaryContact = new Label();
secondaryContact .value="Secondary: Julie Stewart - (502) 545-1935";
winAbout.appendChild(primaryContact );
winAbout.appendChild(new Separator());
winAbout.appendChild(secondaryContact);
//Display window on top of main window.
winAbout.doOverlapped();
}
The window that displays contact information is also defined in index.zul:
<window id="winAbout" visible="false" title="Contacts" closable="true"
border="normal" width="300px" height="100px">
</window>
As previously mentioned, you can add several components and even several windows filled with child components in a single ZUML file, or you can break them up into separate files. Test the sample application and witness some of the features it provides, message boxes for example. Adding such functionality was trivial but can greatly improve the user experience.
Contacts popup window
Error! Course already appears in schedule
Confirmation before exit
I have only touched upon ZK's numerous features. The ZK site provides excellent documentation. I think you will find it worth your while to experiment with ZK and learn how to build Ajax web applications with minimal effort.
About the Author
Michael Klaene is a Senior Consultant with Sogeti LLC. He has spent over 9 years in Information Technology and is an experienced Systems Analyst, delivering solutions that involve numerous technologies, such as J2EE and .NET.