zk 5 essentials

78
PDF generated using the open source mwlib toolkit. See http://code.pediapress.com/ for more information. PDF generated at: Thu, 09 Dec 2010 02:51:54 CST ZK Essentials For ZK 5

Upload: eduardo-mazariegos

Post on 27-Oct-2014

231 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: ZK 5 Essentials

PDF generated using the open source mwlib toolkit. See http://code.pediapress.com/ for more information.PDF generated at: Thu, 09 Dec 2010 02:51:54 CST

ZK EssentialsFor ZK 5

Page 2: ZK 5 Essentials

ContentsArticles

ZK Essentials 1 Introduction 1 An Introduction to ZK's Server client Fusion Architecture 1 Component Based UI 2 Event Driven Programming 10 Working with the Sample Applications 14 The Resources 14 Setting Up the Applications Using Eclipse 15 Store 17 Store with a Database 20 Laying out Your ZK Components 24 How to Layout Components 25 Using ZK Borderlayout 26 Handling the Login Process using ZK MVC and Sessions 30 The Basic Login 30 Implementing ZK MVC 31 Managing credentials using ZK Sessions 32 Displaying Information Using Grid 34 Implementing the View 34 Using a ListModel and RowRenderer 37 The Final Grid 40 Displaying information using the Listbox 44 Implementing the View 44 Using a ListModel and ListitemRenderer 47 The Final Listbox 52 Displaying Information in a Grid Using Data Binding 53 The Concept of Data Binding 53 Implementing Data Binding 57 Working with ZK and databases 62 The Theory of Using ZK with Databases 62 Using Hibernate with ZK 63 Hibernate, Entities and Database Generation 65 Hibernate Session Management and Implementing the DAOs 68 Hibernate Summary 71

Page 3: ZK 5 Essentials

Summary and Further Readings 71

ReferencesArticle Sources and Contributors 74Image Sources, Licenses and Contributors 75

Page 4: ZK 5 Essentials

ZK_Essentials 1

ZK_EssentialsDocumentation:Books/ZK_Essentials

If you have any feedback regarding this book, please leave it here.<comment>http:/ / books. zkoss. org/ wiki/ ZK_Essentials</comment>

Introduction The aim of ZK Essentials is to provide a step by step resource for a developer which addresses the creation of asubstantial application using ZK. Each chapter navigates a particular ZK topic and details in context of theapplication why certain choices and implementation techniques were chosen over others.The book chooses a shopping cart driven application as a platform to explore ZK. By the end of this book we shouldhave absorbed enough knowledge of ZK techniques and practices to implement a custom web application.The book starts off by introducing ZK and its architecture then moves into the creation of the application.

An Introduction to ZK's Server client FusionArchitecture

A ZK application runs at the server. It could access the backend resources, assemble UI with components, listen touser's activity, and then manipulate components to update UI. All are done at the server. The synchronization of thestates of the components between the browser and the server is done automatically by ZK, and transparent to theapplication.When running at the server, the application can access the full stack of Java technology. User activities are, includingAjax and Server Push, abstracted to event objects. UI are composed by POJO-like components. It is the mostproductive approach to develop a modern Web application.

Page 5: ZK 5 Essentials

An Introduction to ZK's Server client Fusion Architecture 2

With ZK's Server+client Fusion architecture, your application won't stop at the server. The application couldenhance the interactivity by adding optional client-side functionality, such as client-side event handling, visual effectcustomizing, and even UI composing without the server-side code. ZK enables the seamless fusion ranging frompure server-centric, to pure client-centric. You could have the best of two worlds: productivity and flexibility.

Component Based UI In ZK, we work with the UI components to assemble together our application GUI. We could declare componentsusing markup language, or Java.

Here we declared a Window [1] component, enabled the border (border="normal"), and set its width to a definite 250pixels. Enclosed in the Window [1] are two Button [2] components.

Where We Declare the ComponentsThe components are declared in files with the extension ".zul". A ZUL page is interpreted dynamically at the server;we could think of it as a JSP empowered with Ajax capabilities. For instance, here we create a new ZUL fileajax.zul, and we implement a sample which user's input in Textbox [3] is reflected in the label below instantly whenthe text box loses focus:ajax.zul

<window title="ZK Essentials" border="normal" width="250px">

<vlayout>

<textbox id="txtbx" onChange="lbl.value = txtbx.value"/>

<label id="lbl"/>

</vlayout>

</window>

The markup declared above renders to the sample program below:

ZK components could be declared entirely in Java also:

Page 6: ZK 5 Essentials

Component Based UI 3

package org.zkoss.zkdemo;

import org.zkoss.zk.ui.Page;

import org.zkoss.zk.ui.GenericRichlet;

import org.zkoss.zul.*;

public class TestRichlet extends GenericRichlet {

//Richlet//

public void service(Page page) {

final Window win = new Window("ZK Essentials", "normal",

false);

win.setWidth("250px");

Vlayout vl = new Vlayout();

vl.setParent(win);

final Textbox txtbx = new Textbox();

txtbx.setParent(vl);

final Label lbl = new Label();

lbl.setParent(vl);

txtbx.addEventListener("onChange", new EventListener(){

@Override

public void onEvent(Event event) throws Exception {

lbl.setValue(txtbx.getValue());

}

});

win.setPage(page);

}

}

please refer to Developer's Reference [4] for more details on programming with Richlets.

What the Components Declarations BecomeComponents declared using ZUML in a ZUL file are parsed by a ZK enhanced XML parser. The componentsdeclared are created as POJO (Plain Old Java Objects) in the JVM at the server. Suppose we have a ZUL page thatoutlines a tree of components as the following:

<window title="ZK Essentials" border="normal" width="250px">

<button label="Hello"/>

<button label="Good-bye "/>

</window>

Page 7: ZK 5 Essentials

Component Based UI 4

The ZUL page renders to a window containing two buttons as shown in the image below:

The markup in ZUL is equivalent to the following POJO declarations in Java:

Window win = new Window();

win.setTitle("ZK Essentials");

win.setBorder("normal");

win.setWidth("250px");

Button helloBtn = new Button();

helloBtn.setLabel("Hello");

helloBtn.setParent(win);

Button byeBtn = new Button();

byeBtn.setLabel("Good-bye");

byeBtn.setParent(win);

Components at server are then translated to instructions(in JSON) needed for widget (JavaScript objects) creationand sent to the client.

Page 8: ZK 5 Essentials

Component Based UI 5

Where the Components Belong

The Page

Imagine components are actors in a play, then Page [5] is the stage where components play out their roles. A page is aspace holder in a browser window where ZK components can be attached and detached. A Page [5] is not acomponent; it does not implement the Component [6] interface. A page is automatically created when user requests aresource such as a ZUL page.

The Desktop

Suppose we have a shopping cart application deployed on www.zkstore.com. When user enters this URL on thebrowser, by default, the page index.zul is requested. A Desktop [7] is created automatically when a Page [5] iscreated. A desktop may contain one or more pages, serving requests for the same URL. This is conceptuallyillustrated below:

How to Access a ComponentWith the components nested and stacked up together to give us our application UI, we need a way to identify thenecessary ones for processing. For example, we might need to dynamically append a component to an existingcomponent, or it's programmed that one component's behavior depends on that of another.The sample below illustrates such an incident:

The markup source is:

<window title="ZK Essentials" mode="overlapped" border="normal" width="250px">

<label id="lbl"/>World !

<button label="Hello " onClick="lbl.value = self.label"/>

Page 9: ZK 5 Essentials

Component Based UI 6

<button label="Good-bye " onClick="lbl.value = self.label"/>

</window>

The value of the label with ID "lbl" depends on user's clicking of the button "Hello", or "Good-bye". When a buttonis clicked, the value of the button's label is assigned to the value of the label. Note that the string "World !" isautomatically converted to a label. Without first assigning "lbl" to the desired label component, we would not havebeen able to fetch it and assign it with a value. In fact, ZK assigns each component with a UUID (Universal UniqueIdentifier) to keep track of its tree of components internally. This UUID is over-ridden when develop assigns it amore legible ID.

Finding a Component Programmatically in Java

Suppose we have a POJO declaration for a simple UI that looks like this:

Window outerWin = new Window();

Button outerBtn = new Button();

btn.setParent(outerWin);

Window innerWin = new Window();

innerWin.setParent(outerWin);

Button innerBtn = new Button();

innerBtn.setParent(innerWin);

For better readability, the equivalent declaration using ZUML in ZUL file is given here:

<window id="outerWin">

<button id="outerBtn">

<window id="innerWin">

<button id="innerBtn"/>

</window>

</window>

Now suppose we have a controller class where we want to programmatically access and modify the childrencomponents (outerBtn, innerWin, innerBtn); how could we go about accomplishing that if we have access to theWindow component only?One way of accomplishing this is calling a component's Component.getFellow() [8] method. For example, if we wishto access the inner Window, we could do the following:

Window innerWin = (Window)outerWin.getFellow("innerWin");

We can call the getFellow method on any component to access another component in the same ID Space.

An ID Space is a way to group components into a more manageable collection in ZK so that we're not at lost with trying to access a component in a large component tree. This concept is illustrated below:

Page 10: ZK 5 Essentials

Component Based UI 7

The Window [1] component and Page [9] are Space Owners by default. We can make any component a space ownerby implementing the IdSpace [10] interface. To identify a component's space owner, call its getSpaceOwner method.There are other methods to accomplish this, we summarize them in a table for clarity:

Component method Note

outerBtn = (Button)outerWin.getFellow("outerBtn"); The components outerWin, outerBtn, and innerWin form anID Space; with outerWin being the Space Owner.Components in the same ID Space can call each other by IDusing the getFellow method.

innerWin = (Window)outerWin.getFellow("innerWin"); innerWin belongs to the same ID Space as outerWin, hence, itcould be called using the getFellow method.

innerBtn = (Button)outerWin.getFellow("innerWin").getFellow("innerBtn"); innerWin and innerBtn belong to an ID Space of their own,with innerWin being the Space Owner.innerWin is also a member of the ID Space which outerWin isthe Space Owner.Hence, we can call getFellow on outerWin to get innerWin,then call getFellow on innerWin to get innerBtn.

outerBtn = (Button)Path.getComponent("/outerBtn"); The Path [11] provides the utility method getComponent whichtakes the relative path of the component as its argument./outerBtn is equivalent to outerWin/outerBtn

innerWin = (Window)Path.getComponent("/innerWin"); innerWin and outerBtn both have outerWin as an ID SpaceOwner.

innerBtn = (Button)Path.getComponent("/innerWin/innerBtn"); innerBtn has innerWin as its ID Space Owner, innerWin inturn has outerWin as its Space Owner.Hence, we write /innerWin/innerBtn, which is equivalent toouterWin/innerWin/innerBtn

outerBtn = (Button)outerWin.getFirstChild(); The getFirstChild method returns the first child component ofthe caller.The advantage of using this method is that you don't even needto know the component ID to fetch the component.

Page 11: ZK 5 Essentials

Component Based UI 8

innerWin = (Window)outerWin.getFirstChild().getNextSibling(); The getFirstChild method gets the outerBtn since it'souterWin's first child component.We then call the getNextSibling method to find the innerWin.

innerBtn =(Button)outerWin.getFirstChild().getNextSibling().getFirstChild();

We compound another getFirstChild method to get the first,and only, child component of innerWin.

Notes on XML SyntaxThe language we use to declare the components is ZUML, an abbreviation for ZK UI Markup Language. ZUMLfollows the syntax of XML. Here are a couple of basic quick notes if you're not familiar with XML[12] .• Elements must be well formed

• close declaration with an end tag:

<window></window>

• close declaration without an end tag (equivalent to the above statement):

<window/>

• Elements must be properly nested:

• Correct:

<window>

<groupbox>

Hello World!

</groupbox>

</window>

• Wrong:

<window>

<groupbox>

Hello World!

</window>

</groupbox>

• Only a single "root" component is allowed:

• one root - legal

<button />

• two roots - illegal

<button/>

<button/>

• one root containing all other components - legal

<window>

<button/>

<button/>

</window>

• Attribute value must be quoted

Page 12: ZK 5 Essentials

Component Based UI 9

• Correct:

<window width="600px"/>

• Incorrect:

<window width=600px/>

Using XML tags, we declare a component and set a component's attributes; as an alternative to coding in Java files,we could set a component's attributes to initialize values, evaluate conditions/expressions, and handle events. Thefigure belows shows an example of how we could easily dictate whether a component is to be displayed or not on apage by a simple "if" condition declared as its attribute.

[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Window. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Button. html#[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Textbox. html#[4] http:/ / books. zkoss. org/ wiki/ ZK_Developer's_Guide/ Migrate/ Integrate_Other_UI_frameworks/ SWING/ Richlets[5] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ ui/ Page. html#[6] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Component. html#[7] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ ui/ Desktop. html#[8] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Component. html#getFellow()[9] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Page. html#[10] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ IdSpace. html#[11] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Path. html#[12] Please refer to resources on Internet, such as (http:/ / www. w3schools. com/ xml/ xml_whatis. asp) and (http:/ / www. xml. com/ pub/ a/

98/ 10/ guide0. html) should you need to get comfortable with its syntax and conventions

Page 13: ZK 5 Essentials

Event Driven Programming 10

Event Driven Programming In the previous section, we saw how components are declared in ZUML (ZK User Interface Markup Language) tomake up an application's user interface. Now we'll look into ZK's event driven programming model to make all thecomponents in an application to work together to bring about functionality for our cause.

