New Features of ZK 3.0

From Documentation
Revision as of 09:52, 10 September 2010 by Elton776 (talk | contribs) (Created page with '{{Template:Smalltalk_Author| |author=Robbie Cheng, Engineer, Potix Corporation |date=November 6, 2007 |version= }} The ZK team proudly presents you ZK 3.0. It includes a lot o…')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
New Features of ZK 3.0

Author
Robbie Cheng, Engineer, Potix Corporation
Date
November 6, 2007
Version


The ZK team proudly presents you ZK 3.0. It includes a lot of new features - server push, layout components, and more integration with other components/frameworks, and the most important of all is the performance improvement - four ~ five times faster than ever! (See the report).

Moreover, for better support to those dated Web servers; for example, Tomcat 4.1 and Websphere 5.1, ZK 3.0 no longer depends on JSP. From now on, ZK only depends on servlet 2.3.

Don't hesitate! It's time to upgrade!

In the following paragraphs, I'll introduce the most exciting new additions to ZK 3.0 since ZK 2.4.


Ease of Use

For ease of use, ZK provides server push which allows you to update client’s information more easily. In addition, two new properties - forward and apply- which allows you realize the MVC approach more easily. Moreover, the new expression of annotation is more intuitive and easy-to-read. Let's check it out!


Server Push

This is so-called reverse-Ajax which allows the server to send content to the client actively. ZK now supports server push implemented using client-polling technique. To use server push, the only two things you have to do are enabling server push, and starting your working Thread, and the rest of work will be finished by ZK. Let’s take a look at a real example below. For example, if you want to update the number of the client constantly. First of all, you have to enable server push for the desktop and to invoke the thread as follows,


<window title="Demo of Server Push">
<zscript>
import org.zkoss.zkdemo.test.WorkingThread;
WorkingThread thread;

void startServerpush(){
desktop.enableServerPush(true);
thread= new WorkingThread(info).start();
}
void stopServerpush(){
thread.setDone();
desktop. enableServerPush(false);
}
</zscript>
<vbox>
<button label="Start Push" onClick="startServerpush()"/>
<button label="Stop Push" onClick="stopServerpush"/>
<label id="info"/>
</vbox>
</window>


Furthermore, to avoid the condition that a desktop might be accessed by multiple threads at the same which might cause the problem of synchronization. Thus, before accessing the desktop, you have to invoke Executions.activate(Desktop desktop) to get full control of the desktop, then release the control of the desktop by invoking Executions.deactivate(Desktop desktop) after the thread finishing its job as follows,

public class WorkingThread extends Thread {
 private final Desktop _desktop;
 private final Label _info;
 private int _cnt;
 private boolean _ceased;
 public WorkingThread(Label info) {
  _desktop = info.getDesktop();
  _info = info;
 }
 public void run() {
  try {
   while (!_ceased) {
    Threads.sleep(2000); //Update each two seconds
    Executions.activate(_desktop);
    try {
     _info.setValue(Integer.toString(++_cnt));
    } catch (RuntimeException ex) {
     throw ex;
    } catch (Error ex) {
     throw ex;
    } finally {
     Executions.deactivate(_desktop);
    }
   }
  } catch (InterruptedException ex) {
  }
 }
 public void setDone(){
  _ceased = true;
 }
}

In this example, the content of label will be updated by the Thread constantly until it is stopped. For more information, please refer to this small talk: Simple and Intuitive Server Push with a Chat Room Example


Forward Property

In the past, we usually register an event listener using zscript and specify related actions within it. This is simple and intuitive but the drawback of it is lower performance because of using zscript requires additional execution time for the interpreter (e.g. BeanShell).

Now, in ZK 3.0, we provide a new property of components—forward—which allows you to forward events to other components to get rid of zscript. Please take a look at the following example. A window usually consists of several buttons, menu items and other controls. For example,

<window use="MyWindow">
...
<button label="OK"/>
<button label="Cancel"/>
</window>


When the user clicks the button, the onClick event is sent to the button itself. However, these events are better to process in the window rather than scattering around these buttons. To do that, you can use the forward attribute as follows.

<window use="MyWindow">
...
<button label="OK" forward="onOK"/>
<button label="Cancel" forward="onCancel"/>
</window>


where the forward attribute of the OK button specifies that the onClick event, if received, shall be forwarded to the space owner (i.e., the window) as the onOK event. Similarly, the onClick event targeting the Cancel button is forwarded as the onCancel event. Thus, you can handle the onOK and onCancel events in the space owner, MyWindow, as follows,

