jQuery、ZK、Java コードを融合させ、Ajax 開発を強化する

サーバー・サイド・プログラミングとクライアント・サイド・プログラミングの両方のメリットを手軽に活用する

jQuery を使用すると、サーバー・サイドの Java™ アプリケーションと容易に通信をすることができます。しかしエンタープライズ Web アプリケーションを作成する場合には、コードが複雑になり、また jQuery を使用してサーバーとクライアントとの間でセキュアに通信しようとすると、非常に時間がかかり、エラーも発生しがちになります。アプリケーション全体を Pure Java コードで実装することができれば、その方がはるかに容易です。クライアント・サイドで制御を行うことでもたらされるあらゆるメリットを活用したり、ビジネス・ロジックを制御したりすることができたらよいと思いませんか?この記事では、ZK ツールと Java EE (Java Platform, Enterprise Edition) 技術を使用し、クライアント・サイドの機能を犠牲にせずに Ajax (Asynchronous JavaScript + XML) アプリケーション開発を強化する方法について学びます。

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 は米国ユタ州のソルトレーク・シティーにある University of Utah の修士号を取得しています。彼は米国とインドで中小企業でも大企業でも働いたことがあり、技術者として、また監督者として多様な業務を行ってきました。彼は現在、IBM Software Group の Lotus 部門で働いています。



2010年 10月 19日

はじめに

jQuery により、CSS (Cascading Style Sheets) 構文の中でセレクターを使用して DOM (Document Object Model) 要素を取得したり、それらの要素を操作したりする方法がよく使われるようになりました。jQuery を使うことでもたらされる数あるメリットの 1 つは、複雑な DOM ツリーを JavaScript でトラバースする苦労がなくなることです。

jQuery は、コンパクトで高速な動作が可能なクロスブラウザーの JavaScript ライブラリーで、jQuery を使うことで Web アプリケーションや Web ページを容易に作成できるようになります。jQuery により、アニメーションの作成、サーバー・リクエストに対する通信、文書のトラバース、イベント処理を単純化することができます。

ZK はイベント・ドリブン方式のコンポーネント・ベースの Ajax フレームワークであり、Java でプログラミングされ、Java EE 技術と統合されていることで知られています。ZK により、デスクトップ・プログラミングの経験を Ajax に生かすことができます。HTML を好む人の場合には、マークアップや式言語 (EL) を使って ZK の UI を組み立てることができます。

この記事では、サーバー・サイドの Java コードと jQuery とを組み合わせることで、いかにしてエンタープライズ Ajax アプリケーション開発の難題を解決できるかについて説明します。また、jQuery と ZK が持つ技術を組み合わせることで、リッチで応答性の高い UI エクスペリエンスを容易かつ効率的に実現することができます。

この記事で使用するサンプル・コードは、ダウンロードすることができます。


Ajax アプリケーション開発の難題

エンタープライズ・クラスの Ajax アプリケーションを作成する場合、通常は以下のような難題に直面します。

複雑さ
Ajax は複雑です。Ajax の通信パターンでは、DOM の要素が個別に更新される際、Web ページ全体を更新する必要がありません。

エンタープライズ・アプリケーションの場合、高度なビジネス・ロジックをサーバー・サイドからクライアント・サイドへと集め、それぞれの Ajax 呼び出しを手動で作成するのは非常に大変な作業です。

サーバー・サイド・プログラミング
サーバー・サイドの Ajax ソリューションでは、クライアントのリソースを活用して応答性の高いユーザー・エクスペリエンスやオフライン機能を実現することができず、コンピューティングやデータ・ストレージをクライアントに分散することもできません。

また、サーバー・サイドの Ajax ソリューションでは、サーバー上のメモリー・フットプリントを減らすことはできないため、アプリケーションのスケーラビリティーを向上させることができません。