How Event Driven Programming Works with Request/ResponseEvent driven programming is widely adopted for responsive GUI experience. Each ZK component is acceptive ofhaving event listeners registered to itself. A component registered with an event listener will listen to actions by auser or events registered by the ZK framework itself. The event driven programming model in ZK works seamlesslywith the Request-Response model of HTTP. Take the sample we saw in the previous section:

<window title="ZK Essentials" mode="overlapped" border="normal" width="250px">

<label id="lbl"/>World !

<button label="Hello " onClick="lbl.value = self.label"/>

<button label="Good-bye " onClick="lbl.value = self.label"/>

</window>

The functionality for this sample code is that it displays the string of text the user selects and display the text in alabel.

Breaking down how the event driven model works

Register Event Listeners

• At line 3 and 4, we register the onClick events on the buttons so we'll know when and which button is clicked

<button label="Hello " onClick="lbl.value = self.label"/>

<button label="Good-bye " onClick="lbl.value = self.label"/>

Event Sent with Request

• When user clicks one of the buttons, its respective onClick event is sent to the server for processing by default(optionally, we could handle events at the client directly). As shown highlighted in blue, the "onClick" event andthe button's UUID (Universal Unique Identifier) is sent in the Ajax request.

EventHandling Instructions• From the request, the ZK upload engine knows which component fired the event and what event is fired. It also

knows how to handle this request because we've specified the event handling code in ZUL using EL (ExpressionLanguage): "lbl.value = self.label", which translates to the following Java code:

Page 14: ZK 5 Essentials

Event Driven Programming 11

lbl.setValue(self.getLabel);

• Where lbl is the ID we assigned to the Label component and self refers to the Button component itself (akin tothis in Java)

Update Instruction Sent Back in Response

• The server then send the instructions back to the client to reflect on this change in the label's value:

Hello

Good-bye • Where the instructions tell the client engine to set the attribute "value" to "Hello" for the component with the

UUID "z_d__2", which is the label component.

How to Register Event ListenersVarious ways are provided in ZK to register and handle events, we'll look into the most common usages here.

Event Handling in ZUL page

In a ZUL file, an event handler is registered to a component as the component's attribute.For example, suppose we have a button labeled "Hello", and we want to create a button labeled "World !"dynamically when the "Hello" button is clicked.

We could program this behavior entirely in a ZUL file:

<window id="win" title="ZK Essentials" border="normal" width="250px">

<button label="Hello">

<attribute name="onClick">

<![CDATA[

Button btn = new Button();

btn.setLabel("World !");

btn.setParent(win);

]]>

</attribute>

Page 15: ZK 5 Essentials

Event Driven Programming 12

</button>

</window>

Inside the button declaration, we declare the "onClick" event as the button's attribute and code its event handlinginstructions directly in ZUL. This is possible because the Java code is interpreted by BeanShell [1] dynamically. Inthe Java code, we first created a new Button, set its label to "World !", and then set the Window component as itsparent. Although convenient, registering event right in ZUL is not recommended if your application is performancesensitive. As all the Java code needs to be interpreted dynamically.

Event Handling In a Controller

Following the ZK MVC pattern, we create a controller class where the event is forwarded to it for handling.So here we make the necessary changes:• At line 1, we declared: apply=controller class name so that the events fired within the window is all forwarded to

the controller for event handling.• At line 2, we need to give the "Hello" button an ID so the controller would know which button fired the onClick

event.

<window id="win" title="ZK Essentials" border="normal" width="250px" apply="demo.zkoss.SampleCtrl">

<button id="helloBtn" label="Hello"/>

</window>

We then implement our controller class:• At line 7, we extend the GenericForwardComposer [2] so all events fired in its applied component would be

forwarded here.• At line 9, we declare the Window variable to match with that we declared for the Window component's ID so they

are wired.• At line 11, we follow ZK's convention for naming the event handler 'event_name$component_id'• From line 12 to 14, we use the same Java code we did previously to dynamically create a button.

package demo.zkoss;

import org.zkoss.zk.ui.util.GenericForwardComposer;

import org.zkoss.zul.Button;

import org.zkoss.zul.Window;

public class SampleCtrl extends GenericForwardComposer {

Window win;

public void onClick$helloBtn(){

Button btn = new Button();

btn.setLabel("World !");

btn.setParent(win);

}

}

Page 16: ZK 5 Essentials

Event Driven Programming 13

Event Handling of Dynamically Generated Components

Suppose we take our previous example a step further, we would like to clear off the "Hello" button in the windowwhen we click the dynamically created "World !" button. We'll need to register an event listener to the dynamicallycreated "World !" button.• At line 10, we add a new event listener to the newly created button. The addEventListener method takes an

event name (String) and an EventListener [3] as its arguments.• Within the anonymous EventListener class, we implement the onEvent method to have the Window component

fetch its "fellow" component "helloBtn" and call its detach method to clear it off the Window component.

public class SampleCtrl extends GenericForwardComposer {

Window win;

public void onClick$helloBtn(){

Button btn = new Button();

btn.setLabel("World !");

btn.setParent(win);

btn.addEventListener("onClick", new EventListener(){

public void onEvent(Event event) throws Exception {

win.getFellow("helloBtn").detach();

}

});

}

}