public class MyWindow extends Window {
  public void onOK() {
    //called when the OK button is clicked (or the ENTER button is pressed)
  }
  public void onCancel() {
    //called when the Cancel button is clicked (or the ESC button is pressed)
  }
}


Apply Property

If you prefer the MVC (Model-View-Controller) approach, i.e., you prefer not to embed the handling codes in the window (the view), you can implement a class to initialize the window. The class must implement the org.zkoss.zk.ui.util.Composer interface.

import org.zkoss.zk.ui.util.Composer;
import org.zkoss.zul.Window;
  public class MyComposer implements Composer {
    public void doAfterCompose(Component comp) {
       ((Window)comp).setTitle("My Title"); //do whatever initialization you want
       //comp is Window since we will specify it to a window later
    }
}


Then, specify the class with the apply attribute as shown below.

<window apply="MyComposer">
...
</window>


New Expression of Annotation

In ZK 3.0, we provide one more intuitive way to annotate ZK components. Let’s take a look at the classic way first.


The Classic Way

The classic way of annotation appears before the declaration of the element that you want to annotate:

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<window xmlns:a="http://www.zkoss.org/2005/zk/annotation">
  <a:bind model="persons" selectedItem="selected"/>
  <listbox rows="4">
	<a:bind _var="person"/>
	<listitem>
	  <a:bind label="person.firstName"/>
	  <listcell/>
	  <a:bind label="person.lastName"/>
	  <listcell/>
	</listitem>
  </listbox>
</window>


The More Intuitive Way

The new way of annotation allows you to annotate components more intuitively. No separate declaration of annotations are required anymore, you could specify annotations as values within components’ declarations or their properties directly as follows,

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<window>
 <listbox rows="4" model="@{persons}" selectedItem="@{selected}">
	<listitem self="@{each=person}">
	  <listcell label="@{person.firstName}"/>
	  <listcell label="@{person.lastName}"/>
	</listitem>
  </listbox>
</window>


Note: self is a keyword to denote the annotation is used to annotate the component declaration, rather than any property.


ZK Components Reloaded

In ZK 3.0, we implemented ZK layout components, TreeModel, timebox, flash components, and etc.


ZK Layout Components

The layout component is a nested component. The parent component is borderlayout, and its children components include north, south, center,west, and east. As you can see, it is intuitive and easy to use. There is an example of using layout component as follows,

<borderlayout>
 <north size="50%" border="0">
  <borderlayout>
   <west size="25%" border="none" flex="true">
	<div style="background:#B8D335">
	 <label value="25%"
	  style="color:white;font-size:50px" />
	</div>
   </west>
   <center border="none" flex="true">
	<div style="background:#E6D92C">
	 <label value="25%"
	  style="color:white;font-size:50px" />
	</div>
   </center>
   <east size="50%" border="none" flex="true">
	<label value="Here is a non-border"
	 style="color:gray;font-size:30px" />
   </east>
  </borderlayout>
 </north>
 <center border="0">
  <borderlayout>
   <west size="30%" flex="true" border="0">
	<div style="background:#E6D92C">
	 <label value="30%"
	  style="color:white;font-size:50px" />
	</div>
   </west>
   <center>
	<label value="Here is a border"
	 style="color:gray;font-size:30px" />
   </center>
   <east size="30%" flex="true" border="0">
	<div style="background:#B8D335">
	 <label value="30%"
	  style="color:white;font-size:50px" />
	</div>
   </east>
  </borderlayout>
 </center>
</borderlayout>

Layout.png

For more information, please take a look at this smalltalk,A Simple, Flexible, and Powerful ZK Layout.


Auxiliary headers

For grid, listbox, and tree, in addition to columns, you can specify auxiliary headers with the auxhead and auxheader components as follows.

<grid>
 <auxhead>
  <auxheader label="H1'07" colspan="6"/>
  <auxheader label="H2'07" colspan="6"/>
 </auxhead>
 <auxhead>
  <auxheader label="Q1" colspan="3"/>
  <auxheader label="Q2" colspan="3"/>
  <auxheader label="Q3" colspan="3"/>
  <auxheader label="Q4" colspan="3"/>
 </auxhead>
 <columns>
  <column label="Jan"/><column label="Feb"/><column label="Mar"/>
  <column label="Apr"/><column label="May"/><column label="Jun"/>
  <column label="Jul"/><column label="Aug"/><column label="Sep"/>
  <column label="Oct"/><column label="Nov"/><column label="Dec"/>
 </columns>
 <rows>
 <row>
  <label value="1,000"/><label value="1,100"/><label value="1,200"/>
  <label value="1,300"/><label value="1,400"/><label value="1,500"/>
  <label value="1,600"/><label value="1,700"/><label value="1,800"/>
  <label value="1,900"/><label value="2,000"/><label value="2,100"/>
 </row>
 </rows>
