Basic Concepts"

From Documentation
Line 71: Line 71:
  
 
===How ZUML and Java work together===
 
===How ZUML and Java work together===
For best practice, [[The_zk_user_interface_markup_language | ZUML]] takes care of UI layout, and Java takes care of everything else.
+
For best practice, [http://books.zkoss.org/wiki/ZK_ZUML_Reference/The_ZK_User_Interface_Markup_Language ZUML] takes care of UI layout, and Java takes care of everything else.
  
 
Actually, you can write java code in ZUML, which is called <tt>zscript</tt>. And you can add/remove GUI component in pure java file too. To the extreme, you can do everything using only ZUML, or using only Java. However, using only ZUML, you'll lack the ability of step-by-step debugging. It will also entangle views with codes, which will be hard to maintain. On the other hand, using only java, it's tedious to write codes to create component and to append it to DOM tree.
 
Actually, you can write java code in ZUML, which is called <tt>zscript</tt>. And you can add/remove GUI component in pure java file too. To the extreme, you can do everything using only ZUML, or using only Java. However, using only ZUML, you'll lack the ability of step-by-step debugging. It will also entangle views with codes, which will be hard to maintain. On the other hand, using only java, it's tedious to write codes to create component and to append it to DOM tree.

Revision as of 03:28, 22 July 2010

Stop.png This documentation is for an older version of ZK. For the latest one, please click here.



Architecture Overview

ZK includes an AJAX-based mechanism to automate interactivity, a rich set of XUL (XML User Interface Language)-based components to enrich usability, and a markup language to simplify development.

The AJAX-based mechanism consists of three parts as depicted below: the ZK loader, the ZK AU (Asynchronous Update) Engine and the ZK Client Engine.

ZK architecture.jpg

Based on the user's request, the ZK Loader loads a ZK page, interprets it, and renders the result into HTML pages in response to URL requests. A ZK page is written in a markup language called ZUML (Zk User interface Markup Language). ZUML, like HTML, describes what components to create and how to represent them visually. These components, once created, remain available until the session expires.

The ZK AU Engine and the ZK Client Engine then work together as pitcher and catcher. They deliver events happening in the browser to the application running at the server, and update the DOM tree at the browser based on how components are manipulated by the application. This is the so-called event-driven programming model.

Execution Flow

  1. When a user types a URL or clicks a hyperlink at the browser, a request is sent to the Web server. If the request URL matches ZK's configured URL pattern ([1]), the ZK loader is then invoked to serve this request.
  2. ZK loader loads the specified page and interprets it to create proper components accordingly.
  3. After interpreting the whole page, ZK loader renders the result into a HTML page. The HTML page is then sent back to the browser accompanied with ZK Client Engine[2].
  4. ZK Client engine sits at the browser to detect any event triggered by user's activity such as moving mouse or changing a value. Once detected, it notifies ZK AU Engine by sending a ZK request[3].
  5. Upon receiving ZK requests from Client Engine, AU Engine updates the content of corresponding component, if necessary. And then, AU Engine notifies the application by invoking relevant event handlers, if any.
  6. If the application chooses to change content of components, add or move components, AU Engine send the new content of altered components to Client Engine by use of ZK responses.
  7. These ZK responses are actually commands to instruct Client Engine how to update the DOM tree accordingly.

Notes

  1. see Appendix A in the Developer's Reference
  2. ZK Client Engine is written in JavaScript. Browsers cache ZK Client engine, so the engine is usually sent only once at the first visit.
  3. ZK requests are special AJAX requests. However, for the mobile edition, ZK requests are special HTTP requests.

The Life cycle of Loading Pages

It takes four phases for ZK loader to load and interpret a ZUML page.

The Page Initial Phase

In this phase, ZK processes the processing instructions, called init. If none of such processing instructions are defined, this phase is skipped.

The Page Creation Phase

In this phase, ZK loader interprets an ZUML page. It creates and initializes components accordingly.

The Event Processing Phase

In this phase, ZK invokes each listener for each event queued for this desktop one-by-one. Only onCreate event is handled in this phase.

The Rendering Phase

After all events are processed, ZK renders these components into a regular HTML page and sends this page to the browser.

The Life cycle of Updating Pages

It takes three phases for ZK AU Engine to process the ZK requests sent from the clients: the Request Processing Phase, the Event Processing Phase, and the Rendering Phase.

ZK AU Engine pipelines ZK requests into queues on a basis of one queue per desktop. Therefore, requests for the same desktop are processed sequentially. Requests for different desktops are processed in parallel.

The Request Processing Phase

Depending on the request, ZK AU Engine might update the content of affected components such that their content are the same as what are shown at the client.
Then, it posts corresponding events to the queue.

The Event Processing Phase

This phase is the same as the Event Processing Phase in the Component Creation Phase. It processes events one-by-one in an independent thread.

The Rendering Phase

After all events are processed, ZK renders affected components, generates corresponding ZK responses, and sends these responses back to the client. Then, Client Engine updates the DOM tree at the browser based on the responses.
Whether to redraw the whole visual presentation of a component or to update an attribute at the browser all depend on the implementation of components. It is the job of component developers to balance between interactivity and simplicity.

Event Handling

Events are fired to the target components. For example, if you click a button , an onClick event is fired to the button . Then button can handle the event itself, or forward the event to other component like window . You can also use Events.postEvent() to post an event using code, and you can use addEventListener to register an event handler in Java. You can easily implement MVC pattern with ZK. Please refer to Chapter. event listening & processing for detail explanation.

Summary

Always keep in mind, ZK is server centric. Any java code you write, is executed in server side. Any event happened in client side, is sent back to server to handle. ZK is event driven architecture.

Markup Language or Pure Java

ZK User Interface Markup Language (ZUML)

The ZK User Interface Markup Language (ZUML) is based on XML. You can use it to layout the GUI components for ZK application. For fast prototype, you can write java code inside it as zscript. Therefore you can handle events inside it. Please refer to The zk user interface markup language.

GUI component

Tags in ZUML represent GUI components of ZK, such as button and textbox. For tags <xxxx> which appear in *.zul, most of their tag names xxxx refer to corresponding ZK GUI components. For example <window/>, <hbox/>, <label>. You can visit javadoc for GUI components to see components ZK has.

UI and event handler

In most cases, developers use ZUML to layout UI components like button and textbox. When an event occurs in the UI, ZK will automatically notify the server and trigger the relevant event handler (written in Java). From that point, you can do anything you can do in Java, as required, including step-by-step debugging, connecting to a database, or using 3rd party Java libraries/frameworks.

How ZUML and Java work together

For best practice, ZUML takes care of UI layout, and Java takes care of everything else.

Actually, you can write java code in ZUML, which is called zscript. And you can add/remove GUI component in pure java file too. To the extreme, you can do everything using only ZUML, or using only Java. However, using only ZUML, you'll lack the ability of step-by-step debugging. It will also entangle views with codes, which will be hard to maintain. On the other hand, using only java, it's tedious to write codes to create component and to append it to DOM tree.

The Role of Java

Event handling

For event handling, you can write java code in zscript in ZUML for fast prototyping. Or like the example, Design pattern: MVC in chapter. Getting Started, you can write event handling code in pure java file. ZUML has attributes use and apply for certain usage,[1]

Define UI component programmatic

For UI components, you can define UI components like button or textbox in ZUML, or dynamically add UI components in Java codes. After all, ZK has a java class for each UI component. As the example Design pattern: MVC in chapter. Getting Started, when you click the button, it appends a label component to the window as a child.

evt.getTarget().appendChild(new Label("Hello"));

In extreme cases, you can also write all UI components in Java without ZUML. [2]

Java is executed at server, call 3rd party library as you like

All Java code, whether implemented in zscript in ZUML, or in java file, is executed at server side. Therefore, you can fully utilize any java library as you like. The client side browser only gets the rendered html content and ZK client engine written in java script.[3]

Note

  1. please refer to next chapter The ZK User interface Markup Language for more information.
  2. Please refer to Chapter Richlet for more detail.
  3. There is a way for you to write java script to execute in client side browser. Please refer to Part G. Migrate/Integrate Other UI frameworks for detail.


UI Components

Component: an UI object

A component is an UI object, such as a label , a button and a tree . It defines the visual presentation and behaviors of a particular user interface. By manipulating them, developers control how to represent an application visually in the client. A component must implement the Component interface.

Component = Visual Part + Java Object

Besides being a Java object in the server, a component has a visual part[1] in the browser, if and only if it belongs to a page. When a component is attached to a page, its visual part is created[2]. When a component is detached from a page, its visual part is removed.

In Java, There are two ways to attach a component into a page. First, you could call the setPage method to make a component to become a root component[3] of the specified page. Second, you could call the setParent , insertBefore or appendChild method to make it to become a child of another component. Then, the child component belongs to the same page as to which the parent belongs.

Similarly, you could detach a root component from a page by calling setPage with null . A child is detached if it is detached from a parent or its parent is detached from a page.


Notes

  1. If the client is a browser, the visual presentation is a DOM element or a set of DOM elements.
  2. The visual part is created, updated and removed automatically. Application developers rarely need to notice its existence. Rather, they manipulate the object part in the server.
  3. A node without a parent node is a root component.

Use id to identify component

Each component has an identifier. It is created automatically when a component is created. Developers could change it anytime. There is no limitation about how an identifier shall be named. However, if an alphabetical identifier is assigned, developers could access it directly in Java codes and EL expression embedded in the ZUML page.

<window title="Vote" border="normal">
	Do you like ZK? <label id="label"/>
	<separator/>
	<button label="Yes" onClick="label.value = self.label"/>
	<button label="No" onClick="label.value = self.label"/>
</window>

The naming of identifier is so unlimited, you can even give it a name as component name like label. First label in <label id="label"/> is a component name, the second label in <label id="label"> is the value of id of the component. label in <button label="yes"/> is a property of button,

<button label="Yes" onClick="label.value = self.label"/>

Above code means when you click the button , change the value of component whose id is label to the button 's label:yes. self is an implicit object depicting the closest component, it is button here.

Versatile Widgets

ZK provides more than 150 off the shelf widgets ready to use. You can look it up at Part C. ZUL Component for basic usage. Or look it up at Developer's Reference for detail. Also, java doc of their corresponding java classes is a good reference. After all, each property of the component is mapping to the setter/getter methods of java class, therefore javadoc is a good reference to find out what properties a component has. You can also visit ZK Live Demo to experience the look and feel of ZK components.

  • Package org.zkoss.zul : ZUL component set that are used for HTML-based clients. It includes window, button, listbox.
  • Package org.zkoss.zkmax.zul : Components and UI utilities available in the Enterprise edition. It includes performance enhanced version of ZUL components. It also includes filedownload and tablelayout.

Inside ZK forge package, ZK has integrated FCKeditor and gmaps as a ZK component. Please refer to ZK's smalltalks to see the introduction of how to integrate existing 3rd party library to an exciting ZK component.

How to find out what properties a component has

Please refer to previous section: Versatile Widgets. Look into javadoc of java class of GUI component. A property always has its corresponding setter/getter methods. The mapping from tag/attribute name to class/method name is intuitive. For the tag button, its corresponding java class is org.zkoss.zul.Button. And <button label="ok"/> will correspond to Button.setLabel("OK").

Page and Desktop

Page: created for each ZUML

A page (Page ) is a collection of components. A page confines components belonging to it, such that they will be displayed in a certain portion of the browser. A page is automatically created when ZK loader interprets a ZUML page.

Desktop: for serving the same URL request

A ZUML page might include another ZUML pages directly or indirectly. Since these pages are created for serving the same URL request, they are collectively called a desktop (Desktop ). In other word, a desktop is a collection of pages for serving the same URL request for one user. As a ZK application interacts with user, more pages might be added to a desktop and some might be removed from a desktop. Similarly, a component might be added to or removed from a page.

Zk basic desktop.jpg

Notice that both pages and desktops are created and remove implicitly. There are no API to create or remove them. A page is create each time ZUML loads a page. A page is removed when ZK finds it is no longer referenced. A desktop is created when the first ZUML page is loaded.

Implicit Objects

Besides components created by user, there are implicit objects created automatically. These implicit objects enable developers to access components more efficiently, get information about system, client. And developer may utilize implicit objects to pass variables. Implicit objects include: self, spaceOwner, page, desktop, execution, session, application, componentScope, spaceScope, pageScope, desktopScope, sessionScope, applicationScope, requestScope, arg, each, forEachStatus, event

The corresponding java classes of implicit objects are located at Package org.zkoss.zk.ui

Please refer to Implicit Objects for detailed explanation.

UI Component Forest

Forest of Trees of Components

Like a tree structure, a component has at most one parent. A component might have multiple children. All components of a page form a DOM tree.

Some components accept only certain types of components as children. Some must be a child of certain type of components. Some don't allow any child at all. For example, Listbox in XUL accepts Listcols and Listitem only. Refer to Javadoc or XUL tutorials for details.

A component without any parent is called a root component. A page might have multiple root components, but this is against XML's syntax limitation: One document root only. You may use tags as zk, window, span, div as the document root to group these root components

ID Space

It is common to decompose a visual presentation into several ZUML pages. For example, a page for displaying a purchase order, and a modal dialog for entering the payment term. If all components are uniquely identifiable in the same desktop, developers have to maintain the uniqueness of all identifiers for all pages that might created to the same desktop.

The concept of ID space is hence introduced to resolve this issue. An ID space is a subset of components of a desktop. The uniqueness is guaranteed only in the scope of an ID space.

The simplest form of an ID space is a window (Window ). All descendant components of a window (including the label window)forms an independent ID space. Thus, you could use a window as the topmost component of each page, such that developers need to maintain the uniqueness of each page separately.

More generally, any component could form an ID space as long as it implements the IdSpace interface. Page also implements the IdSpace interface, so it is also a space owner. Besides window and page, regular macro is another built-in space owner.

The topmost component of an ID space is called the owner of the ID space, which could be retrieved by the getSpaceOwner method in the Component interface.

If an ID space, say X, is a descendant of another ID space, say Y, then space X's owner is part of space Y but descendants of X is not part of space Y.


Following zul example will get an ID space graph as below:

<?page id="P"?>
<zk>
	<window id="A">
		<hbox id="B">
			<button id="D" />
		</hbox>
		<window id="C">
			<button id="E" />
		</window>
	</window>
	<hbox id="F">
		<button id="G" />
	</hbox>
</zk>

Zk the id space.jpg

As depicted in the figure, there are three spaces: P, A and C. Space P includes P, A, F and G. Space A includes A, B, C and D. Space C includes C and E.

Components in the same ID spaces are called fellows. For example, A, B, C and D are fellows of the same ID space.

To retrieve another fellow, you could use the getFellow method in the IdSpace interface or the Component interface.

Notice that the getFellow method can be invoked against any components in the same ID space, not just the space owner. Similarly, the getSpaceOwner method returns the same object for any components in the same ID space, no matter it is the space owner or not. In the example above, if C calls getSpaceOwner will get C itself, if C calls getSpaceOwnerOfParent will get A.

The Path class provides utilities to simplify the location of a component among ID spaces. The way of using it is similar to java.io.File .

//below are 3 different ways to get the same component E
Path.getComponent("/A/C/E");//if call Path.getComponent under the same page.
new Path("A/C", "E").getComponent();
Path.getComponent("//P/A/C/E");//for page, you have to use // as prefix

Remember that each GUI component has its corresponding java object. Through Path.getComponent(), you can get the object in java, and do whatever you want to manipulate the java object. Learn more

Namespace and ID Space

To grant the interpreter an access to the components directly, the namespace concept (Namespace ) is introduced.

  • First, each ID space corresponds to exactly one namespace.
  • Second, variables defined in a namespace are visible to the zscript codes and EL expressions that belong to the same namespace.

In the following example, it will show: Hi, namespace Hi, namespace

<window border="normal">
	<label id="l" value="changed by zscript, therefore not shown"/>
	<zscript>
		l.value = "Hi, namespace";
	</zscript>
	${l.value}
</window>

${l.value} is an EL expression, it means get the value of l.

In the following example, there are two namespaces. One belongs to window w1 while the other belongs to window w2. Thus, the b1 button's onClick script refers to the label defined in window w2 , while the b2 button's onClick script refers to the checkbox defined in window w1 .

<window id="w1">
	<window id="w2">
		<label id="c"/>
		<button id="b1" onClick="c.value = &quot;OK&quot;" label="click me"/>
	</window>
	<checkbox id="c"/>
	<button id="b2" onClick="c.label = &quot;OK&quot;" label="click me"/>
</window>
  • Notice the namespace is hierarchical.

In other words, zscript in window w2 can see components in window w1 , unless it is overridden in window w2 . Thus, clicking button b1 will change label of c to "OK" in the following example.

<window id="w1">
	<window id="w2">
		<button id="b1" onClick="c.value = &quot;OK&quot;" label="Click me"/>
	</window>
	<label id="c"/>
</window>

It looks strange at first glance, as onClick="c.value = &quot;OK&quot;" appears before <label id="c"/> is defined. Don't we have to declare variable before using it? Actually, it's a life cycle issue. zscript inside onClick is only evaluated when user actually clicks on the button. At that time, <label id="c"/> has been created already and is certainly visible to zscript.

For more example

Manipulate DOM by Java

DOM(Document Object Model) is generated as the layout of zul components in ZUML. In addition to ZUML, you can use Java to add, remove, move nodes in DOM manually. When a component is created manually, it won't be added to any page automatically. In other words, it doesn't appear at user's browser. To add it to a page, you could invoke the setParent, appendChild or insertBefore method to assign a parent to it, and it becomes a part of a page if the parent is a part of a page.

As demonstrated in section Design pattern: MVC, a label is appended to window when the button is clicked. A node that represents the label is added to the DOM tree, and the node of window is its parent.

evt.getTarget().appendChild(new Label("Hello"));

Another way to add new child is through Executions.createComponents. Please refer to java doc for Executions

Note that, we can also write java code inside *.zul, which is called zscript.

Events of UI Components

An event (Event ) is used to notify application what happens. Each type of event is represented by a distinct class. For example, MouseEvent represents a mouse activity, such as clicking.

To respond to an event, an application must register one or more event listeners to it. Here are the ways to register an event listener:

  • By specifying the predefined event handler onXxx in the markup language.
  • By calling the addEventListener method for the component or the page you want to listen to.
  • By specifying ZK attributes forward, use, apply. Please refer to The forward Attribute for more information.

In addition to event triggered by user's activity at the browser, an application could fire events by using sendEvent, postEvent and echoEvent methods from the Events class.(Note: These api has to take care about component life cycle, if you use these api outside ZK event handler, please refer to server push.)

How to find out what events a component support

Please look it up at Developer's Reference. For example, button supports onClick, onRightClick, onDoubleClick, onFocus, onBlur events.

Due to ZK's fast evolution, if the Developer's Reference is out of sync, please refer to this How-To to find out what events a component support by tracing source code.

Event Processing is limited to desktop scope

As mentioned above, a desktop is a collection of pages for serving the same URL request. A desktop is also the scope that an event listener could access.

When an event is fired, it is associated with a desktop. ZK separates events by their associated desktops, and pipelines events into separated queues. Therefore, events for the same desktop are processed sequentially. On the other hand, events for different desktops are processed in parallel.

An event listener is allowed to access any component of any page of the associated desktop. It is also allowed to moving components from one page to another as long as they are in the same desktop. On the other hand, it cannot access components belonging to other desktops.

See Also

From ZK Forum

Urgent HELP needed: How to open a new browser window which is a new ZK page of my current desktop!

Pure Java with ZK

Quiz

1.How do server and client transfer message by ZK?

2.What language is ZK client engine written in?

3.In following example, when the button is clicked, what message will be transferred between client and server? Why? Can you trace it by firebug? When is the code of alert("hello") transferred?

<zk>
	<label value="ok" onClick='alert("hello")'/>
</zk>

4.The Role of Java? Is Java executed in server or client?

5.Name three components and their corresponding java classes

6.Does button has property value? label?

7.Name three implicit objects.

8.Please draw the id space graph of the code below. How can we get the components in java? say C,D,G?

<?page id="P"?>
<zk>
	<window id="A">
		<hbox id="B">
			<button id="D" />
		</hbox>
		<window id="C">
			<button id="E" />
		</window>
	</window>
	<hbox id="F">
		<button id="G" />
	</hbox>
</zk>



Last Update : 2010/07/22

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.