DWR(3)

DWRの基本的な動きがわかってきたので、何か実際に作ってみることにした。選んだのはこの間XMLHttpRequestで作ったインクリメンタル検索機能付きリストボックス。

まずはサーバ側の改造。

package test;
import java.util.ArrayList;
public class ProductList {
    public ArrayList getItems(String key) {
        String[] pname = { "130", "230Cs", "235", "240", "240X", "240Z", "310", "310E", "315D",
//                                              : (途中ry
                "TransNote", "X20", "X21", "X22", "X23", "X24", "X30", "X31", "X32", "X40", "X41" };
        int keylen = key.length();

        // 結果を格納するarray
        ArrayList result = new ArrayList();

        // ""以外が選択されていればoptionデータを追加
        if (key != null && !key.equals("")) {
            for (int i = 0; i < pname.length; i++) {
                if (pname[i].length() >= keylen && key.equals(pname[i].substring(0, keylen))) {
                    result.add(new String[] { "code_of_" + pname[i], pname[i] });
                }
            }
        }
        return result;
    }
}

サーブレットだったProductChangedに対してこれはPOJO。resultにadd()している各String型配列の0番目がリストボックスで選択されたとき返す値、1番目が表示させるテキスト。これをDWRがinstallされていてる環境へ追加し、さらにdwr.xmlにも以下の記述を追加する。

<create creator="new" javascript="Product">
    <param name="class" value="test.ProductList"/>
</create>

この状態でhttp://hogehoge/[WEB-APP-NAME]/dwr/test/Productをアクセスすると、このtest.Productのテストページが表示される。このページには

  • このクラスをブラウザからアクセスするときに必要となるJavaScriptのファイル名(ソース名)
  • 公開されているメソッド名のリスト
  • 問題が発生したときの対処方法

などが記載されている。上記リストにはgetItems()も含まれているが、ブラウザ上から引数を与えて実行させ、帰ってくる値をチェックすることもできる。これ便利。

そしてクライアント側はこんな感じ。自分でXMLHttpRequestを操作するのに比べるとだいぶすっきり。

<html lang="ja">
<head>
<title>List test</title>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<script type='text/javascript' src='/dwrsample/dwr/interface/Product.js'></script>
<script type='text/javascript' src='/dwrsample/dwr/engine.js'></script>
<script type='text/javascript' src='/dwrsample/dwr/util.js'></script>
<script type="text/javascript">

</script>
</head>
<body onload="startup();">
<form name="form1">
製品名:<BR>
<input type="text" id="pname" STYLE="width: 150px;" onkeyup="getNewProductName()"><BR>
<select name="productname" id="productname" STYLE="width: 150px;" size=5>
	<option value=""></option>
</select>
<P>
</form>
</body>
</html>

上から見ていくと、FormがLoadされたとき実行するstartup()から呼び出されるDWRUtil.useLoadingMessage()は、DWRを実行しているとき"Loading"というメッセージをGmail風にWindowの右上に表示するためのもの。残念ながら表示されるメッセージは"Loading"固定らしい。

テキストフィールドのonkeyupイベントで実行するgetNewProductName()では、DWRが生成したProxy JavaScript(/dwrsample/dwr/interface/Product.js)を経由してサーバ上のProduct#getItems()を呼び出す。引数の先頭にあるpopulateListは、このgetItems()終了後実行する関数(コールバック関数)。$()も関数で、引数で与えられたidに該当するHTML要素を探して返す。document.getElementById("pname")みたいなもの。でもソースを見ると引数は任意個OKで、その場合の戻り値はArrayとなっている。

コールバックされるpopulateListでは、最初にDWRUtil.removeAllOptions()で指定されたidの要素のoptionを全て削除する。ソースを見るとselectのほか、ul, olもOKっぽい。そしてaddOptions()で"productname"のoptionにdataの内容をセットする。このdataはgetItems()の返したArrayListになる。0, 1は何かというと、optionのvalueと表示するテキストがdataの各要素のそれぞれ何番目なのかを表す添字。はじめ何を指定すればいいのかわからなく困ったけど、これもソースを見たら一発でわかりましたw。

一応IE6.0/FireFox1.0で動きます。