</grid>

Auxheader.png


Timebox

In addition to Datebox, ZK now supports Timebox which allows user to choose time by hour and minutes, for more information, please refer to Using Timebox Component .


Flash Components

Now, ZK supports versatile flash components which allow you to play media files, including .swf, youtube clip, and mp3 files. For more information, please refer to New ZK Flash Based Components.


SimpleListModelSharer

With the help of server push, ZK allows you to share the same ListModel for different clients, and to update their data automatically when necessary. It is useful when you want to broadcast information to clients, for example, stock price. And the most important of all is that its usage is simple. Let’s take a look at an example which broadcasts stock price to clients automatically by using SimpleListModelSharer and Server Push.


stockquotes.zul

<zk>
 <zscript>
  import org.zkoss.zulex.demo.stock.*; 
  
  if(!desktop.isServerPushEnabled()){
   desktop.enableServerPush(true);
  }
  StockUpdateService service = StockUpdateService.lookup();
  ListModel model = service.getProxy(desktop);
  StockRowRenderer renderer = new StockRowRenderer();
 </zscript>
 <hbox>
  Stock:
  <textbox id="stock" value="BCC"/>
  <button id="addbtn" label="add" onClick="service.addStock(stock.value)"/>
 </hbox>
 <separator/>
 <groupbox width="300px">
 <caption label="Live Stock Quotes Demo" />
 <grid model="${model}" rowRenderer="${renderer}" >
  <columns>
   <column label="Symbol" width="100px"/>
   <column label="Price" />
   <column label="Change" />
  </columns>
 </grid>
 </groupbox>
</zk>
  • Enable server push by desktop.enableServerPush(true);.
  • Get a Proxy of ListModel by call getProxy(desktop).
  • Call addStock(value) when onClick
  • Assign model to grid.


StockUpdateService.java

public class StockUpdateService {
 ...
 private StockUpdateService(){
  stockModel = new ListModelList();
  modelSharer = new SimpleListModelSharer(stockModel);
  ...
  new Thread(new UpdateRunnable()).start();
 }
 
 public ListModel getProxy(Desktop desktop){
  return modelSharer.getProxy(desktop);
 }
 
 ...
 class UpdateRunnable implements Runnable{
  ...
  public void run() {
   while(running){
	...
	StockInfo si = getCurrentStockQuotes(index);//get current stock quotes   
	stockModel.set(index,si);//and update it
	...
   }
  }
 }
}
  • New a SimpleModelSharer with stockModel.
  • Start a thread which will update stockModel periodically.
  • Modify stockModel without any tedious code, modelSharer will update all proxies automatically with Server Push.


For more information, please take a look at this smalltalk,Integrate Server Push with ListModel - SimpleListModelSharer.


TreeModel

Tree model is long-awaited by the community, finally ZK supports tree model. Please take a look at the following example,

 <window>
 <zscript>
  ArrayList al = new ArrayList();
  int i=0;
  for(; i < 100000; i++)
  {
   Object obj = ""+i;
   al.add(obj);
  }
  BinaryTreeModel btm = new BinaryTreeModel(al); 
 </zscript>
  <tree model="${btm}" id="tree" >
  </tree>
 </window>


For more information, please refer to ZK Tree Model.


Comboitem - HTML Description

ZK allows you to enrich the description of a Comboitem with HTML as follows,

<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" ?>

<combobox>
 <comboitem label="Simple and Rich" 
   description="The simplest way to make Web applications rich"/>
 <comboitem label="Cool!"
 description="The coolest technology">
	   <![CDATA[ <b>Bold</b> and <i>italic</i>]]>
 </comboitem>
 <comboitem label="Ajax and RIA">
	   <![CDATA[<img src="/zkau/web/zul/img/slider/btn.gif"/>ZK, the best]]>
 </comboitem>
</combobox>


or you could add HTML content by programming as follows,

new Comboitem().setContent("<b>xx</b>....");


Tabbox - Lite Look

ZK provides a "lite" look of tabbox, and you could use it as follows,

<tabbox width="400px" sclass="lite">
  <tabs>
   <tab label="Tab 1"/>
   <tab label="Tab 2" closable="true"/>
   <tab label="Tab 3"/>
  </tabs>
  <tabpanels>
   <tabpanel>This is panel 1</tabpanel>
   <tabpanel>This is panel 2</tabpanel>
   <tabpanel>This is panel 3</tabpanel>
  </tabpanels>
 </tabbox>


