Enhance Ajax development with a fusion of jQuery, ZK, and Java code

Quickly reap benefits of both server- and client-side programming

Using jQuery to communicate with a server-side Java™ application is straightforward. When developing enterprise web applications, though, code becomes complex, and secure communication between the server and client using jQuery becomes very time-consuming and error-prone. It would be much easier if you could implement the entire application in pure Java code. Want to control the business logic and leverage all the benefits of client-side control? In this article, learn to use ZK tools and Java Platform, Enterprise Edition (Java EE) technologies to enhance your Asynchronous JavaScript + XML (Ajax) application development—without giving up client-side functions.

Share:

Lance Lu, Technology Evangelist, Potix Corp.

Photo of Lance LuLance Lu は ZK フレームワークの技術エバンジェリストです。彼は ZK に参加する以前、台湾にある 32 ビット・マイクロプロセッサーの設計企業の上級技術者でした。また、カナダの医療機器メーカーの製品マネージャーであったこともあります。彼はカナダのビクトリア大学 (University of Victoria) で数学の学位を取得しています。彼は学術領域として、物理学、哲学、心理学、数学、コンピューター・サイエンスなどに関心を持っています。



Sachin K Mahajan (sachin.mahajan@in.ibm.com), WebSphere Portal Consultant, IBM  

Sachin Mahajan photoSachin graduated with a Masters degree from the University of Utah, Salt Lake City, U.S. He has worked in both small and large companies in the United States and India performing various technical and managerial roles. Sachin currently works in IBM Software Group's Lotus division.



19 October 2010

Also available in Chinese Japanese Portuguese

Introduction

jQuery popularized the use of selectors in Cascading Style Sheets (CSS) syntax to retrieve Document Object Model (DOM) elements, and to apply operations to those elements. One of the many benefits of using jQuery is that you no longer have the burden of traversing complicated DOM trees using JavaScript.

jQuery. A fast, concise, cross-browser JavaScript library that makes it easy to build web applications and web pages. jQuery simplifies: the creation of animation, communications to server requests, document traversing, and event handling.

ZK is an event-driven, component-based Ajax framework known for its Java programming and integration with Java EE technologies. It brings the desktop programming experience to Ajax. For the HTML inclined, the ZK UI may be pieced together using markup and an expression language (EL).

In this article, explore how the marriage between server-side Java code and jQuery can help you tackle the challenges in enterprise Ajax application development. jQuery and ZK together can integrate technologies to help you easily and efficiently serve up rich and responsive UI experiences.

Download the sample code used in this article.


Ajax application development challenges

The following are typical challenges faced by developers of enterprise-grade Ajax applications.

Complexities
Ajax is complex. With the Ajax communication pattern, a web page does not need to be refreshed in its entirety when elements in DOM can be updated individually.

In an enterprise application, marshalling sophisticated business logic from server to client and taking care of each Ajax call manually is a strenuous effort.

Server-side programming
Server-side Ajax solutions are not able to leverage the resources at the client to build a more responsive user experience, offline functions, or distributing computation and data storage to the client.

The server-side Ajax solutions do not reduce the memory footprint at the server, and, hence, increase the application's scalability.

Client-side programming
Client-side programming introduces further security concerns and development costs. Business logic and sensitive data are left in the open on browsers, making applications vulnerable to attack.

Client-side programming involves extensive JavaScript implementation, which could be a challenge if you're accustomed to application development with Java EE technologies.

Huge data
Another common problem arises when the UI tier must present a lot of data in a view. For example, consider a regular HTML table. When the data source becomes large, you would need to either:
  • Risk overloading the browser cache and slowing down traffic by preloading the large data set
  • Manually implement a mechanism at the server to make a subset of data of interest available in the view whenever a user makes that request.

To clear these hurdles, a viable solution is to use a framework where the client and server states are in sync automatically. You can leverage all the secure Java EE technologies at the server side, while using client-side computation for responsiveness and UI control.


ZK's server+client fusion architecture

ZK's innovative architecture provides the means to fully maximize all the technologies available on both the server and client sides. You can access the client-side widgets directly if you want to. This section outlines some of the benefits of ZK's server+client fusion architecture.

ZK Loader and ZK AU Engine