クライアント・サイド・プログラミング
クライアント・サイド・プログラミングでは、セキュリティーの懸念事項や開発コストが一層増加します。ビジネス・ロジックや機密データがブラウザー上でオープンにされ、アプリケーションが攻撃を受けやすくなります。

クライアント・サイド・プログラミングでは、広範にわたる JavaScript 実装が必要であり、そうした実装は Java EE 技術によるアプリケーション開発に慣れた人にとっては楽ではありません。

巨大なデータ
大量のデータを UI 階層によってビューに表示する必要がある場合、もう 1 つ一般的な問題が起こります。例えば、通常の HTML の表を考えてみてください。データ・ソースが大規模になると、下記のいずれかを選択しなければなりません。
  • 大規模なデータ・セットをプリロードすることにより、ブラウザーのキャッシュが過負荷になり、トラフィックの速度が低下するリスクをとる。
  • 何らかのメカニズムを手動でサーバーに実装し、ユーザーが要求した場合には対象データのサブセットをいつでも表示できるようにする。

これらの難題を克服するための有効なソリューションは、クライアントの状態とサーバーの状態を自動的に同期させるフレームワークを使用することです。サーバー・サイドでは、あらゆるセキュアな Java EE 技術を活用する一方、クライアント・サイドのコンピューティング能力を利用することで、応答性や UI 制御を改善することができます。


サーバーとクライアントを融合した ZK のアーキテクチャー

ZK の画期的なアーキテクチャーにより、サーバー・サイドで利用可能な技術とクライアント・サイドで利用可能な技術のすべてを最大限に活用することができます。必要な場合には、クライアント・サイドのウィジェットに直接アクセスすることができます。このセクションでは、サーバーとクライアントを融合した ZK のアーキテクチャーのメリットについて、そのいくつかを概説します。

ZK ローダーと ZK AU エンジン

ZK ローダーは URL リクエストに対して以下のように動作します。

  • リクエストされたページ上に UI コンポーネントを作成します。
  • 必要なデータをそれらの UI コンポーネントにロードします。
  • それらの UI コンポーネントを HTML ページ上に描画します。
  • その HTML ページを ZK のクライアント・エンジンと共にクライアントに返送します。

ZK の AU (Asynchronous Update) エンジンとクライアント・エンジンによって Ajax 通信が処理されるため、開発者は Ajax 呼び出しの処理にかかわる複雑さを気にする必要がありません。図 1 は、ZK ローダー (ZK Loader)、ZK AU エンジン (ZK AU Engine)、ZK クライアント・エンジン (ZK client engine) を示しています。

図 1. ZK の融合アーキテクチャーの概要
この図では、URL リクエストと ZK リクエストがクライアント・エンジンからサーバーに送信され、サーバーから HTML ページと ZK レスポンスが返される流れが表現されています。

Ajax の複雑さを解決する

ZK のクライアント・エンジンと AU エンジンは、野球に例えると投手と捕手の役割を果たし、ZK のイベント・キューは処理対象のイベントに対するパイプラインとして動作します。この結果、非同期イベントの処理がデスクトップ・プログラミング並みに単純化されます。

サーバー・サイド技術を活用する

サーバーは一連の ZK コンポーネントを JVM の中に保持します。これらの ZK コンポーネントはブラウザーの中に JavaScript オブジェクトとして存在する一連の ZK ウィジェットに対応しているため、ページの状態はサーバー・サイドとクライアント・サイドで同期された状態に保たれます。ビジネス・ロジックや機密データを扱うイベント処理は、すべてサーバー・サイドで行われます。イベント処理の結果としてサーバー・サイドで ZK コンポーネントの状態が変化した場合、その変化がクライアント・サイドの ZK ウィジェットに反映されるのは、そのイベント処理が完了した時点のみです。ビジネス・ロジックがクライアント・サイドに公開されることは決してありません。

クライアント・サイド技術を活用する