The layout is shown in the following figure.

Lite.jpg


Customization of Look and Feel

Before ZK 3.0, the way to change the look and feel of ZK components requires you a little effort by modifying the DSP file; besides, some of them aren't configurable. For ease of use, since ZK 3.0, we allow you to override the CSS definitions of components to change their look and feel. For example, icons of tree, splitter, and slider could be customized by overriding their CSS definitions, and also the look of selected item. For example, you could change the style of selected item of listbox by overriding the following CSS definitions,

 tr.focusd {
  background-color:red;
 }


And the result is as follows.

Listitem2.png


Use Your Own Theme

It is easy to customize the look and feel of the ZK XUL components by providing your own style sheets (CSS). You can refer to norm.css.dsp and normie.css.dsp in the zul project for examples.

<desktop-config>
 <theme-uri>/css/my-fine-font.css</theme-uri>
</desktop-config>

If you just want to change the font size, you can reference normsm.css.dsp.


Change Theme Dynamically

If you prefer to decide the theme at the run time depending on the current user, cookie, locale or others, you can implement a theme provider. A theme provider is a class that implements the org.zkoss.zk.ui.util.ThemeProvider interface.

package my;
public class MyThemeProvider implements ThemeProvder {
 public Collection getThemeURIs(Execution exec, List uris) {
  for (Iterator it = uris.iterator(); it.hasNext();) {
   if ("~./zul/css/norm*.css.dsp*".equals(it.next()))
   it.remove(); //remove the default theme
  }
  HttpServletRequest req = (HttpServletRequest)exec.getNativeRequest();
  uris.add(getMyThemeURI(req));
  return uris;
 }
}

Then, you configure WEB-INF/zk.xml by adding the following lines.

<desktop-config>
 <theme-provider-class>my.MyThemeProvider</theme-provider-class>
</desktop-config>


Enhancement of Data-Binding

Data binding supports validation phase which allows you to do validation in your own way.


An Alternative Way of Validation

Before 3.0, while using data binding, we used to do validation of values by specify conditions in constraint attribute of ZK components. From now on, data binding provides an alternative way to do validation by posting onBindingSave event to each of binding components so that you could do validation with your customized way by registering onBindingSave event listener in these components as follows,

<intbox value="@{person.age, save-when='btn.onClick'}">
<attribute name="onBindingSave">
   if (self.value < 18)
	  throw new WrongValueException("Age below 18 is not allowed to enter this site.")
</attribute>
</intbox>


Then, after posting onBindingSave events to all of binding components to make sure their values are validated. Then, data binding will post an onBindingValidate event to the ZK component which triggers data binding to work, for example, a button.

 <button id="btn" label="submit">
   <custome-attributes passed="false"/>
   <attribute name="onBindingValidate">
	  self.setAttribute("passed",true);
	</attribute>
   <attribute name="onClick">
	  if (self.getAttribute("passed") == true)
		 Executions.sendRedirect("index.zul");
   </attribute>
 </button>


Finally, after posting all events of validation phase to all related ZK components, data binding will truly save data into data bean.


Namespace Extended

ZK supports native namespace for better performance, and it allows XML output. Please take a look at the following two paragraphs.

Native Namespace

In ZK 3.0, we provide a new namespace—native namespace—for mixing ZK components with HTML tags in addition to XHTML namespace. The major difference between them is whether to create ZK components at the server side or not. If you used XHTML to mix HTML tags, ZK will generate corresponding ZK components at the server. On the contrast, ZK won’t generate ZK components at the server for better performance while using Native namespace.

One thing to notice is that there is no difference between the out put of these two namespaces. If you mix HTML tags with ZK component using native namespace as follows,

<n:ul xmlns:n="http://www.zkoss.org/2005/zk/native">
  <n:li>
	<textbox/>
  </n:li>
  <n:li>
	<textbox/>
  </n:li>
</n:ul>


in which will generates the following HTML tags to the browser:

<ul>
  <li>
	<input id="z_a3_2"/>
  </li>
  <li>
	<input id="z_a3_5"/>
  </li>
</ul>


However, if you want to change the content of these HTML tags dynamically, you should use XHTML namespace instead of Native namespace. The choice is yours.


XML Output

Nowadays, XML have become the standard format of many devices and protocols, such as RSS and SVG. It is straightforward to output XML with ZK. ZK generates them directly to the output without instantiating a ZK component for each of them.