References[1] http:/ / www. beanshell. org/[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ ui/ util/ GenericForwardComposer. html#[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ event/ EventListener. html#

Page 17: ZK 5 Essentials

Working with the Sample Applications 14

Working with the Sample Applications In this section, we'll go over how to set up the sample applications on a ZK development environment.

The Resources This book comes with two examples:• Store - which uses an in memory model defined by Java statements• Store with database - which uses a persistent model driven by Hibernate. This is used for the last chapter of the

book.If you require the ZK libraries please download ZK first:1. Go to ZK's download page [1] and choose a package to download.2. Unzip the package and place it in a folder

StoreThe store is available on our svn using the following command:

svn checkout http:/ / zkbooks. googlecode. com/ svn/ trunk/ zkessentials/ store/ zkessentials-store

This will put the store source code into a folder named zkessentials-store.If you prefer to set up the project in eclipse please refer to here.

Store with databaseThe store with database is also available on our svn. You can checkout the project using:

svn checkout http:/ / zkbooks. googlecode. com/ svn/ trunk/ zkessentials/ storewithdb/ zkessentials-storewithdb

Having checked this out you will have the source code and a runnable WAR file which also includes the sourcecode.If you prefer to set up the project in eclipse please refer to here.

References[1] http:/ / www. zkoss. org/ download/ zk. dsp

Page 18: ZK 5 Essentials

Setting Up the Applications Using Eclipse 15

Setting Up the Applications Using Eclipse If you prefer to install it manually or use with other IDE, please refer to Create and Run Your First ZK Applicationmanually.

Set-up ZK Studio1. Open your Eclipse IDE2. On the main menu bar, select Help > Install New Software...3. Copy and paste the ZK Studio plugin's update URL : http:/ / studioupdate. zkoss. org/ studio/ update into the

input box as shown below:

4. Select Help > Activate ZK Studio

Page 19: ZK 5 Essentials

Setting Up the Applications Using Eclipse 16

5. Once the download is complete, go to Window > Preferences > ZK > ZK Packages, click Add File/Directory toadd the ZK package downloaded

6. Check-mark the package and click "Ok"

Page 20: ZK 5 Essentials

Store 17

Store

Set-up the ZK Essentials sample1. Go to the ZK Essentials checkout page [1], and checkout the source2. Create a new ZK project: File > New > Others... > ZK > ZK Project

3. Enter project name and specify the ZK package to use for this project

Page 21: ZK 5 Essentials

Store 18

4. Import the sample code by right clicking the project and select Import5. Choose import from File System

6. Select the folder containing the sample code and click "Ok" to import:

Page 22: ZK 5 Essentials

Store 19

7. Click Yes to over write the files: index.zul and web.xml

References[1] http:/ / code. google. com/ p/ zkbooks/ source/ checkout

Page 23: ZK 5 Essentials

Store with a Database 20

Store with a Database To import the project into eclipse it is easiest to make use of the WAR file which has been provided in the SVN. Wecan directly import the WAR file using eclipse’s import mechanism.1. To start go to File -> Import in eclipse and you will be presented with the following dialog

2. Type WAR into the filter text then select the storewithdb WAR file you just downloaded and press next

3. Download the WAR file from https:/ / zkbooks. googlecode. com/ svn/ trunk/ zkessentials/ storewithdb/storewithdb. war and place it into an accessible folder

Page 24: ZK 5 Essentials

Store with a Database 21

4. On the WAR import screen browse for the WAR file and select it, the rest of the fields should be filled outautomatically

5. Click finish and the WAR file will be imported6. You should now have a clean project imported with no errors. At this point you can run the index.zul page on

your serverNOTE: Having imported if eclipse is registering a lot of errors then please see the section below labelled"Dealing with Errors"

Page 25: ZK 5 Essentials

Store with a Database 22

Dealing with ErrorsYou may be seeing a lot of errors in your project say something along the lines of:

You should see errors referring to the fact that annotations are only available in Java 1.5. Right click on one of theerrors and click Quick Fix:

On the following screen make sure "change project compliance to JRE 1.5 is selected and click finish:

Page 26: ZK 5 Essentials

Store with a Database 23

Having done that we should have approximately 1 item left in the problems list. This should state that the Javacompiler level does not match the version of the installed Java project facet:

Right click on the error and click quick fix as before. Then in the following screen select the item "Change Javaproject facet version to Java 5.0" and press Finish.

Page 27: ZK 5 Essentials

Store with a Database 24

You should find that all the errors are now fixed and you can continue to run the application.

Laying out Your ZK Components In the last section, we learned about the foundations of the ZK framework: components and events. Now we're readyto embark our effort in creating a shopping cart application using ZK. We begin by learning how to lay out the lookof a ZK application.

Page 28: ZK 5 Essentials

How to Layout Components 25

How to Layout Components

Taking Web Pages to a Higher Dimension with AjaxThe content in a static web page is bounded by its page size and its layout; introducing new information to a staticweb page means redirecting to a new page. With Ajax, new information and presentation could be dynamicallyloaded onto a page by replacing pieces of the existing DOM elements, making an Ajax enabled web page analogousto having a higher order of dimension then a traditional HTML page. A clear illustration of that is the tabs (Tabbox[1]) widget, which allows document content to be stacked up in an area with fixed size on a single page. In the tablebelow, we summarize the Ajax elements enabling us to this additional degrees of freedom in page layout:

Ajax Element Usage Demo

Overlay Stack contents up in a fixed area on the same page Tabbox [2]

Folding Allow "show and hide" for contents dependent on other contents Hierarchical Grid [3], Master Detail[4],

Pop-up Allow contents contained in an area to be evoked on top of its parent page with itsposition adjustable

Modal Window [5], Pop-ups [6],

Collapsible /Closable

Allow contents to be hidden so page space is disclosed Portal Layout [7], Border Layout[8]

Splittable Allow the contents area size to be adjustable Splitter [9], Border Layout [8]

ZK offers a variety of layouts that incorporates these elements to bring flexible layout to meet the demands ofbuilding diverse web applications.Please refer to the following references for these ZK components:• Border Layout

• Component Reference• Demo [8]

• Portal Layout• Component Reference• Demo [7]

• Column Layout• Component Reference• Demo [10]

• Table Layout• Component Reference• Demo [11]

• Tab Box• Component Reference• Demo [2]

• Group Box• Component Reference• Demo [12]

• Vlayout

Page 29: ZK 5 Essentials

How to Layout Components 26

• Component Reference• Hlayout

• Component Reference

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Tabbox. html#[2] http:/ / www. zkoss. org/ zkdemo/ tabbox[3] http:/ / www. zkoss. org/ zkdemo/ grid/ hierarchy[4] http:/ / www. zkoss. org/ zkdemo/ grid/ master_detail[5] http:/ / www. zkoss. org/ zkdemo/ window/ modal_dialog[6] http:/ / www. zkoss. org/ zkdemo/ menu/ pop-ups[7] http:/ / www. zkoss. org/ zkdemo/ layout/ business_portal[8] http:/ / www. zkoss. org/ zkdemo/ layout/ border_layout[9] http:/ / www. zkoss. org/ zkdemo/ layout/ splitter[10] http:/ / www. zkoss. org/ zkdemo/ layout/ column_layout[11] http:/ / www. zkoss. org/ zkdemo/ layout/ table_layout[12] http:/ / www. zkoss. org/ zkdemo/ layout/ group_box

Using ZK Borderlayout Suppose in our shopping cart application, we have the following requirements:• Product View - A table displaying the available products to purchase• Shopping Cart View - A list of items placed in the shopping cart• Order View - A record of all the orders placed

Page 30: ZK 5 Essentials

Using ZK Borderlayout 27

The borderlayout divides a page into five sections: North, East, Center, West, South.

Border Layout AttributesThe attributes involved in the configuration of border layout is listed in the table below:

Attributes Sample Description

size <north size="20%">...</north> <south size="180px">...</south> set size in pixels or a percentage relative to its parentcomponent

border <east border="normal">...</east> show/hide border; "normal" shows border, while "none" hidesborder

collapsible <west collapsible="true">...</west> allow the whole division to show/hide

maxsize/minsize <south splitter="true" maxsize="500px"minisize="200px">...</south>

set the maximum and minimum allowable size for acomponent;

splittable <north splittable="true">...</north> allow the contents area size to be adjustable

Page 31: ZK 5 Essentials

Using ZK Borderlayout 28

Why Use BorderlayoutBorder Layout [1] stands out as the obvious choice because it supports:• splittable [9], so we could adjust the dimensions of the views by dragging the splitters.• collapsible [8], so views could be collapsed to make room for other views.Using the Borderlayout [2], we could outline the shopping cart application like the following:

The borders can be made adjustable (splittable="true"), and the east and south components can be collapsed to giveroom to the center component displaying the Product View.

Implementing the ViewsWe start implementing the Views for our shopping cart sample application by first making the divisions of the Viewsusing borderlayout:

<window border="normal" width="100%" height="900px">

<borderlayout>

<center title="Product View" border="0">

<div id="PrdoDiv" style="background:#D9E5EF; height:100%" apply="demo.web.ui.ctrl.ProductViewCtrl">

//Product View Implementation

</div>

</center>

<east title="Shopping Cart View" size="30%" flex="true" splittable="true" collapsible="true">

<div style="background:#D9E5EF; height:100%" apply="demo.web.ui.ctrl.ShoppingCartViewCtrl">

//Shopping Cart View Implementation

</div>

</east>

<south title="Order View" size="250px" flex="true" border="0" splittable="true" collapsible="true" style="overflow:scroll">

Page 32: ZK 5 Essentials

Using ZK Borderlayout 29

<div style="background:#D9E5EF; height:100%" apply="demo.web.ui.ctrl.OrderViewCtrl" >

//Order View Implementation

</div>

</south>

</borderlayout>

Here we note a few key implementations:• The size of the borderlayout is not specified, so its dimensions will assume that of its parent component Window

[1].• The borderlayout component itself does not have the "border" attribute, only its children (north, west, etc..) do.• north, east, center, west, and south, are allowed only one child component; therefore, use container components

such as Div [3] or Window [1] to wrap multiple components when placing them in borderlayout's childrencomponents.

• The center component does not take any size attributes; its height is dependent on the dimensions of north/south,while its width is dependent east/west.

• The splittable and collapsible attributes are set to "true" to allow the dimensions of east and south to bemanipulated.

• The apply attribute is used here to assign a controller to the container component so components within it areauto-wired with data objects and events are automatically forwarded to event handlers.

The Finalized Layout

Page 33: ZK 5 Essentials

Using ZK Borderlayout 30

References[1] http:/ / books. zkoss. org/ wiki/ ZK_Developer's_Guide/ ZUL_Components/ Layout_and_Windows/ The_Layout_Components[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Borderlayout. html#[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Div. html#

Handling the Login Process using ZK MVC andSessions Having established a layout for the application we move onto dealing with user authentication. In this section we willtake a look at how to build your login using ZUL files, ZK MVC pattern of development and Sessions.

The Basic Login Before beginning to implement the login first let us define the behavior we require in use case. The use case belowrepresents the flow we would like to deliver to users upon entry or login to the system.

The first thing we need to do is create the interface log-in using a ZUL file. The basic ZUL markup which representsour login form is shown below.<syntax lang="xml"> <?page title="ZK Store - Login"?> <window id="loginWin" border="normal" width="300px"title="You are using: ${desktop.webApp.version}"> <grid> <rows> <row> Name: <textboxid="nameTxb"/></row> <row> Password:<textbox id="passwordTxb" type="password"/></row> </rows> </grid><button id="confirmBtn" label="confirm"/> <label id="mesgLbl"/> </window> </syntax>The ZUL representation is very simple and consists of a Grid which aids the layout of the Textbox along with aButton to perform the confirm action and a Label to notify the user of any issues with the login process. At themoment the ZUL file represents a dumb login page as the button is not mapped to an action.The recommended way to add functionality to your UI is to follow the MVC pattern of development. The followingsection details how to implement ZK using the MVC pattern.

Page 34: ZK 5 Essentials

Implementing ZK MVC 31

Implementing ZK MVC The MVC pattern is a favorite of developers as it neatly separates the various application layers in a clear manner.ZK aids in this process by allowing UI declaration to be done using an XML declarative language. It should be notedhowever, that we can create Swing programmatic UIs using Richlets.ZK MVC revolves around two key items, the GenericForwardComposer [1] and the apply attribute. TheGenericForwardComposer [1] is a utility class which adds auto-wire functionality enabling access to UI objects fromJava code without any effort. Let’s demonstrate how to add functionality to the login page.

Creating a controller (GenericForwardComposed) & applying itFirstly we need to create a controller class named LoginViewCtrl which extends from the GenericForwardComposer[1], this is a trivial matter in Java.<syntax lang="xml"> public class LoginViewCtrl extends GenericForwardComposer </syntax>Having created this class we need to link it to our ZUL file. We do this by specifying the apply attribute.<syntax lang="xml" high="4"> <?page title="ZK Store - Login"?> <window id="loginWin" border="normal"width="300px" title="You are using: ${desktop.webApp.version}" apply="demo.web.ui.ctrl.LoginViewCtrl"><grid> <rows> <row> Name: <textbox id="nameTxb"/></row> <row> Password:<textbox id="passwordTxb"type="password"/></row> </rows> </grid> <button id="confirmBtn" label="confirm"/> <label id="mesgLbl"/></window> </syntax>As demonstrated in the above code we set the apply attributes value to the full class name with path, in this case<mp>demo.web.ui.ctrl.LoginViewCtrl</mp>.

Auto-wiring components and eventsHaving applied the GenericForwardComposer [1] we can declare the components within the class as private variableswhich will be auto wired with the equivalent ZUL components.<syntax lang="java" high="13,14,15"> import org.zkoss.zul.Label; import org.zkoss.zul.Textbox;import demo.model.bean.User; import demo.web.UserCredentialManager;/**

* @author Ian Tsai

*

*/

public class LoginViewCtrl extends GenericForwardComposer {private Textbox nameTxb; private Textbox passwordTxb; private Label mesgLbl; } </syntax>You can now access the UI components server-side and interact with them. All the wiring and the communication istaken care of by ZK automatically.The next step is to enable the capturing of events. In this specific case we need to capture the <mp>onClick</mp>event of out button <mp>confirmBtn</mp>. To do this we need to create a method with a specific signature, in thiscase we use the event name followed by a $ and followed by the component name. Therefore in our case the methodsignature is as follows:<syntax lang="java"> public void onClick$confirmBtn() </syntax>Notice that the method does not take any parameters, however if necessary the method can take an Event [2] object asa parameter or the subsequent subclass which is applicable in the context.

Page 35: ZK 5 Essentials

Implementing ZK MVC 32

Lastly we need to consider that people coming to the login.zul page may already be logged in just as our use caseindicates. Therefore we need to setup a mechanism that checks whether that is the case before loading the UI. This isdone by overriding the GenericForwardComposer [1] methodGenericForwardComposer.doAfterCompose(org.zkoss.zk.ui.Component) [3] which is called when the events andcomponents are being wired. Thus if you override this method please make sure to call the super method. At thisstage your doAfterCompose(org.zkoss.zk.ui.Component) [3] method should look like this:<syntax lang="java"> public void doAfterCompose(Component comp) throws Exception {super.doAfterCompose(comp);//to be implemented, let’s check for a login } </syntax>By now we have an understanding of what advantages ZK provides us by wiring the components, events and dataautomatically. We need to move on to our goal of implementing a user management system to check credentials andredirect according to our use case. The next section walks through how user credentials was implemented using asession.

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ util/ GenericForwardComposer. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ event/ Event. html#[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ util/ GenericForwardComposer. html#doAfterCompose(org. zkoss. zk. ui.

Component)

Managing credentials using ZK Sessions One of the paradigms used within the essentials guide is the singleton managers which live within the session. Thebasic premise for storing singletons in the session is the fact that they are available anywhere at any time and usercredential specific, when the session expires the login credentials are conveniently cleared.

The Credentials ManagerFor managing credentials we create a singleton named <mp>UserCredentialManager</mp> which wraps a<mp>UserDAO</mp>. Additionally the <mp>UserCredentialManager</mp> will expose two<mp>getInstance</mp> methods, one which takes a Session [1] and one that doesn’t. The basic concept is that whenthe instance is retrieved it will check the Session [1] for an existing credential manager and if there isn’t one present itwill create one.The code below demonstrates the two <mp>getInstance</mp> methods along with the creation of the<mp>userDAO</mp> in the constructor.<syntax lang="java" high="11,18"> public class UserCredentialManager {private static final String KEY_USER_MODEL = UserCredentialManager.class.getName()+"_MODEL"; privateUserDAO userDAO; private User user; private UserCredentialManager(){ userDAO = new UserDAO(); } publicstatic UserCredentialManager getIntance(){ return getIntance(Sessions.getCurrent()); } /** * * @return */ publicstatic UserCredentialManager getIntance(Session zkSession){ HttpSession httpSession = (HttpSession)zkSession.getNativeSession(); // Session session = Executions.getCurrent().getDesktop().getSession(); // Sessionsession = Executions.getCurrent().getSession(); Session session = Sessions.getCurrent(); synchronized(zkSession){UserCredentialManager userModel = (UserCredentialManager) zkSession.getAttribute(KEY_USER_MODEL);if(userModel==null){ zkSession.setAttribute(KEY_USER_MODEL, userModel = new UserCredentialManager()); }return userModel; } } } </syntax>

Page 36: ZK 5 Essentials

Managing credentials using ZK Sessions 33

The manager is very standard exposing a login method which if successful sets the <mp>User</mp> object and a<mp>isAuthenticated</mp> method which checks to see whether the user is null and returns accordingly. Havingput this into place we can now make use of it in our controller to change the page flow of the application.

Redirecting the user depending on the UserCredentialManagerIf we think back to our login page and use case we have two places we need to check for a valid user. Once when theuser navigates to the page and when the user presses the confirm button. If the user is authenticated then we need away to redirect to the index page. This is handled using the Execution [2] class which provides information about thecurrent execution, such as the request parameters.A GenericForwardComposer contains an Execution object named execution which is accessible. If we need to accessit outside of a GenericForwardComposer [1] we can retrieve the current execution by calling the getCurrent() [3]

method in the Executions [4] class as it is static.The Executions.sendRedirect(java.lang.String) [5] class has a method named Executions [4] which will redirect theuser to a page you specify, in this case “index.zul.”<syntax lang="java" high="2"> if(UserCredentialManager.getIntance(session).isAuthenticated()){execution.sendRedirect("index.zul"); } </syntax>This concludes the login topic, next we will deal with displaying information to the user using a Grid [6] and Listbox[7].

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Session. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Execution. html#[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Executions. html#getCurrent()[4] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Executions. html#[5] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ Executions. html#sendRedirect(java. lang. String)[6] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Grid. html#[7] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Listbox. html#

Page 37: ZK 5 Essentials

Displaying Information Using Grid 34

Displaying Information Using Grid We'll use the Grid component to present the "Product View" of our shopping cart application.

Implementing the View Suppose the figure below is the requirement for the "Product View" in our shopping cart application:

Here we havesix columns, each with a header to denote the data field, and six rows with each row containing a single productentry. The product information is listed from column one to five while the last column contains ZK componentswhich allow end users to choose and submit a product's quantity for purchase. To accommodate these requirements,we'll use the ZK Grid component.

Introduction to the ZK GridA ZK Grid contains two main constituents, Columns and Rows. The Columns tag is used to divide the Grid with theColumn components and display the column headers; while the Rows tag contains the Row components which holdother UI components needed for read (Data Presentations) or write (Form Inputs) purposes.In the simple example below, we put two Column components in the Columns tag to give our Grid two columns andset their labels to give the Grid column headers. We place two Row components in Rows and assign two Labelcomponents in each to show textual data.

<grid width="400px" >

<columns>

<column label="Column Header 1" />

<column label="Column Header 2" />

</columns>

Page 38: ZK 5 Essentials

Implementing the View 35

<rows >

<row >

<label value="Row 1 - Item 1"/>

<label value="Row 1 - Item 2"/>

</row>

<row >

<label value="Row 2 - Item 1"/>

<label value="Row 2 - Item 2"/>

</row>

</rows>

</grid>

A Row component accepts all ZK components as its children components, hence, a Grid component can be treatedas a component container making it suitable for• Laying out forms [1]

• Presenting a collection of data [2]

• Presenting hierarchical data [3]

For our implementation of the "Product View", we could use a Grid to divide product entries into rows, with the firstcolumn holding the product's image, second to fifth columns containing the product's properties, and the last columnenclosing a Cell component which allows end users to select and submit the quantity of the purchased item.

Grid ConfigurationAll ZK components can be customized using CSS. In this short snippet, we were able to configure the size of theGrid and its constituents, set alignment, and change text color using minimum attribute declarations.

<grid width="400px" >

<columns>

<column label="Column Header 1" width="60%"/>

<column label="Column Header 2" width="40%"/>

</columns>

<rows >

<row >

<label value="Row 1 - Item 1" />

<label value="Row 1 - Item 2"/>

</row>

<row align="center">

<label value="Row 2 - Item 1" style="color:blue"/>

<label value="Row 2 - Item 2"/>

</row>

</rows>

Page 39: ZK 5 Essentials

Implementing the View 36

</grid>

For this particular example, we assigned a percentage value to each Column so their size is shown proportional to theGrid component. Items in a Row are automatically aligned at the center when it's declared in the Row componentattribute. The style attribute allows us to specify the CSS for any particular ZK component, for instance, the color ofthe text is set as blue for the Row 2 -Item 1 label.

The Product View ImplementationFor our shopping cart example, the implementation of the "Product View" is placed in the Center section of theBorderlayout. The Grid is encased by a Div component which is applied with a controller class that extends theGenericForwardComposer [1] class. We'll go into the details of this controller class in the next section of this book.We give the Grid component an ID so that we could retrieve the Grid in our controller class and associate the datafields to its inner components. At line 3, we marked the Columns 'sizable="true"' so the end user could adjust thecolumn width by dragging its borders. From line 4 through 9 we decorate the column headers with image(Image) ortext(Label) and set the default width for each column. With just several lines of mark up, we've already finished withour UI declaration that will serve as the containers for data to be populated.

<center border="0">

<div id="PrdoDiv" style="background:#E6D92C; height:100%" apply="demo.web.ui.ctrl.ProductViewCtrl">

<grid id="prodGrid">

<columns sizable="true">

<column image="/image/Bullet-10x10.png" align="center" width="100px"/>

<column label="Name" width="100px"/>

<column label="Price" width="50px"/>

<column label="Quantity" width="50px"/>

<column label="Arrive Date" width="110px" />

<column label="operation" />

</columns>

</grid>

</div>

</center>

References[1] http:/ / www. zkoss. org/ zkdemo/ input/ form_sample[2] http:/ / www. zkoss. org/ zkdemo/ grid/ load_on_demand

Page 40: ZK 5 Essentials

Using a ListModel and RowRenderer 37

Using a ListModel and RowRenderer Data presentation in ZK involves preparing the Model and Renderer in association with the View (ZK components).Once an association is established between these three parts, the data presented in ZK components are automaticallyupdated whenever the data model is changed. In the previous section, we declared the basic UI skeleton, now we'lllook into how to prepare a data model and write a renderer to populate the Grid component.

Where the View, Model, and Renderer Come TogetherTo associate our Product View (Grid component) with a Model and a Renderer, we'll implement a controller classwhich extends the ZK utility class GenericForwardComposer [1]. In itsGenericForwardComposer.doAfterCompose(org.zkoss.zk.ui.Component) [3] method, the ZK components declared inmark up are wired with the component instances declared in the controller for our manipulation, while the eventsfired are automatically forwarded to this controller for event handling. Therefore, in our controller class, we overrideand call GenericForwardComposer.doAfterCompose(org.zkoss.zk.ui.Component) [3] method of its super class andimplement the code that assigns a model and renderer to our Product View Grid.ProductViewCtrl.java

public class ProductViewCtrl extends GenericForwardComposer {

private Grid prodGrid;

@Override

public void doAfterCompose(Component comp) throws Exception {

super.doAfterCompose(comp);

//create model

prodGrid.setModel(...); //assign model to Grid

Page 41: ZK 5 Essentials

Using a ListModel and RowRenderer 38

//create renderer

prodGrid.setRowRenderer(...);//assign renderer to Grid

...

}

}

Notice the Grid reference "prodGrid" in ProductViewCtrl.java is auto-wired with the Grid declared in mark upwhose ID is "prodGrid".

<div id="PrdoDiv" style="background:#E6D92C; height:100%" apply="demo.web.ui.ctrl.ProductViewCtrl">

<grid id="prodGrid">

<columns sizable="true">

<column image="/image/Bullet-10x10.png" align="center" width="100px"/>

<column label="Name" width="100px"/>

<column label="Price" width="50px"/>

<column label="Quantity" width="50px"/>

<column label="Arrive Date" width="110px" />

<column label="operation" />

</columns>

</grid>

</div>

Wrapping Data Object with ListModelThe implementations of ZK's ListModel [1] interface provide a wrapper for Java Collections to work with ZK's datamodeling mechanisms. For Grid [6] and Listbox [7] components, we use the ListModelList [2] implementation;addition or removal of entries in the ListModelList [2] would cause the associated Listbox [7] to update its contentaccordingly.In the snippet below, the ListModelList takes in a product list fetched from a DAO object as its argument. At line 8,we assign the ListModelList object as the model for the Product View Grid by using Grid's setModel method.ProductViewCtrl.java

public void doAfterCompose(Component comp) throws Exception {

...

ProductDAO prodDao = new ProductDAO();

List<Product> prods = prodDao.findAllAvailable();

ListModelList prodModel = new ListModelList(prods);

prodGrid.setModel(prodModel);

...

});

}

Page 42: ZK 5 Essentials

Using a ListModel and RowRenderer 39

Using a RowRenderer to Populate DataTo populate each row with data, we create an anonymous RowRenderer [3] class and implement its row,java.lang.Object data) RowRenderer.render(Row row, java.lang.Object data) [4] method. Here the ZK frameworksupplies us with the row instance and the data object obtained through the iteration of the data model ListModelList.At line 5, we cast the data object back to the Product object so we could extract information from it and render themin each row; that is, inside the render method, we associate the data fields of the Product object to a Row object, inthe order we wish them to appear across the Grid columns.We are required to place an image of the product in the first column, hence at line 7, we create an instance of theImage [5] class, configure its dimensions, and finally set the row object as its parent component. From line 11through 14, we extract the Product's name, price, quantity, and manufactured date and wrap these data fields with theLabel [6] components and set the row object as their parent component. Line 15 calls the initOperation method inthe same class to create and return a Cell [7] component which is set as the child component for the last column of therow; more of its implementation in the next section.