ZK ウィジェットはクライアント・サイドの JavaScript オブジェクトであり、jQuery で作成されています。そのため ZK ウィジェットには jQuery に付随する動作がすべて継承されています。コンポーネントの完全な表現とコンポーネントの状態はクライアントとサーバーの両方にあるため、アプリケーションのプログラミングをサーバー・サイドで行うこともクライアント・サイドで行うこともできます。図 2 はその例を示しています。

図 2. ZK のクライアント・サイド技術
この図には、DOM、ZK の Ajax ウィジェット、オプションとしてのクライアント・サイド・アプリケーション、ZK クライアント・エンジンが表示されており、それぞれの間が両方向の矢印で結ばれています。

大量のデータの処理

場合によると、クライアント・サイドで大量のデータを処理するという問題を解決しなければならない場合があります。ZK の grid コンポーネント、listbox コンポーネント、tree コンポーネントはデータのレコードを表示するために使用されますが、これらのコンポーネントにはオンデマンドでデータをロードする機能があります。そのため、ビューの中で必要にならない限り、データはブラウザー上に描画されません。ZK にはまた、大量のデータを複数のページに分散するページング機能もあります。これらの機能を利用することで、大量のデータを表示する上での複雑さを大幅に軽減することができます。


ZK を使用したソリューション

サーバーとクライアントを融合した ZK のアーキテクチャーを説明するために、株価表示アプリケーションを概念検証の例に上げ、このアプリケーションを 2 つの異なる方法で実現します。純粋にサーバー主導のソリューションをリファレンスの方法として使用し、もう一方の方法ではサーバーとクライアントの両方にイベント処理を分散します。

この株価表示アプリケーションは XML の株価レコードの履歴を読み取り、そのデータを表形式と折れ線グラフで表示します。またこのアプリケーションには、Google Suggest のように検索用語を自動補完する検索ボックスも含まれています。図 3 はこのアプリケーションを示しています。

図 3. 株価表示アプリケーション
この画面には何件かの株価が表示されており、それらの高値、始値、安値、終値、出来高も表示されています。

ZK の MVC を使用したサーバー・サイド・ソリューション

サーバー主導の手法として、このサンプルではZK の MVC (Model-View-Controller) の手法を採用しています。

モデル
このモデルは、3 つの Java クラス、2 つのデータ・オブジェクト、1 つの DAO オブジェクトによって構成されています。1 つの Stock オブジェクトが多くの Price オブジェクトに対応する場合があります。
	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
}

StockDAO クラスは data.xml の中にある株価の履歴データを解析し、メモリー内に Stock オブジェクトと Price オブジェクトを作成します。各 Stock オブジェクトは LinkedList のオブジェクト 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) {...}
}
ビュー
ビューは ZK のマークアップ言語を使って実装されます。メインの表示ページ (index.zul) はボーダー・レイアウトを使って分割されます。west ブロックには検索ボックスと株式銘柄の一覧が配置され、center ブロックには、price.zul のプレースホルダーとして機能する include 要素が配置されます。各株式のデータ・レコードは grid コンポーネントの中に表示され、また price.zul の chart コンポーネントにプロットされます。

リスト 1 に示す index.zul の内容は以下のとおりです。

  • 1 行目の init タグは ZK ローダーに対し、ZK のデータ・バインディング・マネージャーを初期化するように指示します。この指示によって、データ・ソースは自動的に UI コンポーネントにバインドされ、また逆に UI コンポーネントがデータ・ソースにバインドされます。
  • 2 行目の apply="StockController" は、デフォルト・パッケージの StockController クラスが borderlayout コンポーネントのコントローラーとして動作することを表しています。
  • 12 行目の model="@{main$composer.stocks}" は、StockController クラスの getStocks() メソッドから取得したデータ・モデルによって listbox を設定することを意味しています。
  • 14 行目から 16 行目の listitem コンポーネントは各 stock オブジェクトに対して作成され、その stock オブジェクトの名前が listcell のラベルに割り当てられます。
リスト 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>