The following is an example that generates the SVG output. It looks very similar to the XML output you want to generate, except you can use zscript, EL expressions, macro components and other ZK features.

<?page contentType="image/svg+xml;charset=UTF-8"?>

<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <z:zscript xmlns:z="http://www.zkoss.org/2005/zk"><![CDATA[
  String[] bgnds = {"purple", "blue", "yellow"};
  int[] rads = {30, 25, 20};
  ]]></z:zscript>
  <circle style="fill:${each}" forEach="${bgnds}"
  cx="${50+rads[forEachStatus.index]}"
  cy="${20+rads[forEachStatus.index]}"
  r="${rads[forEachStatus.index]}"/>
</svg>

For more information, please refer to XML Output in dev's guide.


Performance Tips

Pluggable EL Evaluator

In ZK 3.0, by making the EL evaluator pluggable, ZK gives you an option to use JSP 2.1's EL, OGNL, MVEL and others. Currently, JSP 2.0, JSP 2.1, MVEL, and OGNL plugin are available in ZK. In the following example, we demonstrate you how to use MVEL to evaluate EL.

<?evaluator name="mvel"?>
<window id="w" title="MVEL Demo">
  ${new org.zkoss.zul.Textbox().setParent(w)}
</window>

You can integrate with other EL evaluator by implementing the org.zkoss.xel.ExpressionFactory interface. For more information, please refer to "The evaluator Directive" in developer's reference.

A Faster Way to Render ZK Components

In addition to DSP, JSP and any Servlet technologies, you can implement the org.zkoss.zk.util.ComponentRenderer interface, and then specify it in the moldURI attribute by starting with "class:". With this approach, the performance is improved a lot, if we can specify a class and render the component directly without going through Servlet.

<?component name="window" extends="window" mold-name="default" 
mold-uri="class:com.mycompany.myWindowRender" ?>

<window title="Faster Window!" border="normal" width="200px">
 Hello, World!
</window>


Other Features

Other convenient features are illustrated in the following paragraphs.

A New Way to Avoid Session Timeout

In the past, a session is considered as timeout, if it doesn't receive any client request in the specified timeout interval. From now on, ZK allows you to keep a session alive by using a Timer which sends onTimer event to the server. Thus, you could specify whether to keep the session alive, when receiving the onTimer event as follows,

<session-config>
  <timer-keep-alive>true</timer-keep-alive>
</session-config>


A New Way to Use TLD of DSP

Usually, if we want to use TLD in ZUL page, we have to copy those TLD files to \WEB-INF directory, and include them as follows,

 <?taglib uri="/WEB-INF/tld/web/core.dsp.tld" prefix="c"?>


Now, ZK provides you an easier way by including those TLDs as follows without copying those TLD files as follows,

 <? taglib uri="http://www.zkoss.org/dsp/zweb/core" pefix="c" ?>


A Way to Include Method without TLD

Before ZK 3.0, for ease of use, we usually defined often used methods in TLD file, but it will cause the problem of dependence between the page and the TLD file. To avoid the problem of dependence, you can use a processing instruction called the xel-method to include methods as follows.

<?xel-method prefix="c" name="forName" class="java.lang.Class" 
signature="java.lang.Class forName(java.lang.String)"?>

<textbox value="${c:forName('java.util.List')}"/>


Integration with Other Frameworks

JSF

JSF (JavaServer Faces) is a technology used for building user interfaces for JavaServer applications. Now, ZK provides a set of JSF components which wrap ZK components, and implement the features of JSF like ValueBinding, Converter, Validator, etc. For more information, please refer to this smalltalk, Enrich Your JSF Applications with ZK Today!

JSP

This is great news for developers and companies who want to bring rich interface to their legacy JSP applications with ZK. Here, ZK introduces you a JSP tag library of ZK which allows you to integrate ZK components into your JSP pages using JSP tags. For more information. please take a look at the following smalltalks,Use ZK JSP Tags in Your JSP Pages, ZK JSP Tag Lib Support Initiator and Annotation

Ext-JS

Yui-Ext-- now called Ext JS, is a world famous client-side, JavaScript library for building web applications. However, using Yui-Ext JavaScript library with server side Java code is very complicated. But don't worry, ZK framework will as always do the complicated part for you. There are many useful and amazing widgets and functions, please refer to the following smalltalks, Integrating Yui-Ext into ZK Framework, New Features of yuiextz 0.5.1., Y-Grid Support Drag-Drop and DataBinding, Enrich the Layout of ZK with Ext JS




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