public void doAfterCompose(Component comp) throws Exception {

...

prodGrid.setRowRenderer(new RowRenderer() {

public void render(Row row, Object data) throws

Exception {

final Product prod = (Product)data;

Image img = new Image(prod.getImgPath());

img.setWidth("70px");

img.setHeight("70px");

img.setParent(row);

new Label(prod.getName()).setParent(row);

new Label(""+prod.getPrice()).setParent(row);

new

Label(""+prod.getQuantity()).setParent(row);

new

Label(YYYY_MM_DD_hh_ss.format(prod.getCreateDate())).setParent(row);

initOperation(prod).setParent(row);

}

...

});

}

The renderer is a series of instructions assigning the UI components with values; using a View-Model-Rendererapproach, any changes in the data model translates to updates in the UI component when the renderer code is run.

Page 43: ZK 5 Essentials

Using a ListModel and RowRenderer 40

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ ListModel. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ ListModelList. html#[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ RowRenderer. html#[4] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ RowRenderer. html#render(Row[5] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Image. html#[6] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Label. html#[7] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Cell. html#

The Final Grid The fully implemented Product View looks like the below:

In the previous section, we saw how the renderer assigns UI components (for example, Image [5] and Label [6]) intorows of a Grid for UI presentation.ProductViewCtrl.java - Rendering Rows

public void doAfterCompose(Component comp) throws Exception {

...

prodGrid.setRowRenderer(new RowRenderer() {

public void render(Row row, Object data) throws

Exception {

final Product prod = (Product)data;

Image img = new Image(prod.getImgPath());

img.setWidth("70px");

img.setHeight("70px");

Page 44: ZK 5 Essentials

The Final Grid 41

img.setParent(row);

new Label(prod.getName()).setParent(row);

new Label(""+prod.getPrice()).setParent(row);

new

Label(""+prod.getQuantity()).setParent(row);

new

Label(YYYY_MM_DD_hh_ss.format(prod.getCreateDate())).setParent(row);

initOperation(prod).setParent(row);

}

...

});

}

The last column contains a Cell [7] component (returned by the method initOperation) which allows end users toADD items to be purchased. In this section, we'll look into the implementation of this functionality which fulfills therequirements for the Product View Grid.ProductViewCtrl.java - Implementation for "Adding" Items to Purchase

private Cell initOperation(final Product prod){

Cell cell = new Cell();

final Spinner spinner = new Spinner(1);

spinner.setConstraint("min 1 max

"+prod.getQuantity());

spinner.setParent(cell);

Button button = new Button("add");

button.setImage("/image/ShoppingCart-16x16.png");

button.setParent(cell);

final Label errorLb = new Label();

errorLb.setParent(cell);

button.addEventListener(ON_CLICK, new

EventListener() {

public void onEvent(Event event) throws

Exception {

ShoppingCartCtrl ctrl =

ShoppingCartViewCtrl.getInstance(desktop);

try{

ctrl.addItem(prod, spinner.getValue());

errorLb.setValue("");

}catch(WrongValueException e){

errorLb.setValue(e.getMessage());

}

}

});

return cell;

Page 45: ZK 5 Essentials

The Final Grid 42

}

The Cell ComponentIn the initOperation method, Spinner [1] and Button [2] are created programmatically to allow end users to select andsubmit the quantity of the items to be purchased; the Cell [7] is set as the parent component for these components,serving as a container.

Setting Constraints for an Input UI ComponentAll ZK components implementing the InputElement [2] interface can call the constr)InputElement.setConstraint(java.lang.String constr) [3] method to set an upper and lower bound on the allowableinput value. For instance, value selected for the Spinner [1] component is only meaningful if it's between 1 and thequantity remained in stock for each product; hence, we could cal the setConstraint to impose the allowable range:

spinner.setConstraint("min 1 max "+prod.getQuantity());

This convenient method offers us an easy way to impose a simple validation mechanism for the input componentssuch as Textbox [3], Intbox [4], Datebox [5], and Combobox [6].

Registering an Event ListenerWhen users click the "add" button, we need to verify whether the quantity from all orders combined does not exceedthe quantity in stock for each product. Since we are creating the button here programmatically, we'll need to add anevent listener manually, as oppose to making button declaration in ZUL and rely on the GenericForwardComposer[1] facilitate this process.