リスト 2 に示す price.zul の内容は以下のとおりです。

  • 1 行目では、先ほどと同じように ZK のデータ・バインディング・マネージャーが初期化されています。
  • 2 行目の apply="PriceController" は、デフォルト・パッケージの PriceController クラスが window コンポーネントのコントローラーとして動作することを表しています。
  • 3 行目の model="@{main2$PriceController.prices}" は、PriceController クラスの getPrices() メソッドから取得したデータ・モデルによってグリッドを設定することを意味しています。
  • 13 行目から 20 行目の row コンポーネントは各 price オブジェクトに対して作成され、この price オブジェクトの値がラベルに割り当てられます。
リスト 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>
コントローラー
コントローラーは ZK の rg.zkoss.zk.ui.util.GenericForwardComposer を継承するクラスです。rg.zkoss.zk.ui.util.GenericForwardComposer により、データ・オブジェクトが UI コンポーネントと自動的に接続されます。

StockController クラスは index.zul の borderlayout コンポーネントの中でビューを制御しています。リスト 3 に示す StockController クラスの内容は以下のとおりです。

  • 8 行目で、id=mainborderlayoutonCreate イベント・リスナーに登録されています。この onCreate イベント・リスナーにより、デフォルトでビューに表示される株式が設定されます。
  • 13 行目で、id=itemListlistboxonSelect イベント・リスナーに登録されています。この onSelect イベント・リスナーは listbox の中で選択された listitem を取得し、id=detail の include コンポーネント (株価データと折れ線グラフを表示するためのページ・ソース) を設定します。
  • リスト 18 で、id=searchBox の textbox が onChanging イベント・リスナーに登録されています。この onChanging イベント・リスナーは株式に対して繰り返し処理を行い、テキストボックスの値が変更されるたびに、ユーザーが入力した内容に一致する株式のリストを返します。引数のイベントは org.zkoss.zk.ui.event.InputEvent にキャストされ、ユーザーが入力した内容は key というストリングに割り当てられます。
  • 34 行目で、getStocks() メソッドは data.xml に記載されているすべての株式を返します。
リスト 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. }

PriceController クラスはグリッドの中のビューと、price.zul の chart コンポーネントを制御します。リスト 14 に示す PriceController クラスの内容は以下のとおりです。

  • 14 行目で、price.zul に対するリクエストに追加された id パラメーターを取得しています。org.zkoss.zk.ui.Executions クラスは Ajax 以外のリクエストに対するラッパーです。
  • 21 行目で、折れ線グラフ・モデルの値を設定しています。
  • 25 行目で、getPrices() メソッドを宣言しています。この宣言により、price.zul の grid コンポーネントの式言語で getPrices() メソッドを呼び出すことができます。なぜなら、PriceController クラスは (UI コンポーネントをデータ・オブジェクトに接続する) org.zkoss.zk.ui.util.GenericAutowireComposer を継承しているからです
リスト 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. }

この例全体を通して、検索ボックス機能を実現するために必要な非同期呼び出しと、表データおよびグラフ・データの動的な更新は、すべて ZK のクライアント・エンジンと AU エンジンによって処理されています。命令はサーバーで実行され、クライアントは単純に UI コンポーネントとデータ・モデルの中で更新情報を受信しているにすぎません。


サーバーとクライアントを融合したソリューション

同じアプリケーションを、サーバーとクライアントを融合した手法で実現してみましょう。明らかにクライアント・サイドで実装した方が適切な候補として、検索ボックスがあります。検索ボックスでは応答性が重要であり、株式の名前のみを解析して表示すればよく、株価データの解析や表示は必要ありません。この場合には StockController クラスは必要ありません。検索ボックスのイベント処理はすべてクライアントで実装されるからです。この例では index.zul を変更し、hybrid.zul とリネームします。