The ZK Loader serves a URL request by:

  • Creating the UI components on the requested page
  • Loading the data needed onto the components
  • Rendering them onto an HTML page
  • Sending it back to the client, along with ZK's Client Engine

The ZK Asynchronous Update (AU) Engine and Client Engine handle the Ajax communications, shielding you from the complexity of Ajax call handling. Figure 1 shows the ZK Loader, the ZK AU Engine, and the ZK Client Engine.

Figure 1. ZK fusion architecture overview
Diagram showing URL and ZK requests from the client engine to the server and the server returning an html page and ZK responses.

Solving Ajax complexities

ZK's Client Engine and AU Engine play the roles of pitcher and catcher, and ZK's event queue pipe-lines the events to be processed. The result is asynchronous event handling that's simplified to the likes of desktop programming.

Leveraging server-side technologies

Because the server maintains a set of ZK components in JVM corresponding to the set of ZK widgets residing in the browser as JavaScript objects, the state of a page is kept in sync on both sides. Any event handling that deals with business logic or sensitive data is kept at the server side. The resulting change of states in the ZK components at the server is only reflected back to the client-side ZK widgets when the event processing is completed. No business logic is ever exposed at the client side.

Leveraging client-side technologies

ZK widgets are client-side JavaScript objects written with jQuery, so they inherit all the behaviors that come with jQuery. Because a complete representation of components and their states exist at both the client and the server, you are given the option to program applications at the server or client. Figure 2 shows an example.

Figure 2. ZK client-side technology
Diagram showing arrows to and from the DOM, ZK Ajax widgets, optional client-side app, and ZK client engine.

Handling large amounts of data

Sometimes you need to resolve the issue of handling a large amount of data on the client side. ZK's grid, listbox, and tree components, which are used to display records of data, have a load-on-demand feature so data is not rendered on the browser unless it's needed in a view. There is also a paging feature whereby large amounts of data could be distributed across multiple pages. With these features, the complexity of presenting a huge amount of data is greatly reduced.


Solutions using ZK

To explore ZK's server+client fusion architecture, you'll walk through a sample proof-of-concept stock viewer application in two different ways: using a pure server-driven solution as a reference, and distributing the event handling to both server and client.

The stock viewer application will read a historical stock record in XML, and will display the data in a tabular format and a line graph. The application will also include a search box that auto-completes a search, such as Google Suggest. Figure 3 shows the application.

Figure 3. Stock view application
Screen showing several stocks, high, opening, low, and closing prices, and volume traded.

Server-side solution using ZK MVC

For the server-driven approach, the sample adapts ZK's Model-View-Controller (MVC) approach.

Model
The model is comprised of three Java classes, two data objects, and a DAO object. A Stock object may correspond to many Price objects.
	public class Stock {
	private int _id;
	private String _name;
	private List<Price> _priceItems = new ArrayList<Price>();
....
//getter and setter methods
}
	
	public class Price {
	private String _date;
	private double _open;
	private double _high;
	private double _low;
	private double _close;
	private int _volumn;
....
//getter and setter methods
}

The StockDAO class parses the historic stock data in data.xml and creates the Stock and Price objects in memory. Each Stock object is added to the linked list "stocks."

             public class StockDAO {
             private List<Stock> stocks = new LinkedList<Stock>();
             public List findAll() {...} // returns all stock items in data.xml
		public Stock getStock(int id) {...}
}
View
The view is implemented using ZK's markup language. The main presentation page, index.zul, is partitioned using border layout. The west division hosts the search box and the list of stock names, and the center division contains the include element that serves as a placeholder for price.zul. The data record for each stock is displayed in the grid component and plotted in the chart component in price.zul.

In the index.zul listing shown in Listing 1:

  • In line 1, the init tag tells the ZK Loader to initialize ZK's Data Binding Manager so a data source can be automatically bound to UI components, and vice-versa.
  • In line 2, apply="StockController" denotes that the StockController class from the default package will serve as the borderlayout component's controller.
  • In line 12, model="@{main$composer.stocks}" translates to setting the listbox with the data model obtained from the StockController class' getStocks() method.
  • From lines 14 to 16, a listitem component is created for each stock object and its name is assigned to the listcell's label.
Listing 1. index.zul
1. <?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
2. <borderlayout id="main" apply="StockController">
3.  	<west title="ZK Finance" size="250px" flex="true"
4. 		splittable="true" minsize="210" maxsize="500" collapsible="true">
5. 		<panel>
6. 			<toolbar>
7. 				<label value="Search:" />
8. 				<textbox id="searchBox" ctrlKeys="#down#up"
9. 					focus="true" sclass="demo-search-inp" />
10. 			</toolbar>
11. 			<panelchildren>
12. 				<listbox id="itemList" model="@{main$composer.stocks}"
13. 					fixedLayout="true" vflex="true">
14. 					<listitem self="@{each='stock'}" value="@{stock}">
15. 						<listcell label="@{stock.name}" />
16. 					</listitem>
17. 				</listbox>
18. 			</panelchildren>
19. 		</panel>
20. 	</west>
21. 	<center>
22. 		<include id="detail"/>
23. 	</center>
24. </borderlayout>

In the price.zul listing shown in Listing 2:

  • In line 1, as before, ZK's Data Binding Manager is initialized here.
  • In line 2, apply="PriceController" denotes that the PriceController class from the default package will serve as the window component's controller.
  • In line 3, model="@{main2$PriceController.prices}" translates to setting the grid with the data model obtained from the PriceController class' getPrices() method.
  • From lines 13 to 20, a row component is created for each price object and its value is assigned to a label.
Listing 2. price.zul
1. <?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
2. <window id="main2" apply="PriceController">
3. 	<grid id="history" model="@{main2$PriceController.prices}" >
4. 		<columns menupopup="auto">
5. 			<column label="Date" />
6. 			<column label="Open" />
7. 			<column label="High" />
8. 			<column label="Low" />
9. 			<column label="Close" />
10. 			<column label="Volumn" />
11.  		</columns>
12. 		<rows>
13. 			<row self="@{each='price'}">
14. 				<label value="@{price.date}"/>
15. 				<label value="@{price.open}"/>
16. 				<label value="@{price.high}"/>
17. 				<label value="@{price.low}"/>
18. 				<label value="@{price.close}"/>
19. 				<label value="@{price.volumn}"/>
20. 			</row>
21. 		</rows>
22. 	</grid>
23. 	<chart id="line" width="500" height="250" type="line"
24. 		fgAlpha="128" model="@{main2$PriceController.cateModel}"/>
25. </window>
Controller
The controllers are classes that extend from ZK's rg.zkoss.zk.ui.util.GenericForwardComposer, which automatically wires the data objects with the UI components.

In the StockController class, which controls the view in the borderlayout component in index.zul:

  • In line 8, the borderlayout with id=main is registered with an onCreate event listener, which sets the default stock item to be shown in the view.
  • In line 13, the listbox with id=itemList is registered with an onSelect event listener, which gets the selected listitem in listbox and sets the include component with id=detail—the page source for displaying the stock data and line plot.
  • In line 18, the textbox with id=searchBox is registered with an onChanging event listener, which iterates through the stock items and returns a list of stocks matching the user's input each time the textbox's value is changed. The event in the argument is cast to org.zkoss.zk.ui.event.InputEvent so the user's input can be assigned to the string key.
  • In line 34, the getStocks() method returns all stock items listed in data.xml.
Listing 3. StockController.java
1. public class StockController extends GenericForwardComposer {	
2. 	Textbox searchBox;
3. 	Listbox itemList;
4. 	Include detail;
5. 	StockDAO dao = new StockDAO();
6. 	private static String DETAIL_URL = "price.zul";
7.  
8. 	public void onCreate$main(){		
9. 		itemList.setSelectedIndex(0);		
10. 		Events.postEvent(new Event(Events.ON_SELECT, itemList));
11. 	}
12. 
13. 	public void onSelect$itemList(){
14. 		int id = ((Stock)itemList.getSelectedItem().getValue()).getId();
15. 		detail.setSrc(DETAIL_URL + "?id=" + id);
16. 	}	
17.  
18. 	public void onChanging$searchBox(InputEvent event) {
19. 		String key = event.getValue();
20. 		LinkedList item = new LinkedList();
21. 		List items = dao.findAll();
22.  
23. 		if (key.trim().length() != 0) {
24. 			for (Iterator iterator = items.iterator(); iterator.hasNext();) {
25. 				Stock st = (Stock) iterator.next();
26. 				if (st.getName().toLowerCase()
27. 						.indexOf(key.toLowerCase()) != -1)
28. 					item.add(st);
29. 			}
30. 			itemList.setModel(new ListModelList(item));
31. 		} else itemList.setModel(new ListModelList(items));
32. 	}
33.  
34. 	public List getStocks(){
35. 		return dao.findAll();
36. 	}
37. }

In the PriceController class, which controls the view in the grid and chart components in price.zul:

  • In line 14, the id parameter appended to the request for price.zul is fetched. The org.zkoss.zk.ui.Executions class is a wrapper for a non-Ajax request.
  • In line 21, the values for the line chart model are set.
  • In line 25, the getPrices() method is declared so it could be called through EL in the grid component in price.zul. This works because the PriceController class extends org.zkoss.zk.ui.util.GenericAutowireComposer, which wires the UI components with the data objects.
Lisitng 4. PriceController
1. public class PriceController extends GenericAutowireComposer {
2. 
3. 	private StockDAO dao = new StockDAO();
4. 	private CategoryModel cateModel;			
5. 	private List items;
6.  
7. 	public PriceController() {
8. 		init();
9. 	}
10. 
11.	public void init() {
12. 		//get stock id
13. 	   	int id = Integer.parseInt((String) 
14. 		Executions.getCurrent().getParameter("id"));		
15. 		Stock stock = dao.getStock(id);
16. 		items = stock.getPriceItems();		
17. 		//create category model for chart
18. 		cateModel = new SimpleCategoryModel();
19. 		for (Iterator iterator = items.iterator(); iterator.hasNext();) {
20. 			Price price = (Price) iterator.next();
21. 			cateModel.setValue(stock.getName(), price.getDate(), 
22. 		Price.getClose());
23. 		}
24. 	}
25. 	public List getPrices(){
26. 		return items;
27. 	}
28. 	public CategoryModel getCateModel() {
29. 		return cateModel;
30. 	}	
31. }

Throughout this example, the asynchronous calls needed to achieve the search box function, and the dynamic data updating in the table and chart, are handled entirely by ZK's Client Engine and AU Engine. Instructions are executed at the server; the client only receives the updates in the UI components and data model.


Server+client fusion solution

Let's look at the same application with the server+client fusion methodology. The obvious candidate for client-side implementation is the search box, where responsiveness is a priority and only the names of the stock items, not their data, need to be parsed and displayed. In this case, the StockController class is no longer needed because the event handling on the search box will be implemented solely at the client. The example modifies index.zul and renames it to hybrid.zul.

In the hybrid.zul listing below, note the following ZK constructs:

  • ZK's client name space must be declared:
    <zk xmlns:w="http://www.zkoss.org/2005/zk/client">
    (The name space w, for widgets, is a ZK convention.)
  • In line 2, the attribute apply="StockController" is taken out of the borderlayout because the search box and the listbox that show the stock names will be updated directly at the client.
  • In line 8, the textbox's onChanging event is now declared to be handled at the client with the annotation w:
  • In line 9, you get the listbox and invoke its update() method. The expression this.$f(‘list') is equivalent to inp.getFellow("list") in Java, which gets the listbox component with id="list".
  • In line 13, the bind_ callback method from the class zk.Widget is overridden to run the update() method and set the first list item as the selected one after the listbox is bound to the DOM tree.
  • In line 28, zUtl.parseXML() is a utility method for parsing XML documents. jq() is made the notation for the jQuery selector in ZK so that jQuery's notation $() may still be used whenever applicable.
  • In line 38, a new listitem widget is created with its label value and ID set for each stock item, and is appended to the listbox as its children widgets.
  • From lines 56 to 70, the listbox's onSelect event is handled directly by implementing a service method for the asynchronous request at the server. The example retrieves the uuid for the listitem being selected and appends it to the request for the price.zul page, which displays the stock data and the line chart.
Listing 5. hybrid.zul
1. <zk xmlns:w="http://www.zkoss.org/2005/zk/client">
2. <borderlayout id="main">
3. 	<west title="ZK Finance" size="250px" flex="true"
4. 	splittable="true" minsize="210" maxsize="500" collapsible="true">
5. 	<panel>
6. 		<panelchildren>
7. 			<textbox id="inp">
8. 			<attribute w:name="onChanging">
9. 				this.$f('list').update(event.data.value);
10. 	 		</attribute>
11. 			</textbox>
12. 			<listbox id="list" onSelect="" rows="10" width="300px">
13. 			<attribute w:name="bind_">
14. 			function (desktop, skipper, after) {
15. 				this.$bind_.apply(this, arguments);		
16. 				var self = this;
17. 				after.push(function () {
18. 				self.update();
19. 				self.firstChild.setSelected(true);
20. 				});
21. 				}
22. 			</attribute>
23. 			<attribute w:name="update"><![CDATA[
24. 
25. 			(function () {
26. 			var data;
27. 			function loadData(w) {
28. 	var xmlDoc = zk.xml.Utl.parseXML(jq(w).html().replace(/<!--|-->/g,'').trim()),
29. 			ids = xmlDoc.getElementsByTagName("id"),
30. 			labels = xmlDoc.getElementsByTagName("name");
31.  			data = [];
32. 			jq(ids).each(function (i) {
33. 			data.push({id: this.firstChild.nodeValue, label:
34. 			labels[i].firstChild.nodeValue});
35. 			});
36. 			}
37. 
38. 			function createItems (listbox, data) {
39. 			if (!data.length) return;
40. 			jq(data).each(function () {
41. 	listbox.appendChild(new zul.sel.Listitem({label: this.label, uuid: this.id}));
42. 			});
43. 			}
44. 			return function (txt) {
45. 				txt = txt || '';
46. 				if (!data) loadData(this.$f('data'));
47. 				this.clear();
48. 				createItems(this, jq.grep(data, function (item) {
49. 			return item.label.toLowerCase().indexOf(txt.toLowerCase()) != -1;
50. 			}));
51. 			this.stripe();
52. 			};
53. 			})()
54. 			]]></attribute>
55. 			</listbox>
56. 	<zscript>
57. 	public class MyService implements org.zkoss.zk.au.AuService {
58. 	public boolean service(org.zkoss.zk.au.AuRequest request, boolean everError) {
59. 		final String cmd = request.getCommand();
60. 		if (cmd.equals(Events.ON_SELECT)) {
61. 		String uuid = ((List)request.getData().get("items")).get(0);
62. 		System.out.println("selected:" + uuid);
63. 		content.setSrc("price.zul?id=" + uuid);
64. 		return true;
65. 		}
66. 		return false;
67. 		}
68. 		}
69. 	list.setAuService(new MyService());
70. </zscript>
71. <include id="data" src="data.xml" comment="true"/>
72. </panelchildren>
73. </panel>
74. </west>
75. <center>
76. 	<include id="content" src="price.zul?id=1"/>
77. </center>
78. </borderlayout>
79. </zk>

You can download the sample code. Note the improvement in the search box's responsiveness.


Summary

In this article, you explored how to improve your Ajax development in ZK by taking advantage of the merits of both server- and client-side programming. ZK synchronizes the application states at both sides automatically. You can enjoy the productivity of Java EE technologies, while still having the choice to implement client-side functions. Your implementation approach becomes reliant on the requirements of the enterprise application you build, and not on the merits or constraints of the development framework.


Download

DescriptionNameSize
Sample code for this articlezk5Client_ServerFusion.zip9018KB

Resources

Learn

  • "Rich Internet applications using ZK" (developerWorks, Jan 2010) introduces you to ZK and gives you a real-world example of its use running on Apache Tomcat and connecting to a MySQL database.
  • Read about ZK 5.0 and jQuery and ZK 5.0 and jQuery part 2 and get an introduction, a demo, how to implement the ZK controls, how to construct an example, and much more.
  • Learn more about client namespace and client-side programming.
  • Read about ZK Widget, the super class of all widget classes.
  • ZK MVC Made Easy discusses in detail the three utility classes and three helper methods provided by ZK that will help you easily write applications in the Model-View-Controller pattern.
  • Learn about ZK data binding (a mechanism that automates the data-copy plumbing code between UI components and the data source) and the data binding manager.

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, Java technology
ArticleID=551078
ArticleTitle=Enhance Ajax development with a fusion of jQuery, ZK, and Java code
publish-date=10192010