private Cell initOperation(final Product prod){

...

Button button = new Button("add");

button.addEventListener(ON_CLICK, new

EventListener() {

public void onEvent(Event event) throws

Exception {

//event handling code here...

});

return cell;

}

Utilizing Session Scope AttributesThe tasks needed to be done in the button's event handling is adding the purchased product to the shopping cart in thequantity that's specified. Since a shopping cart instance should pervade a user's session, it makes sense to save, orretrieve it as a session attribute:ShoppingCartViewCtrl.java

private static ShoppingCart getShoppingCart(Session session){

ShoppingCart cart =

(ShoppingCart) session.getAttribute("ShoppingCart");

if(cart==null){

session.setAttribute("ShoppingCart", cart = new

Page 46: ZK 5 Essentials

The Final Grid 43

ShoppingCart());

}

return cart;

}

So that when we try to add an item, along with its quantity, we could get the same shopping cart instance for thesession and validate whether the addition is allowed. Note that session is an implicit object instantiated by ZK.ShoppingCartViewCtrl.java

public void addItem(Product prod, int amount) {

try{

getShoppingCart(session).add(prod, amount, new

AddToCartCallback() {

//validation code

});

refresh();

}catch(OverQuantityException e){

throw new WrongValueException(e);

}

}

The ShoppingCartView class is a controller where we access the single shopping cart instance across a session andrenders the shopping cart data in the Shopping Cart View. Since only a single controller instanceShoppingCartViewCtrl is needed per desktop, we save and retrieve the ShoppingCartViewCtrl instance indesktop scope. ShoppingCartViewCtrl.java

public static ShoppingCartCtrl getInstance(Desktop desktop){

return (ShoppingCartCtrl)

desktop.getAttribute(KEY_SHOPPING_CART);

}

With the ShoppingCart instance stored as a session attribute, and the ShoppingCartViewCtrl instance stored indesktop scope, they are made easily accessible to us in the button's event handling code.

private Cell initOperation(final Product prod){

...

button.addEventListener(ON_CLICK, new

EventListener() {

public void onEvent(Event event) throws

Exception {

ShoppingCartCtrl ctrl =

ShoppingCartViewCtrl.getInstance(desktop);

try{

ctrl.addItem(prod, spinner.getValue());

errorLb.setValue("");

}catch(WrongValueException e){

errorLb.setValue(e.getMessage());

}

}

Page 47: ZK 5 Essentials

The Final Grid 44

});

return cell;

}

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Spinner. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ impl/ api/ InputElement. html#[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ impl/ api/ InputElement. html#setConstraint(java. lang. String[4] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Intbox. html#[5] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Datebox. html#[6] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Combobox. html#

Displaying information using the Listbox We’ll use the Listbox component to present the “Shopping Cart” of our application.

Implementing the View

Implementing the ViewSuppose the figure below is the requirement for the "Shopping cart" in our shopping cart application:

Here we have five columns, four with a header to denote the data field, and a variable number of rows containingproduct orders. In this case we also have a requirement to display a picture of the product ordered when selecting anitem in the shopping cart. In this case we use the Listbox as this enables developers to select an item firing anonSelect event when this occurs.

Page 48: ZK 5 Essentials

Implementing the View 45

Introduction to the ZK ListboxA ZK Listbox contains a few constituents, listitem, listcell, listhead and listheader.

A Simple Listbox example

The simplest Listbox [7] can be outputted using Listitems. In the example below we place 3 Listitems into theListbox [7].

<zk>

<listbox>

<listitem label="Butter Pecan"/>

<listitem label="Chocolate Chip"/>

<listitem label="Raspberry Ripple"/>

</listbox>

</zk>

The Select Mold

In addition the Listbox [7] comes in two molds, default and select. The select mold enables the HTML SELECT tagto be generated instead thus producing the following content. The following example demonstrates the effect ofchanging the mold on the Listbox [7].

<zk>

<listbox mold=”select”> <listitem label="Butter Pecan"/>

<listitem label="Chocolate Chip"/>

<listitem label="Raspberry Ripple"/>

</listbox>

</zk>

Multiple Columns and Headers

The Listbox [7] also supports multiple columns and headers. In the following example we use Listhead [1] andListheader [2] to create headers on two columns. The following example demonstrates a multi-column Listbox [7]

with a header. Please note you can have a multi-column Listbox [7] without the headers by specifying more than oneListcell [3] in a particular Listitem [4].

<zk>

<listbox width="200px">

<listhead>

<listheader label="Name"/>

<listheader label="Occupation"/>

</listhead>

<listitem>

Page 49: ZK 5 Essentials

Implementing the View 46

<listcell label="George"/>

<listcell label="House Painter"/>

</listitem>

<listitem>

<listcell label="Mary Ellen"/>

<listcell label="Candle Maker"/>

</listitem>

<listitem>

<listcell label="Roger"/>

<listcell label="Swashbuckler"/>

</listitem>

</listbox>

</zk>

The Shopping cart view Implementation

The implementation of shopping cart view is placed in the east side section of the Borderlayout [2]. Just like theprevious section the Listbox [7] is encased by a Div [3] component which is applied with a controller class whichextends the GenericForwardComposer [1] class. We’ll go into details of this controller class in the next section of thisbook. The only special part of the Listbox [7] we haven’t already covered is the Listfooter [5] which is encased in thetag Listfoot [6]. This will place the specified components on the button, in this case a subtotal, button to submit anorder and a button to clear the order.

<east title="Shopping Cart" size="30%" flex="true" splittable="true" collapsible="true">

<div style="background:#E6D92C; height:100%" apply="demo.web.ui.ctrl.ShoppingCartViewCtrl">

<listbox id="shoppingCartListbox">

<listhead sizable="true">

<listheader label="Name" />

<listheader label="Price" />

<listheader label="Amount" />

<listheader label="subTotal"/>

<listheader align="center"/>

</listhead>

<listfoot>

<listfooter span="2" id="subtotalFooter"></listfooter>

<listfooter><button id="submitOrderBtn" label="submit"/></listfooter>

<listfooter><button id="clearBtn" label="clear"/></listfooter>

</listfoot>

</listbox>

<textbox id="descTxb" rows="10" width="200px" value="Note for this order." />

Page 50: ZK 5 Essentials

Implementing the View 47

<image id="cartItemImage" />

</div>

</east>

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Listhead. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Listheader. html#[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Listcell. html#[4] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Listitem. html#[5] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Listfooter. html#[6] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Listfoot. html#

Using a ListModel and ListitemRenderer As previously addressed presentation of data can be done using appropriate renderers or databinding. In this case asthe information is very dynamic then we have chosen to use the rendering method. For more information onchoosing between databinding and renderers please visit this section.The ListModel [1] and ListitemRenderer [1] work in a similar manner to the RowRenderer [3].

Where the View, Model, and Renderer Come TogetherTo associate our Shopping cart view (Listbox [7] component) with a Model and a Renderer, we'll implement a controller class which extends the ZK utility class GenericForwardComposer [1]. In its GenericForwardComposer.doAfterCompose(org.zkoss.zk.ui.Component) [3] method, the ZK components declared in mark up are wired with the component instances declared in the controller for our manipulation, while the events fired are automatically forwarded to this controller for event handling. Therefore, in our controller class, we override

Page 51: ZK 5 Essentials

Using a ListModel and ListitemRenderer 48

and call GenericForwardComposer.doAfterCompose(org.zkoss.zk.ui.Component) [3] method of its super class andimplement the code that assigns a model and renderer to our Shopping cart Listbox [7].ProductViewCtrl.java

public class ProductViewCtrl extends GenericForwardComposer {

private Listbox shoppingCartListbox;

@Override

public void doAfterCompose(Component comp) throws Exception {

super.doAfterCompose(comp);

//create model

shoppingCartListbox.setModel(...); //assign model to Grid

//create renderer

shoppingCartListbox.setItemRenderer(...);//assign renderer to

Grid

...

}

}

<div style="background:#E6D92C; height:100%" apply="demo.web.ui.ctrl.ShoppingCartViewCtrl">

<listbox id="shoppingCartListbox">

<listhead sizable="true">

<listheader label="Name" />

<listheader label="Price" />

<listheader label="Amount" />

<listheader label="subTotal"/>

<listheader align="center"/>

</listhead>

<listfoot>

<listfooter span="2" id="subtotalFooter"></listfooter>

<listfooter><button id="submitOrderBtn" label="submit"/></listfooter>

<listfooter><button id="clearBtn" label="clear"/></listfooter>

</listfoot>

</listbox>

<textbox id="descTxb" rows="10" width="200px" value="Note for this order." />

<image id="cartItemImage" />

</div>

Page 52: ZK 5 Essentials

Using a ListModel and ListitemRenderer 49

Using an ListitemRenderer to Populate DataTo populate the data we create an anonymous ListitemRenderer [1] class and implement its render method in asimilar manner to the RowRenderer [3].From here we know that the data passed to the methodis a <mp>CartItem</mp> as set in our model. We need topopulate 5 columns and therefore need to create 5 Listcells. The first 3 items can be extracted from the data bean andeasily placed into Listcells, however, the last two items consist of a sub total and a cancel button.To implement the subtotal and cancel button we create two private functions in our anonymous class named<mp>initSubTotal</mp> and <mp>initCancelBtn</mp> respectively.

shoppingCartListbox.setItemRenderer(new ListitemRenderer()

{

public void render(Listitem listItem, Object data)

throws Exception {

final CartItem cartItem = (CartItem)data;

final Product prod = cartItem.getProduct();

listItem.setValue(cartItem);

new

Listcell(prod.getName()).setParent(listItem);

new

Listcell(""+prod.getPrice()).setParent(listItem);

new

Listcell(""+cartItem.getAmount()).setParent(listItem);

initSubTotal(cartItem, new

Listcell()).setParent(listItem);

initCancelBtn(cartItem, prod, new

Listcell()).setParent(listItem);

}

private Listcell initSubTotal(CartItem cartItem,

Listcell cell){

float price = cartItem.getProduct().getPrice();

float subTotal = price * cartItem.getAmount();

Label subTotalLb = new Label("$ "+subTotal);

subTotalLb.setStyle("word-wrap: word-break");

subTotalLb.setParent(cell);

return cell;

}

private Listcell initCancelBtn(final CartItem

cartItem, final Product prod, Listcell cell){

Button button = new Button();

Page 53: ZK 5 Essentials

Using a ListModel and ListitemRenderer 50

button.setImage("/image/DeleteCross-16x16.png");

button.addEventListener(ON_CLICK, new

EventListener() {

public void onEvent(Event event) throws

Exception {

_cartModel.remove(cartItem);

refresh();

}

});

button.setParent(cell);

return cell;

}

});

Let’s look more in depth at the two functions.

private Listcell initSubTotal(CartItem cartItem, Listcell cell) {

float price = cartItem.getProduct().getPrice();

float subTotal = price * cartItem.getAmount();

Label subTotalLb = new Label("$ "+subTotal);

subTotalLb.setStyle("word-wrap: word-break");

subTotalLb.setParent(cell);

return cell;

}

private Listcell initCancelBtn(final CartItem cartItem, final Product

prod, Listcell cell){

Button button = new Button();

button.setImage("/image/DeleteCross-16x16.png");

button.addEventListener(ON_CLICK, new EventListener() {

public void onEvent(Event event) throws Exception {

_cartModel.remove(cartItem);

refresh();

}

});

Both these functions take the cartitem along with a Listcell [3] and return a Listcell [3]. In the method<mp>initSubTotal</mp> the subtotal is calculated, placed into a Label [6] and then has the style set. Finally theLabels parent is set and returned.

Label subTotalLb = new Label("$ "+subTotal);

subTotalLb.setStyle("word-wrap: word-break");

subTotalLb.setParent(cell);

return cell;

The cancel function is slightly more indepth as it constructs a button, sets its image and then adds an EventListener [3] to itself to listen for the ON_CLICK event. The advantage of a renderer is displayed here as a reference to the <mp>Cartitem</mp> is available therefore it is very easy to create an anonymous EventListener [3] implementation

Page 54: ZK 5 Essentials

Using a ListModel and ListitemRenderer 51

which can remove the <mp>cartitem</mp> from the model as the object reference is freely available.Finally if we return to the original implementation of the ListItemRenderer [2] class all the Listcell [3] set their parentto the given Listitem [4] so they are displayed appropriately.

public void render(Listitem listItem, Object

data) throws Exception {

final CartItem cartItem = (CartItem)data;

final Product prod = cartItem.getProduct();

listItem.setValue(cartItem);

new

Listcell(prod.getName()).setParent(listItem);

new

Listcell(""+prod.getPrice()).setParent(listItem);

new

Listcell(""+cartItem.getAmount()).setParent(listItem);

initSubTotal(cartItem, new

Listcell()).setParent(listItem);

initCancelBtn(cartItem, prod, new

Listcell()).setParent(listItem);

}

Just as with the Grid’s RowRenderer [3], the ListItemRenderer [2] is a series of instructions assigning the UIcomponents with values; using a View-Model-Renderer approach, any changes in the data model translates toupdates in the UI component when the renderer code is run.

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ ListitemRenderer. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ ListItemRenderer. html#

Page 55: ZK 5 Essentials

The Final Listbox 52

The Final Listbox In the previous section, we saw how the renderer assigns UI into items of a Listbox [7] for UI presentation. Thissection explores the additional functionality surrounding the shopping cart view implementation.Finally we need to display a picture of the product which has been ordered on select.

Displaying an image when selecting the relevant orderThis functionality is the reason that the Listbox [7] was chosen for the particular task as it provides an<mp>onSelect</mp> event when the user selects a relevant item. In this case we would like to display an item’simage in a Image [5] component below the Listbox [7]. The ZUL file contains the following:Index.zul

<listbox>

…</listbox>

<textbox id="descTxb" rows="10" width="200px" value="Note for this order." />

<image id="cartItemImage" />

To capture the <mp>onSelect</mp> event we need to create a method with a specific signature. We use the eventname followed by a $ and followed by the component name. In addition the method should take the argument of typeSelectEvent [1]. In this case the method signature would be:

public void onSelect$shoppingCartListbox(SelectEvent event){

…}

Then we need retieve the relative item from the event using the SelectEvent.getSelectedItems() [2] method whichreturns the relevant selected items, in this case only one. The value is then retrieved and casted to a<mp>Cartitem</mp> and set as the <mp>cartitemImage’s</mp> source.

public void onSelect$shoppingCartListbox(SelectEvent event){

Listitem item = (Listitem) new

ArrayList(event.getSelectedItems()).get(0);

CartItem cartItem = (CartItem) item.getValue();

cartItemImage.setSrc(cartItem.getProduct().getImgPath());

}

We have explored how to use a Listbox [7]. The next section introduces databinding with the Grid [6].

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ event/ SelectEvent. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zk/ ui/ event/ SelectEvent. html#getSelectedItems()

Page 56: ZK 5 Essentials

Displaying Information in a Grid Using Data Binding 53

Displaying Information in a Grid Using DataBinding In the section Displaying Information Using Grid, we devised a renderer to associate the View (Product View Grid)with a data model. In this section, we'll look into how we could automate that process with ZK's annotated databinding mechanism.

The Concept of Data Binding ZK's annotated data binding mechanism involves the following players to make it work:• Data Bean• ZK UI Components declared in ZUL file• ZK's annotated data binding manager utilityIn a nutshell, a bean's particular property is associated with a specified component attribute, such that whenever avalue is modified, the annotated data binding manager calls the data bean's getter and setter methods to keep thevalues in sync between the bean and the component.The syntax for declaring this association in ZUML is

<component-name attribute-name="@{bean-name.attribute-name}"/>

A Basic Example of ZK Annotated Data BindingHere we walk through a basic annotated data binding sample step by step.

Prepare the Data Bean

Create a data oject "Person" with two properties:

public class Person {

private String _firstName = "";

private String _lastName = "";

private Boolean _married = true;

public Person(){

}

public Person(String firstName, String lastName, Boolean married){

_firstName = firstName;

_lastName = lastName;

_married = married;

}

// getter and setters

public void setFullName(String f) {

// do nothing

}

Page 57: ZK 5 Essentials

The Concept of Data Binding 54

public String getFullName() {

return _firstName + " " + _lastName;

}

}

Declare the data bean in ZUL file

Instantiate the Person class in zscript:

<window>

<zscript><![CDATA[

//prepare the person object

import bean.Person;

Person person = new Person();

person.setFirstName("Max");

person.setLastName("Planck");

]]>

</zscript>

// UI declaration

</window>

Activate the Annotated Data Binding Manager

We activate the data binding manager by declaring the page initiator, the initiator does the following automaticallyfor us:1. Create an instance of AnnotatedDataBinderInit [1].2. Sets the AnnotateDataBinder instance as a variable with the name "binder" stored in the component as specified

in arg0 "component-path"(if arg0 is not specified, use Page instead).3. Calls DataBinder.loadAll() to initiate all UI components from the associated data source.

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>

Declare Components for Annotated Data Binding

Now we declare the components in our ZUL file to apply the annotated data binding mechanism:

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>

<window>

<zscript><![CDATA[

//prepare the person object

import bean.Person;

Person person = new Person();

person.setFirstName("Max");

person.setLastName("Planck");

]]>

</zscript>

<grid width="400px">

<rows>

<row> First Name: <textbox value="@{person.firstName}"/></row>

<row> Last Name: <textbox value="@{person.lastName}"/></row>

<row> Full Name: <label value="@{person.fullName}"/></row>

Administrador
Highlight
Page 58: ZK 5 Essentials

The Concept of Data Binding 55

</rows>

</grid>

</window>

The result is a table with 3 rows, when user enters values in the textboxes and an onChange event is fired, the lablein the last row is updated instantly.

A Basic Example of Annotated Data Binding with a CollectionThe sample code below illustrates how to populate data using a Collection in a UI component:

<?page title="Data binding 5" contentType="text/html;charset=UTF-8"?>

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>

<window title="Data binding 5" border="normal">

<zscript><![CDATA[

//prepare the sample List

import bean.Person;

int count = 3;

List persons = new ArrayList();

for(int j= 1; j <= count; ++j) {

Person personx = new Person();

personx.setFirstName("Leohnard"+j);

personx.setLastName("Euler"+j);

persons.add(personx);

}

]]></zscript>

<listbox rows="4" model="@{persons}">

<listhead>

<listheader label="First Name" width="100px" />

<listheader label="Last Name" width="100px" />

<listheader label="Full Name" width="100px" />

</listhead>

<!-- define variable person here-->

<listitem self="@{each='person'}">

<listcell>

<textbox value="@{person.firstName}" />

</listcell>

<listcell>

<textbox value="@{person.lastName}" />

</listcell>

<listcell label="@{person.fullName}" />

</listitem>

</listbox>

Page 59: ZK 5 Essentials

The Concept of Data Binding 56

</window>

At line 2, we declare the initiator for the annotated data binder. From line 4 through 14, we prepare the datacollection, for this example, we dynamically generate a list of the Person data object and iteratively set the first andlast names for each. Since we are using the data collection to populate the Listbox [7] component, we use ZK'sannotated data binding syntax to assign it a data model (line 17); in this case, persons is the data collection weinstantiated earlier in zscript will be applied to the data binder. For each Listitem [4] (an listitem in listbox isanalogous to a row in grid), we assign each with a Person object and the object's attributes (first name, last name,full name) to each cell of the listitem. When this simple composition, we are able to populate the whole Listbox withour "Persons" data collection.Let's summarize what needs to be done for annotated data binding a UI component with a data collection:1. declare the initiator for annotated data binder (line 2)2. prepare the data collection (zscript is used in this sample, the Java code can be placed in an controller class

instead)3. annotate the UI component (Grid [6], Listbox [7]) for data binding with the data collection name (line 17)4. annotate the row element (Listitem [4] for Listbox [7]; Row [2] for Grid [6]) with the data object (Person) by

iterating through data object collection (Persons).5. annotate each cell in the row element with the respective data object property

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zkplus/ databind/ AnnotatedDataBinderInit. html#[2] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Row. html#

Page 60: ZK 5 Essentials

Implementing Data Binding 57

Implementing Data Binding In the previous sections, we implemented a "View-Model-Renderer" approach to populate tabular data incomponents (Grid [6], Listbox [7]). In this section, we explore how to leverage ZK's convenient annotated databinding to achieve the same end.

The Orders ViewIn the Orders View, we present users with all the records of the orders placed. The upper portion of the view,implemented using a Listbox [7], discloses information on the orders placed. When users click on an item in the list,the details pertaining to the products purchased in that order is shown in the grid below. Users could cancel an orderby clicking the button "Cancel Selected Order".

How Data Binding and Controller Work TogetherIn the previous section [1], we looked at how the controller works in the View-Model-Render approach. Usingannotated data binding, we no longer need to wrap a data collection with a ZK utility model class and implementinga renderer, therefore, we could simplify the code in the controller class: DatabindingOrderViewCtrl.java

public class DatabindingOrderViewCtrl extends GenericForwardComposer

implements OrderCtrl{

private static final String KEY_ORDER_VIEW_CTRL =

"KEY_ORDER_VIEW_CTRL";

private Listbox orderLibox;

private Button cancelOrderBtn;

@Override

public void doAfterCompose(Component comp) throws Exception {

super.doAfterCompose(comp);

desktop.setAttribute(KEY_ORDER_VIEW_CTRL, this);

cancelOrderBtn.setDisabled(true);

}

//no more model or renderer code needed

public List<Order> getOrders(){

List<Order> orders = getOrderDAO().findByUser(getCurrentUserId());

Page 61: ZK 5 Essentials

Implementing Data Binding 58

return orders;

}

private static OrderDAO getOrderDAO(){

return new OrderDAO();

}

public void onClick$cancelOrderBtn(){

if(orderLibox.getSelectedItem()==null){

return;

}

Order order = (Order)

orderLibox.getSelectedItem().getValue();

cancelOrder(order.getId());

}

public void onSelect$orderLibox(){

if(cancelOrderBtn.isDisabled())

cancelOrderBtn.setDisabled(false);

}

private void cancelOrder(Long orderId) {

//1. Do the update using DAO

getOrderDAO().cancelOrder(orderId);

//2. update UI

AnnotateDataBinder binder = (AnnotateDataBinder)

page.getAttribute("binder");

binder.loadAll();

}

}

• At line 11, we save this controller class as a desktop attribute so it could be retrieved anywhere within the desktopscope

• Since we'll need to supply the annotated data binder the data collection we'll use for the grid, we keep the code atline 17 so the data binder could call this code and fetch the data collection.

Now we proceed to apply data binding to the Orders View.

Data Binding Grid with a Data CollectionAn introduction on data binding with data collection was given in the previous section [2]. We'll apply that techniquehere:• At line 2, we apply our simplified controller class• At line 4, we assign the list orders from the controller class to the Listbox as its data model; the annotation

orderArea$composer.orders translates to "getting the parent Div component's controller class and run themethod getOrders" (the attribute "selectedItem" will be covered in the subsection below)

• At line 11, we iterate through the data collection and assign the order data object to each Listitem componentthat's been generated automatically.

Page 62: ZK 5 Essentials

Implementing Data Binding 59

• From line 12 through 14, we get the order object's properties and append it to the labels in the list cells. (theattribute "converter" will be covered in the subsection to follow)

index.zul

<south size="250px" flex="true" border="0" splittable="true" collapsible="true" style="overflow:scroll">

<div id="orderArea" style="background:#E6D92C; height:100%" apply="demo.web.ui.ctrl.DatabindingOrderViewCtrl" >

<listbox id="orderLibox" model="@{orderArea$composer.orders}" selectedItem="@{selectedOrder}">

<listhead>

<listheader label="info"/>

<listheader label="description"/>

<listheader label="Sub Total"/>

</listhead>

<listitem self="@{each='order'}" value="@{order}">

<listcell label="@{order, converter='demo.web.ui.OrderInfoTypeConverter'}" />

<listcell label="@{order.description}" />

<listcell label="@{order.total}" />

</listitem>

</listbox>

<grid id="orderItemsGrid" model="@{selectedOrder.items}">

<columns sizable="true">

<column label="Name"/>

<column label="Quantity"/>

<column label="Price"/>

<column label="Sub Total"/>

</columns>

<rows>

<row self="@{each='orderItem'}">

<label value="@{orderItem.name}"/>

<label value="@{orderItem.quantity}"/>

<label value="@{orderItem.price}"/>

<label value="@{orderItem, converter='demo.web.ui.OrderItemSubTotalTypeConverter'}" maxlength="8" />

</row>

</rows>

</grid>

<button id="cancelOrderBtn" label="Cancel Selected Order"/>

</div>

</south>

Converting Data Types When BindingIn Orders View we need to display the purchased date as a String, but the Order object gets us the Date [3] object only, not a String which could be attached to a label in listcell.

Page 63: ZK 5 Essentials

Implementing Data Binding 60

To convert Date to String, we'll need to implement the TypeConverter [4] interface.OrderInfoTypeConverter.java

package demo.web.ui;

import org.zkoss.zk.ui.Component;

import org.zkoss.zkplus.databind.TypeConverter;

import com.sun.jna.FromNativeContext;

import demo.model.OrderDAO;

import demo.model.bean.Order;

public class OrderInfoTypeConverter implements TypeConverter {

// Save

public Object coerceToBean(Object val, Component comp) {

throw new UnsupportedOperationException();

}

//Load

public Object coerceToUi(Object val, Component comp) {

Order order = (Order) val;

String info = order.getStatus()+" : "+

Consts.YYYY_MM_DD_hh_ss.format(order.getCreateDate());

return info;

}

}

There are two methods that we must implement, one is coerceToBean (converting data type and save to bean), theother is coerceToUi (converting data type and load to UI component). In our case, we have the Date object in beanand need to convert that to String and display it in an UI component, so we implement the coerceToUi method asshown in the snippet above.In our UI markup, index.zul, we then include the converter in the databinding annotation as such:

<listcell label="@{order, converter='demo.web.ui.OrderInfoTypeConverter'}" />

Page 64: ZK 5 Essentials

Implementing Data Binding 61

Getting and Passing a Selected List Item in ZULListbox [7] differs from Grid [6] in that it supports the method Listbox.getSelectedItem() [5]. We summarize the keypoints behind how this works below:1. We could call Listbox.getSelectedItem() [5] in ZUL (line 4) using annotations to retrieve the list item selected:

selectedItem="@{selectedOrder}"

1. here selectedOrder is just an arbitrary variable we declare to reference the Order data object2. At line 18, we call the Order object's getItems method to retrieve the list of "OrderItem" data objects and assign

that list to the grid component as its model.1. OrderItem is a wrapper for the Product object, with additional information like the quantity being ordered,

the price, and the sub total.3. At line 26, we associate each row with each OrderItem; a row is created automatically for each OrderItem4. From line 27 through 30, the getter methods for the OrderItem's properties are called and their values are

assigned to the labels.As it's illustrated here, ZK's data binder automatically does a lot of wiring work for us behind the scenes. In the nextsubsection, we proceed to discuss when is it a good idea to implement data binding and when it is not.

When to Use Data BindingAs a general rule of thumb, use data binding when:• the components do not need to be dynamically created (eg. components created using

Executions.createComponents())• the data in grid / listbox can be easily fetched using getter methods of the associated data object

References[1] http:/ / books. zkoss. org/ wiki/ ZK_Essentials/ Displaying_information_using_the_Listbox/ Using_a_ListModel_and_ListitemRenderer[2] http:/ / books. zkoss. org/ wiki/ ZK_Essentials/ Displaying_Information_in_a_Grid_Using_Data_Binding/ The_Concept_of_Data_Binding[3] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ java/ util/ Date. html#[4] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zkplus/ databind/ TypeConverter. html#[5] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zul/ Listbox. html#getSelectedItem()

Page 65: ZK 5 Essentials

Working with ZK and databases 62

Working with ZK and databases This section guides us through the process of re-implementing sections of our application to make use of persistentstorage using Hibernate.

The Theory of Using ZK with Databases ZK is predominantly a server centric framework thus developers are not required to leverage any special mechanismto transfer data from the server to the client.Fundamentally, as discussed in previous sections, data is provided to the view using a model which is a collectiontype, usually a <mp>List</mp>. For detailed information please click here.The sequence of displaying the data in the view is shown below.

With ZK handling the transfer of data to the client the process is substantially easier. A ZK developer is able toleverage any application or ORM framework such as Spring and Hibernate respectively without needing to performany special task.If you are familiar with Hibernate you do not need to read any further as a the standard List of objects retrieved fromORM frameworks is compatible with ZK's model concept. Thus using the knowledge we gained in previous sectionsyou can construct your application.This chapter introduces those unfamiliar with ORM framworks to Hibernate and ZK. The following sections providea simple tutorial on refactoring our current application to make use of persistent storage.

Page 66: ZK 5 Essentials

Using Hibernate with ZK 63

Using Hibernate with ZK As established previously, the applications DAOs access an "in-memory" model provided by Java Lists. We arerequired to adjust the DAOs so they access a persistent model powered by HSQLDB using Hibernate.Hibernate is an ORM framework of choice for many large enterprises as it provides an easy way to access persistentstorage. Hibernate can be combined with Spring and EJB3 to make the mangement of application lifecycles andsession trivial providing greater flexibility for developers. In this example only Hibernate will be used, however,there are many examples of using Hibernate along with Spring available on the web.HSQLDB is a relational database engine written in Java which provides an easy way to persist data to a file store.

The Required LibrariesTo get started the following libraries are required for a ZK Hibernate application with HSQLDB. When testing outthe sample application provided with this book chapter you can ignore the below details as the libraries are providedin the WAR file along with the sample. For those of you who would like to start your own project the essentiallibraries required are.• Hibernate 3.6• ZK 5.0.5• HSQLDB jarHere is a screenshot of the jar files found in the sample application for this chapter.

Page 67: ZK 5 Essentials

Using Hibernate with ZK 64

Setting up HibernateHibernate requires configuration to work. Our sample application contains two configuration files placed in folderincluded in the classpath:1. log4j.properties 2. hibernate.cfg.xmlThe log4j.properties file is used to inform Log4j of the level that we wish to log. In our case we set the lowest levelof logging possible which in this case is DEBUG and TRACE for the hibernate classes. Setting this to such a finegrained setting enables us to see exactly what is going on in hibernate.The second file hibernate.cfg.xml contains detailed configuration for Hibernate in XML format. The content isprovided and analyzed below.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>

<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>

<property name="hibernate.connection.url">jdbc:hsqldb:file:data/store</property>

<property name="hibernate.connection.username">sa</property>

<property name="hibernate.show_sql">true</property>

<property name="hibernate.current_session_context_class">thread</property>

<property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>

<property name="hibernate.hbm2ddl.auto">create-drop</property>

<mapping class="demo.model.bean.Order"/>

<mapping class="demo.model.bean.OrderItem"/>

<mapping class="demo.model.bean.User"/>

<mapping class="demo.model.bean.Product"/>

</session-factory>

</hibernate-configuration>

• Line 5 let’s hibernate know that we intend to use HSQLDialect as it is an HSQL database• Line 6 specifies the jdbc driver class• Line 7 is the path to the datastore, in this case informing HSQLDB we will make use of a file named store in the

folder data• Line 8 is the username, in this case a default sa• Line 9 dictates that we would like Hibernate to print out the SQL• Line 10 states that the session context is thread based• Line 11 states that the HQL style we would like to use is classic

• HQL is Hibernates own query language for more information please click here [1]

• Lines 14-19 are to do with definition of the entity types within the application and generation of the database.These topics are covered in the following section.

Page 68: ZK 5 Essentials

Using Hibernate with ZK 65

References[1] http:/ / docs. jboss. org/ hibernate/ core/ 3. 3/ reference/ en/ html/ queryhql. html

Hibernate, Entities and Database Generation Hibernate persists Objects to the database. To perform this task we need two things, a database schema and a set ofmapped classes. In the previous section we explored the Hibernate configuration file and highlighted the followinglines:

<property name="hibernate.hbm2ddl.auto">create-drop</property>

<mapping class="demo.model.bean.Order"/>

<mapping class="demo.model.bean.OrderItem"/>

<mapping class="demo.model.bean.User"/>

<mapping class="demo.model.bean.Product"/>

One of the most important properties in this XML file is “hibernate.hbm2ddl.auto” set as “create-drop”. When set tocreate the option will create exports the schema DDL to the database when Hibernate’s SessionFactory is created.This is very useful when developing a data driven application as it eliminates the need to manually update SQLscripts when your schema needs to change. However, this setting is not recommended for production usage.NOTE: As the database schema is generated and dropped at the beginning and end of every session this means thatthe data is not persisted past the end of the application. By changing this to update the data will be persisted acrossmultiple runs.The other properties enable the mapping of Java classes to Database tables. In general, this mapping is declared intwo ways:• By providing the class name using the attribute <mp>class</mp>• By providing a URI to an XML resource which describes the mappingMapping by XML or annotation achieve the same goal and the implementation method depends on developerpreference. Some developers prefer XML, some prefer annotations. In this case we chose to use annotations.

Using Hibernate AnnotationsWhen instructing Hibernate that the class is an Entity which should be persisted the annotation is placed above theclass declaration. For property declarations annotations can be placed directly above the field or on the getter of theproperty.There are varying opinions on which is better and why, however, in this case we have chosen to place the annotationon the field value as it is clearer for demonstration purposes. The following is the <mp>Product</mp> class whichhas been annotated.

@Entity

@Table(name="products")

public class Product {

@Id

@GeneratedValue(strategy=GenerationType.AUTO)

private long id;

Page 69: ZK 5 Essentials

Hibernate, Entities and Database Generation 66

@Column(name="productname")

private String name;

@Temporal(TemporalType.TIMESTAMP)

private Date createDate;

private float price;

private int quantity;

private boolean available;

private String imgPath;

…}

The above code demonstrates how the <mp>Product</mp> class was annotated to allow persistence. Taking theannotations one at a time we will explore what they do.

@Entity

An entity is a lightweight persistence domain objects representing a table in a database. In this case we let Hibernateknow that the class Product is an entity. This is required for classes you would like to persist to the database.

@Table(name="products")

The table entity is set at the class level and enables us to define the table, catalog and schema names of the entitymappings. If names are not specified then the default values are used, however, in our case Product is an SQLreserved word therefore we change the table name to products.

@Id

We need to let Hibernate know which field of ours id the ID, this is easily achieved by applying the annotation @Id.

@GeneratedValue(strategy=GenerationType.AUTO)

Along with the annotation, @Id, we also need to inform Hibernate that it is auto-incremented by the database. We letHibernate know using the @GeneratedValue annotation and setting the strategy to GenerationType AUTO.

@Column(name="productname")

The next annotation refers to the definition of a column. Under normal circumstances we do not need to provide aname however, in this case without specifying the name of the column it would default to "name." Just as "product","name" is also an SQL reserved keyword hence we specify a valid column name, "productname".

@Temporal(TemporalType.TIMESTAMP)

Java APIs do not define the temporal precision of time. When placing data into persistent storage we would like todescribe the expected precision. To do this we use the Temporal attribute. Types include DATE, TIME andTIMESTAMP.The rest of the classes in our example use the same annotation strategies. There is only one exception present inOrder.java which describes the relationship between an <mp>Order</mp> and its <mp>OrderItems</mp>.

Page 70: ZK 5 Essentials

Hibernate, Entities and Database Generation 67

Creating the Relationship - Linking TableAn <mp>Order</mp> has a one-to-many relationship with <mp>OrderItems</mp>, to map this relationship we arerequired to introduce a linking table named <mp>OrderedItems</mp>. This relationship is shown below:

In order for Hibernate to generate the database schema and map the relationship correctly we need to describe it. Todo this we use two annotations:• @OneToMany• @JoinTableLet’s explore the relative code.

@OneToMany

@JoinTable(

name="OrderedItems",

joinColumns=@JoinColumn(name="orderid"),

inverseJoinColumns=@JoinColumn(name="orderitemid")

)

@LazyCollection(value=LazyCollectionOption.FALSE)

private List<OrderItem> items = new ArrayList<OrderItem>();

The "name" attribute tells Hibernate the table name which we would like to use or in our case create.The "joinColumns" attribute requires the foreign key columns of the join table which reference the primary table ofthe entity owning the association, in this case the order id. On the other hand the "inverseJoinColumns" attributerequires the foreign key columns of the join table which reference the primary table of the entity that does not ownthe association, in this case the OrderItem’s id.We provide both attributes a "@joinColumn" annotation requires the "name" and "referencedColumnName"which are the name of the column in the table OrderedItems and the name of the referenced column within the entityrespectively.The <mp>Order</mp> owns the association (ie. Owns the Order items) so its key is passed to "joinColumns" and<mp>OrderItem</mp> does not own the association so its information is passed to "inverseJoinColumns."

Page 71: ZK 5 Essentials

Hibernate, Entities and Database Generation 68

Lazy LoadingThere is one last thing to consider; when an <mp>Order</mp> object is loaded we want to load its<mp>OrderItems</mp> at the same time. Hibernate only loads the first object level which can lead to exceptionssuch as a LazyLoadException when we access the item list and it has not been initialized. Meaning when the Orderobject is loaded then the its OrderItems aren’t.In this case it is easy to fix by making use of the @LazyCollection annotation and setting the option to FALSE:

@LazyCollection(value=LazyCollectionOption.FALSE)

This will ensure that when an <mp>Order</mp> is loaded its <mp>OrderItems</mp> are too. When designinglarger systems we have to take into account how much data should be loaded and whether we should follow lazyloading practices or not. For the purposes of this chapter lazy loading is not required.The final section introduces Hibernate Session management and how we implemented the DAOs.

Hibernate Session Management andImplementing the DAOs As discussed earlier we are not making use of an EJB3 container nor Spring therefore are required to manage thesession ourselves. This involves building a SessionFactory object when the application loads, closing it when theapplication ends and manually opening and closing sessions when required.

The SessionFactory and the HibernateUtilA common pattern in Hibernate is to make use of a <mp>HibernateUtil</mp>. This is a class which providesfunctionality to build and access our <mp>SessionFactory</mp>. The following code compromises our<mp>HibernateUtil</mp>:

public class StoreHibernateUtil {

private static final SessionFactory sessionFactory;

static {

try {

// Create the SessionFactory from standard

(hibernate.cfg.xml)

// config file.

sessionFactory = new

Configuration().configure().buildSessionFactory();

} catch (Throwable ex) {

// Log the exception.

System.err.println("Initial SessionFactory creation

failed." + ex);

throw new ExceptionInInitializerError(ex);

}

}

public static SessionFactory getSessionFactory() {

Page 72: ZK 5 Essentials

Hibernate Session Management and Implementing the DAOs 69

return sessionFactory;

}

public static Session openSession() {

return sessionFactory.openSession();

}

}

In this class the SessionFactory is built statically upon first accessing the object and then provides static utilitymethods to access the SessionFactory and open a new Session.We are required to build the SessionFactory when the application loads and close it when the application terminates.To do this we implement two ZK interfaces, WebAppInit and WebAppCleanup and specify the implementing classin the zk.xml file:

public class HibernateListeners implements WebAppInit, WebAppCleanup {

public void init(WebApp webapp) throws Exception {

//initialize Hibernate

StoreHibernateUtil.getSessionFactory();

}

public void cleanup(WebApp webapp) throws Exception {

//Close Hibernate

StoreHibernateUtil.getSessionFactory().close();

}

}

<zk>

<listener>

<listener-class>demo.model.HibernateListeners</listener-class>

</listener>

</zk>

In this case we named our class <mp>HibernateListeners</mp> and made sure that the <mp>SessionFactory</mp>was built on initialization of the web application and closed in the cleanup method.This initializes and closes Hibernate now we need to make use of it in the DAOs.

Re-implementing the DAOs using HibernateIn this section we are going to explore the general usage of Hibernate in our DAOs for the majority of use cases. Weopen and close one when performing any database interaction. Hibernate is centered around Session and Transactionconcept where a session can have many transactions, commiting and rolling them back from the session as needed.In this example there will only be one Transaction per session due to the simplicity of the use case. However, it isentirely possible to have a session which which span all the transactions of a user. For more information on Sessionsand Transactions in Hibernate please click here [1].Let’s take a simple use case for retrieving all the available <mp>Products</mp> as found in<mp>ProductDAO.java</mp>:

Page 73: ZK 5 Essentials

Hibernate Session Management and Implementing the DAOs 70

public List<Product> findAll(){

//return new ArrayList<Product>(dbModel.values());

Session session = StoreHibernateUtil.openSession();

Query query = session.createQuery("from products");

List<Product> products = query.list();

session.close();

return products;

}

In this code snippet we utilize our <mp>HibernateUtil</mp> to open a new session at line 3 and then create a query.The query is written in HQL (Hibernate Query Language) retrieving all the rows from the table products. For moreinformation on HQL please click here [1]. Once we have created the Query object we can use its list method toretrieve the <mp>List</mp> of products, close the session then return.In the same DAO sometimes we need to retrieve all available <mp>Products</mp>. This means we need to retrieveall the Products where available is equal to true. In our example we do this by creating a Criteria object:

public List<Product> findAllAvailable(){

Session session = StoreHibernateUtil.openSession();

Transaction t = session.beginTransaction();

Criteria criteria =

session.createCriteria(Product.class).add(Restrictions.eq("available",

true));

List<Product> products = criteria.list();

t.commit();

session.close();

return products;

}

The snippet follows the same session management strategy, however, this time we create a <mp>Criteria</mp>object adding a restriction that "available" must be true. Then we can use the method <mp>criteria.list()</mp> toretrieve a list of products which are available.The retrieval methods in each DAO follow a similar strategy so finally let’s take a look at the add method of the<mp>OrderDAO</mp> which persists an <mp>Order</mp>.

public void add(Order order){

Session session = StoreHibernateUtil.openSession();

Transaction t = session.beginTransaction();

session.persist(order);

t.commit();

session.close();

}

Page 74: ZK 5 Essentials

Hibernate Session Management and Implementing the DAOs 71

We see that the Session management strategy is exactly the same, however, now we use the session’s persist functionto add the <mp>Order</mp> object to the session, then we commit the transaction and close the session. This willthen add the Order object to the relative table.

References[1] http:/ / community. jboss. org/ wiki/ sessionsandtransactions

Hibernate Summary As demonstrated by this tutorial Hibernate is highly configurable and very powerful. This chapter covered the verybasic annotations and usage of Hibernate, therefore when employing the power of Hibernate for a larger applicationwe should further explore Hibernate's options such as not allowing null values for certain table columns. For acomplete list of Hibernate's annotations please click here [1].

References[1] http:/ / docs. jboss. org/ hibernate/ annotations/ 3. 5/ reference/ en/ html_single/

Summary and Further Readings We glimpsed into the fundamental principles behind how ZK works and we employed some of the essential featuresof ZK to build a sample shopping cart applications in this book. Let's recap on these elements in ZK:

Components• Components are UI elements that an application developer piece together to build the application UI, think

LEGO. Consult ZK_Component_Reference guide on what children components a particular component canhave.

• Components can be declared in ZUML (ZK User Interface Markup Language, in XML syntax), oralternatively, in Java.

• Components (POJO) run on JVM at the server, and they have their counter parts (widgets - JS objects) at theclient.

• User activities on widgets are reflected to the components at the server; component updates are reflected backto the widgets at client.

• A Page [9] is a "stage" where components come on and off it to play their parts and fulfill their roles.• Components are conceptually grouped in ID Spaces; we can call the getFellow() [8] method on one component

to get another component as long as they are in the same ID Space.• By default, components declared in Window [1] form an ID Space (including Window [1] itself) with Window

[1] being the ID Space Owner.• By default, a Page [9] is an ID Space Owner; any component can become the ID Space Owner by

implementing IdSpace [10]

Page 75: ZK 5 Essentials

Summary and Further Readings 72

Events• User activities (eg. onClick) and system notifications (eg. server push) are abstracted to event objects.• Register event listeners on components so event objects can be created and forwarded.• By default, all events are sent to the server for processing.• With ZK's Server+Client Fusion architecture, events could also be handled at the client directly.• Event handling code can be declared as a component attribute in ZUL.• Events can be forwarded to a controller class for handling.• Event listeners can be added dynamically in Java.

ZK MVC• The ZK MVC approach provides a great separation among data (aka. model), UI and business logic (aka.

control).• Under the ZK MVC pattern, UI components are declared with ZUML in ZUL files and tasks such as setting a

component's data model and renderer, component manipulation, are implemented in a Controller class in Java• The controller class should extend GenericForwardComposer [1] so components declared in ZUL can be

referenced in Java code and events are automatically forwarded to the controller class for handling.

Data Display in UI: View-Model-Renderer• The View-Model-Renderer approach facilitates the display of a data collection in a component such as a Grid

[6] or Listbox [7].• The View-Model-Renderer approach provides a great separation between data and UI.• The Model is a wrapper for a Java Collection which serves as an interface between the ZK framework and the

data collection. For example, ListModelList [2] takes a list as its argument and allows the framework to accessand manipulate data objects within the collection.

• The Renderer provides a set of instructions for associating a bean and bean's properties to UI components.

Annotated Data Binding• Annotated Data Binding provides a great separation between data and UI.• Annotated Data Binding allows bean properties to be declared as component attribute values so that View and

Model are bound automatically without the need to specify a Renderer or creating a Model wrapper explicitly.• Under the hood, data binder calls a bean's getter and setter methods to retrieve, or set values in UI components.• Data binding works with ZK MVC as such:

• Controller class provides a getter method to obtain the bean, or Collection.• Declare the bean, or Collection, as the value for a UI component in ZUL, and the data binder will call the

Controller class' getter method to append data to UI.• By implementing the TypeConverter [4] interface, data type can be converted between UI component and data

model when data binding occurs.

Page 76: ZK 5 Essentials

Summary and Further Readings 73

Gaining a Deeper UnderstandingTo strengthen the concepts we learned in this book, please refer to the following links:

• ZK Developer's Reference/UI Composing• ZK Developer's Reference/Event Handling• ZK Developer's Reference/Databinding• ZK Developer's Reference/MVC• Small Talk: ZK MVC Made Easy

Other ZK Features that Make Things Easier and More FunMaterial in this book touched bases on the essentials of ZK application development. Other important conceptscrucial to really leveraging the benefits that ZK brings to Ajax application development includes:

• ZK Client-side Reference/General Control/Event Listening• ZK Developer's Reference/UI Composing/Macro Component

Performance TipsPlease follow these guidelines for building performance critical enterprise applications:

• ZK Developer's Reference/Performance Tips

References[1] http:/ / www. zkoss. org/ javadoc/ latest/ zk/ org/ zkoss/ zki/ ui/ util/ GenericForwardComposer. html#

Page 77: ZK 5 Essentials

Article Sources and Contributors 74

Article Sources and ContributorsZK_Essentials  Source: http://books.zkoss.org/index.php?title=ZK_Essentials  Contributors: Tmillsclare

Introduction  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Introduction  Contributors: Tmillsclare

An Introduction to ZK's Server client Fusion Architecture  Source:http://books.zkoss.org/index.php?title=ZK_Essentials/Introduction_to_ZK/An_Introduction_to_ZK%27s_Server_client_Fusion_Architecture  Contributors: Sphota, Tmillsclare, Tomyeh

Component Based UI  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Introduction_to_ZK/Component_Based_UI  Contributors: Sphota, Tmillsclare, Tomyeh

Event Driven Programming  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Introduction_to_ZK/Event_Driven_Programming  Contributors: Sphota

Working with the Sample Applications  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_the_Sample_Applications  Contributors: Sphota

The Resources  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_the_Sample_Applications/The_Resources  Contributors: Sphota, Tmillsclare

Setting Up the Applications Using Eclipse  Source:http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_the_Sample_Applications/Setting_Up_the_Applications_Using_Eclipse  Contributors: Sphota, Tomyeh

Store  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_the_Sample_Applications/Setting_Up_the_Applications_Using_Eclipse/Store  Contributors: Sphota

Store with a Database  Source:http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_the_Sample_Applications/Setting_Up_the_Applications_Using_Eclipse/Store_with_a_Database  Contributors: Tmillsclare

Laying out Your ZK Components  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Laying_out_Your_ZK_Components  Contributors: Sphota, Tmillsclare

How to Layout Components  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Laying_out_Your_ZK_Components/How_to_Layout_Components  Contributors: Sphota, Tomyeh

Using ZK Borderlayout  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Laying_out_Your_ZK_Components/Using_ZK_Borderlayout  Contributors: Sphota

Handling the Login Process using ZK MVC and Sessions  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Handling_the_Login_Process_using_ZK_MVC_and_Sessions Contributors: Tmillsclare

The Basic Login  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Handling_the_Login_Process_using_ZK_MVC_and_Sessions/The_Basic_Login  Contributors: Tmillsclare

Implementing ZK MVC  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Handling_the_Login_Process_using_ZK_MVC_and_Sessions/Implementing_ZK_MVC  Contributors:Ashishd, Tmillsclare

Managing credentials using ZK Sessions  Source:http://books.zkoss.org/index.php?title=ZK_Essentials/Handling_the_Login_Process_using_ZK_MVC_and_Sessions/Managing_credentials_using_ZK_Sessions  Contributors: Tmillsclare

Displaying Information Using Grid  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_Information_Using_Grid  Contributors: Sphota

Implementing the View  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_Information_Using_Grid/Implementing_the_View  Contributors: Sphota

Using a ListModel and RowRenderer  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_Information_Using_Grid/Using_a_ListModel_and_RowRenderer Contributors: Sphota

The Final Grid  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_Information_Using_Grid/The_Final_Grid  Contributors: Sphota

Displaying information using the Listbox  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_information_using_the_Listbox  Contributors: Tmillsclare

Implementing the View  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_information_using_the_Listbox/Implementing_the_View  Contributors: Tmillsclare

Using a ListModel and ListitemRenderer  Source:http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_information_using_the_Listbox/Using_a_ListModel_and_ListitemRenderer  Contributors: Tmillsclare

The Final Listbox  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_information_using_the_Listbox/The_Final_Listbox  Contributors: Tmillsclare

Displaying Information in a Grid Using Data Binding  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_Information_in_a_Grid_Using_Data_Binding  Contributors:Sphota

The Concept of Data Binding  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_Information_in_a_Grid_Using_Data_Binding/The_Concept_of_Data_Binding Contributors: Sphota

Implementing Data Binding  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Displaying_Information_in_a_Grid_Using_Data_Binding/Implementing_Data_Binding Contributors: Sphota

Working with ZK and databases  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_ZK_and_databases  Contributors: Tmillsclare

The Theory of Using ZK with Databases  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_ZK_and_databases/The_Theory_of_Using_ZK_with_Databases Contributors: Tmillsclare

Using Hibernate with ZK  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_ZK_and_databases/Using_Hibernate_with_ZK  Contributors: Tmillsclare

Hibernate, Entities and Database Generation  Source:http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_ZK_and_databases/Hibernate%2C_Entities_and_Database_Generation  Contributors: Tmillsclare

Hibernate Session Management and Implementing the DAOs  Source:http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_ZK_and_databases/Hibernate_Session_Management_and_Implementing_the_DAOs  Contributors: Tmillsclare

Hibernate Summary  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Working_with_ZK_and_databases/Hibernate_Summary  Contributors: Tmillsclare

Summary and Further Readings  Source: http://books.zkoss.org/index.php?title=ZK_Essentials/Summary_and_Further_Readings  Contributors: Gap77, Sphota, Tomyeh

Page 78: ZK 5 Essentials

Image Sources, Licenses and Contributors 75

Image Sources, Licenses and ContributorsImage:architecture-s.png  Source: http://books.zkoss.org/index.php?title=File:Architecture-s.png  License: unknown  Contributors: TomyehImage:ZKEssentials_Intro_Hello.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_Hello.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_AjaxZUL.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_AjaxZUL.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_ZULSample.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_ZULSample.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_ZULtoPOJO.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_ZULtoPOJO.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_MultiPage.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_MultiPage.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_HelloGoodbye.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_HelloGoodbye.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_IDSpace.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_IDSpace.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_Goodbye.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_Goodbye.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_EventReq.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_EventReq.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_EventRes.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_EventRes.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_EventInRes.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_EventInRes.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_onClick.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_onClick.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_HelloBtn.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_HelloBtn.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_GoodbyeBtn.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_GoodbyeBtn.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_WorldBtnEvent.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_WorldBtnEvent.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Intro_HelloDetached.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Intro_HelloDetached.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Setup_ZKStudio.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Setup_ZKStudio.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Setup_ActivateZKStudio.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Setup_ActivateZKStudio.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Setup_ZKJars.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Setup_ZKJars.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Setup_NewProj.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Setup_NewProj.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Setup_CreateProj.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Setup_CreateProj.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Setup_ImportFileSystem.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Setup_ImportFileSystem.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Setup_ImportSample.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Setup_ImportSample.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Setup_OverwriteFiles.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Setup_OverwriteFiles.png  License: unknown  Contributors: SphotaFile:ZKEss_import.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_import.png  License: unknown  Contributors: TmillsclareFile:ZKEss_war_import.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_war_import.png  License: unknown  Contributors: TmillsclareFile:ZKEss_war_import_final.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_war_import_final.png  License: unknown  Contributors: TmillsclareFile:ZKEss_imported.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_imported.png  License: unknown  Contributors: TmillsclareFile:ZKEss_many_problems.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_many_problems.png  License: unknown  Contributors: TmillsclareFile:ZKEss_annotations_1.5.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_annotations_1.5.png  License: unknown  Contributors: TmillsclareFile:ZKEss_project_compliance.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_project_compliance.png  License: unknown  Contributors: TmillsclareFile:ZKEss_facet_error.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_facet_error.png  License: unknown  Contributors: TmillsclareFile:ZKEss_change_facet.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_change_facet.png  License: unknown  Contributors: TmillsclareImage:ZKEssentials_Layout_Wireframe.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Layout_Wireframe.png  License: unknown  Contributors: SphotaImage: ZKEssentials_Layout_BorderFrames.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Layout_BorderFrames.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Layout_Borders.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Layout_Borders.png  License: unknown  Contributors: SphotaImage:ZKEssentials_Layout_FinalizedLayout.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_Layout_FinalizedLayout.png  License: unknown  Contributors: SphotaFile:ZKEss_LoginUsecase.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_LoginUsecase.png  License: unknown  Contributors: TmillsclareImage:ZKEssentials_DisplayInGrid_ProductView.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_DisplayInGrid_ProductView.png  License: unknown  Contributors:SphotaImage:simple_grid.png  Source: http://books.zkoss.org/index.php?title=File:Simple_grid.png  License: unknown  Contributors: SphotaImage:grid_configuration.png  Source: http://books.zkoss.org/index.php?title=File:Grid_configuration.png  License: unknown  Contributors: SphotaImage:ZKEssentials_DisplayInGrid_ViewModelRenderer.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_DisplayInGrid_ViewModelRenderer.png  License: unknown Contributors: SphotaFile:ZKEss_shopping_cart.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_shopping_cart.png  License: unknown  Contributors: TmillsclareFile:ZKEss_list.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_list.png  License: unknown  Contributors: TmillsclareFile:ZKEss_select.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_select.png  License: unknown  Contributors: TmillsclareFile:ZKEss_columns.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_columns.png  License: unknown  Contributors: TmillsclareFile:ZKEss_model.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_model.png  License: unknown  Contributors: TmillsclareImage: ZKEssentials_DisplayInGrid_BasicDataBinding.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_DisplayInGrid_BasicDataBinding.png  License: unknown Contributors: SphotaImage:ZKEssentials_DisplayInGrid_DatabindingCollection.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_DisplayInGrid_DatabindingCollection.png  License:unknown  Contributors: SphotaImage:ZKEssentials_DataBinding_OrdersView.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_DataBinding_OrdersView.png  License: unknown  Contributors:SphotaImage:ZKEssentials_DisplayInGrid_OrdersList.png  Source: http://books.zkoss.org/index.php?title=File:ZKEssentials_DisplayInGrid_OrdersList.png  License: unknown  Contributors:SphotaFile:ZKEss_view_seq.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_view_seq.png  License: unknown  Contributors: TmillsclareFile:ZKEss_all_libs.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_all_libs.png  License: unknown  Contributors: TmillsclareFile:ZKEss_linking_table.png  Source: http://books.zkoss.org/index.php?title=File:ZKEss_linking_table.png  License: unknown  Contributors: Tmillsclare