リスト 5 に示す hybrid.zul のリストでは、以下の ZK 構成体に注目してください。

  • ZK のクライアント名前空間を宣言する必要があります。
    <zk xmlns:w="http://www.zkoss.org/2005/zk/client">
    (ウィジェットの名前空間を w で表すのは ZK の規約です。)
  • 2 行目で、borderlayout から apply="StockController" 属性が削除されています。これは株式の名前を表示する検索ボックスとリストボックスがクライアントによって直接更新されるためです。
  • 8 行目で、textboxonChanging イベントが、w: というアノテーションによってクライアントで処理されるように宣言されています。
  • 9 行目で、listbox を取得し、listboxupdate() メソッドを呼び出しています。this.$f(‘list') という表現は Java の inp.getFellow("list") と等価であり、この表現によって id="list"listbox コンポーネントを取得しています。
  • 13 行目で、zk.Widget クラスの bind_ という callback メソッドはオーバーライドされて update() メソッドを実行し、また listbox が DOM ツリーにバインドされた後、最初のリスト項目が選択された状態になるように設定されています。
  • 28 行目の zUtl.parseXML() は XML 文書を構文解析するためのユーティリティー・メソッドです。ZK での jQuery セレクターの表記として jq() が指定されているため、必要な場所ではどこでも jQuery の表記 $() を使用することができます。
  • 38 行目で新しい listitem ウィジェットが作成され、このウィジェットのラベルの値と ID は各株式に対応して設定されています。また listitem ウィジェットは listbox の子ウィジェットとして listbox に追加されています。
  • 56 行目から 70 行目で、listboxonSelect イベントは、非同期リクエストに対するサービス・メソッドをサーバーで実装することによって直接処理されています。この例では、選択された listitemuuid を取得し、price.zul ページに対するリクエストに追加しています。そして price.zul ページによって株価データと折れ線グラフが表示されます。
リスト 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>

このサンプル・コードはダウンロードすることができます。検索ボックスの応答性が改善されていることに注目してください。


まとめ

この記事では、ZK による Ajax 開発を改善する方法として、サーバー・サイドのプログラミングとクライアント・サイドのプログラミングの両方のメリットを活用する方法について説明しました。ZK により、サーバー・サイドとクライアント・サイドのアプリケーションの状態を自動的に同期させることができます。Java EE 技術の生産性の高さを生かせる一方、クライアント・サイドの機能を実装する選択肢が相変わらず残されています。実装の手法は作成対象のエンタープライズ・アプリケーションの要件に依存するようになり、開発フレームワークのメリットや制約に依存することがなくなります。


ダウンロード

内容ファイル名サイズ
Sample code for this articlezk5Client_ServerFusion.zip9018KB

参考文献

学ぶために

  • ZK を使ったリッチ・インターネット・アプリケーション」(developerWorks、2010年1月) は ZK を紹介し、ZK を使って作成した実際のアプリケーションを Apache Tomcat 上で実行して MySQL データベースに接続する例について説明しています。
  • ZK の資料として、「ZK 5.0 and jQuery」と「ZK 5.0 and jQuery part 2」を読んでください。ZK の紹介、デモ、ZK の制御の実装方法、サンプル・アプリケーションの作成方法など、豊富な内容が含まれています。
  • クライアント名前空間とクライアント・サイド・プログラミングについて学んでください。
  • あらゆるウィジェット・クラスのスーパークラス、ZK.Widget の資料を読んでください。
  • ZK MVC Made Easy」は、ZK に用意された 3 つのユーティリティー・クラスと 3 つのヘルパー・メソッドを詳細に説明しています。これらのクラスやメソッドにより、Model-View-Controller のパターンに従って容易にアプリケーションを作成することができます。
  • ZK のデータ・バインディング (UI コンポーネントとデータ・ソースの間でデータをコピーするための接続コードを自動化するメカニズム) とデータ・バインディング・マネージャーについて学んでください。

製品や技術を入手するために

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development, Java technology
ArticleID=587553
ArticleTitle=jQuery、ZK、Java コードを融合させ、Ajax 開発を強化する
publish-date=10192010