Server Push with a Stock Chart Example
Grace Lin, Engineer, Potix Corporation
May 20, 2008
Applicable to ZK 3.1 Freshly (zk-3.1.0-FL-2008-05-20 and later)
Live Demo of Stock Chart
To show how easy we can use server push with ZK, let us take a look at the stock charting example.
Introduction
The term 'server push' generally means that server pushes content to the browser client, but the browser doesn't allow this directly. However, there are some ways to emulate server push. We will mention two examples below, one by client polling and the other using comet.
Client Polling
The client polls the server at a certain interval, asking it if a new event has occurred (e.g. each five seconds asking the server “Any new events?”). This technique is typically used to update news information. Polling server push introduces a painful trade-off between latency and server load; the average event latency is half the poll interval.
ZK provide a constructed implementation (org.zkoss.zkex.ui.impl.PollingServerPush) for you to use client polling technique. There is an example use this technique in the previous small talk “ Simple and Intuitive Server Push with a Chat Room Example ”. When you update ZK to 3.1.0, remember to change code “ChatWindow.java” from
getFellow("div").smartUpdate("scrollTop", "10000");
to
((ComponentCtrl) getFellow("div")).smartUpdate("scrollTop", "10000");
Because of component’s smartUpdate is moved to ComponentCtrl.
Comet
Comet techniques are advocated when your application needs low latency events to be delivered from the server to the browser. Instead of repeatedly polling for new events, Ajax Comet applications rely on a persistent HTTP connection between server and client, using one of two strategies:
Streaming
In an application using streaming Comet, the browser opens a single persistent connection to the server for all Comet events, which is handled incrementally on the browser side; each time the server sends a new event, the browser interprets it, but neither side closes the connection.
Long polling
As the name suggests, long polling requires a new request for each event (or set of events). The browser makes an request to the server, which is kept open until the server has new data to send to the browser. After sending such an event, the server closes the connection, and the browser immediately opens a new one.
Now, ZK supports Comet by the implementation (org.zkoss.zkmax.ui.comet.CometServerPush), you can use it easily.
ZUL File
First, use the chart component and set variables. Then, put an empty model to chart.
Enable Server Push for the Desktop
ZK handle most of thing for you, and you only need to enable Server Push with the following 2 instructions.
- 1. Use Desktop.enableServerPush(true) to enable server push for the Desktop
- 2. Simply create a new thread in the desktop, and this thread will be invoked if Server Push has been enabled for the desktop.
<?xml version="1.0" encoding="UTF-8"?>
<window title="Server Push">
<chart id="timeseries" title="Stock Chart" width="500"
height="250" type="time_series" threeD="false" fgAlpha="128" />
<zscript>
if(!desktop.isServerPushEnabled()){
desktop.enableServerPush(true);
}
XYModel xymodel = new SimpleXYModel();
timeseries.setModel(xymodel);
StockChartUpdate scp = new StockChartUpdate(timeseries);
scp.start();
</zscript>
</window>
StockChartUpdate Class
StockChartUpdate extends Thread to update the stock chart. It will produce new stock price, remove old, and use these data to draw chart when every 2 seconds. In ZK, to avoid the problem of synchronization, a desktop could be accessed by one thread per time. So we use the following two methods to make sure that the desktop be accessed independently.
1. Activate the Desktop before using it
- Invoke Executions.activate(Desktop) to get full control of the desktop. 2.Deactivate Desktop after using it
- Invoke Executioins.deactivate(Desktop) to release full control of the desktop, after the thread finished its job
public class StockChartUpdate extends Thread {
private LinkedList<StockInfo> _stockRecord;
.....
public void updateChart() {
_stockRecord.add(getNewPrice(_stockRecord.peekLast()));
if (_stockRecord.size() > 15)
_stockRecord.remove();
XYModel xymodel = new SimpleXYModel();
for (int i = 0; i < _stockRecord.size(); i++) {
StockInfo stock = _stockRecord.get(i);
xymodel.addValue(stock.getLabel(), stock.getTime().getTime(), stock
.getPrice());
}
_chart.setModel(xymodel);
}
.....
public void run() {
if (!_desktop.isServerPushEnabled())
_desktop.enableServerPush(true);
log.info("active StockChartUpdate : " + getName());
try {
while (!_ceased) {
Executions.activate(_desktop);
try {
updateChart();
} finally {
Executions.deactivate(_desktop);
}
Threads.sleep(2000); // Update every two seconds
}
} catch (InterruptedException ex) {
log.info("The server push thread interrupted", ex);
} finally {
if (_desktop.isServerPushEnabled())
_desktop.enableServerPush(false);
}
log.info("The StockChartUpdate thread ceased: " + getName());
}
}
Download
Configure the Server Push Class
ZK provides two "server push" implementation classes. If you use ZK Professional Edition (with zkex.jar), the default implementation is the client-polling-based class, org.zkoss.zkex.ui.impl.PollingServerPush. If you use ZK Enterprise Edition (with zkmax.jar), the default implementation is the COMET-based class, org.zkoss.zkmax.ui.comet.CometServerPush.
If you use zkmax.jar and want to do client polling, please set the configuration in WEB-INF/zk.xml like following.
<device-config>
<device-type>ajax</device-type>
<server-push-class>org.zkoss.zkex.ui.impl.PollingServerPush</server-push-class>
</device-config>
If you want to use your own server push class, you should implement org.zkoss.zk.ui.sys.ServerPush interface with a no argument default constructor. Then, set WEB-INF/zk.xml as following:
<device-config>
<device-type>ajax</device-type>
<server-push-class>my.ServerPush</server-push-class>
</device-config>
Integrate Server Push
ZK also provides some easy to use utilities regarding server push, like “SimpleListModelSharer”. The SimpleListModelSharer integrates ServerPush and ListModel to share data to different desktops. By simply updating a single model, all its views on each desktop is updated automatically.
Summary
In this small talk, we simply introduce “Server Push” and show how to use it in ZK. Everyone can use it easily with provided implementation. You can implement it by yourself. Server push could be applied in many applications, try it and have fun. If you are have any comment or idea, please feel free to leave comment to ZK forum.
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |