java.sun.comから,こんな記事が掲載されている。
「Accessing Resources From JavaServer Faces Custom Components」 – java.sun.com
JSFのカスタムコンポーネントで,Ajaxによるファイルアップロード系の処理をするためにShale RemotingやDojoを使った例である。全体のコードが掲載されておらず,ポイントしかわからないかもしれない。もし全コードを見渡したい人は,「Java PetStore 2.0ea1のための環境準備」を参考にして,PetStoreのコードを読むと良いだろう(すでにea3がリリースされているっぽい)。
- Posted:
- 01.05.2007
- Category:
- Shale

JSFの実行時の環境をシミュレートした状態で単体テストを可能にしてくれるShale Test Frameworkについて,全4回のエントリで紹介した。
「
JSFアプリケーションの単体テスト with Shale Test Framework (1)」
[全般] Shale Test Frameworkの紹介。
「
JSFアプリケーションの単体テスト with Shale Test Framework (2)」
[全般] 題材の紹介とEclipseプロジェクトの準備。
「
JSFアプリケーションの単体テスト with Shale Test Framework (3)」
[全般] テストクラスの解説(前準備から対象メソッドコールまで)。
「
JSFアプリケーションの単体テスト with Shale Test Framework (4)」
[全般] テストクラスの解説(検証処理とjson-libの使い方)。
JSFは来年急速に普及することが予想される。柔軟な機構とEoDを見据えたJSFを更に発展させ,実装者が迷いのない開発を行うことができるように,そして少しでも手数が少なく,それでいて有効な単体テストができるように,Shale Test Frameworkは是非とも使いこなせるようにしておきたいライブラリである。
日々の開発に役立てて欲しい。
- Posted:
- 12.26.2006
- Category:
- Shale

Shale Test Framework(STF)を紹介しているエントリも,早くも3回目になってしまった。前回のエントリでは,テストメソッドの説明の途中で強引に終わらせてしまった。今回はその続きを見ていこう。
まず,テストメソッドのソースコードを再び示しておこう。前回のエントリでは,テスト対象のgetRightSelectItems()メソッドを呼び出すところまで解説した。
今回のテスト対象のManagedBeanのメソッドでは,ResponseWriterオブジェクトに対して文字列をwriteしている。その検証のためには,テストメソッドからwriteされた文字列を取得する必要がある。

AbstractJsfTestCaseクラスが提供するResponseWriterオブジェクトは,実際はMockResponseWriterクラスのインスタンスであり,これはMockRenderKitクラスが生成する。HttpServletResponseオブジェクトに関してもモッククラスが提供されていて,getWriter()メソッドで得られるWriterオブジェクトに関しても,MockPrintWriterクラスのインスタンスとなっている。MockPrintWriterオブジェクトは,CharArrayWriterオブジェクトに対して出力することが規定されているので,結果としてResponseWriterオブジェクトに対して出力された文字列は,CharArrayWriterオブジェクトの内部に蓄積され,MockPrintWriter#content()メソッドを使用して取り出すことができる。
話を元に戻そう。SelectItemsProducer#getRightSelectItems()メソッドでは,ResponseWriterオブジェクトに対して,コンテントタイプを”text/javascript;charset=UTF-8″というように指定している。これを4行目で検証している。AbstractJsfTestCaseクラスでは,実行時に存在するHttpServletResponseオブジェクトを,MockHttpServletResponseクラスのインスタンスとして,responseインスタンスフィールドにセットしてくれている。responseフィールドのgetContentType()メソッドの戻り値について,正しくコンテントタイプがセットされたかどうかを検証できる。
さて,いよいよ出力されたJSON形式のテキストの検証だが,テキストのまま検証するのはかなり難しく,手間である。幸いにも,JSON形式のテキストをパースしてオブジェクトとして扱うことを可能にするライブラリが,今日ではいくつか提供されている。今回は,json-libというライブラリを使ってみよう。

と,その前に,SelectItemsProducer#getRightSelectItems()メソッドが出力した文字列を取得しなければならない。その処理を,getContent()メソッドにまとめてみた。
responseフィールドのgetWriter()メソッドの戻り値をMockPrintWriterクラスでダウンキャストする。そして,content()メソッドを呼び出して,出力された文字列を文字配列として取得,その後1つの文字列として返却している。
ここで,SelectItemsProducer#getRightSelectItems()メソッドが出力するテキストがどういうものかを把握しておこう。

大括弧で括られていることから,配列形式であることがわかる。その中に,”label”や”value”という要素が含まれている。json-libでは,配列をJSONArrayクラスで,個々の要素をJSONObjectクラスで,それぞれ扱うことが出来る。
まずは,getContent()メソッドで得られた文字列全体を,JSONArrayオブジェクトにパースする。それが5行目である。JSONArray#fromString()メソッドを使って,JSONArrayオブジェクトに変換する。仮に,出力結果がJSON形式として不正なものだった場合は,パースに失敗し,JSONException例外が発生する。このパース作業によって,出力結果がJSON形式として妥当かどうかを検証できる。
パースした結果のJSONArrayオブジェクトには,各要素をJSONObjectオブジェクトとして保持しているはずである。まずは,その件数を検証する。6行目において,JSONArray#length()メソッドを呼び出すことで要素の個数を取得し,宇都宮線と高崎線の2個かどうか検証している。
次に,各要素の検証だが,これはassertSelectItem()メソッドにまとめてみた。
JSONArrayオブジェクトのgetJSONObject()メソッドにインデックスを渡すことによって,各要素をJSONObjectクラスのインスタンスとして取得することができる。さらに,JSONObject#getString()メソッドに名前を渡すことで,それに対する値を得ることができる。ここで検証したい値は,”label”と”value”の値。引数に正しい値を指定して,それぞれが一致するかどうかを検証している。
STFを使用することによって,JSFの実行時の環境をシミュレートした上で,テストメソッドを記述することができる。特に,Shale Remotingを使ったManagedBeanや,JSFコンポーネントを自作した場合について,STFは手放せないライブラリとなるはずだ。
Shale Remotingと合わせて,是非試してみて欲しい。
- Posted:
- 12.26.2006
- Category:
- Shale

前回のエントリでは,Shale Test Framework(STF)を試すための題材を紹介した。さらに,STFを試すためのtest-stfプロジェクトも提供を行った。入手していない方は,是非ここからダウンロードして欲しい。test-stfプロジェクトには,「JSF+AjaxでUIコンポーネント開発 with Shale Remoting」で取り上げたdouble-selectコンポーネントに選択肢を提供するManagedBean,SelectItemsProducerクラスを含めた。SelectItemsProducerクラスには,単体テスト対象のgetRightSelectItems()メソッドを設置してある。今回は,このgetRightSelectItems()メソッドをテストするためのテストケースクラスを,STFを前提に紹介していこうと思う。
STFでは,JSFの実行時環境をシミュレートするために,AbstractJsfTestCaseクラスを提供している。JSFのAPIに依存したコードをテストするには,このクラスを継承してテストケースを作成すれば良い。
SelectItemsProducerTestクラスをAbstractJsfTestCaseクラスを継承して作成している。AbstractTestCaseクラスはデフォルトコンストラクタを持っていないため,SelectItemsProducerTestクラスでもname引数を持つコンストラクタを定義している。
そして次がちょっとしたハマりポイントなのだが,AbstractJsfTestCaseクラスを使用する場合は,suite()メソッドをオーバーライドする必要がある。これを行わないと,いくらテストメソッドを作っても,それが実行されることはない。suite()メソッドの中では,自分自身のクラスオブジェクトを元にしたTestSuiteオブジェクトを生成して返す。これによって,めでたくテストメソッドが実行されるようになる。
次に,テスト対象のSelectItemsProducerオブジェクトを準備しよう。
SelectItemsProducerオブジェクトをインスタンスフィールドとして定義し,setUp()メソッドおよびtearDown()メソッドによってライフサイクルを管理している。
ここで注意点。AbstractJsfTestCaseクラスでシミュレートされるJSF実行時環境は,AbstractJsfTestCase#setUp()メソッドで準備され,AbstractJsfTestCase#tearDown()メソッドで後始末が行われる。よって,具体的なテストケースクラスでは,setUp()メソッドおよびtearDown()メソッドのオーバーライドを行った場合は,必ずスーパークラスの処理を呼び出してあげなければならない。これを忘れると,JSFとは関係ない単なるJUnitテストケースクラスと成り下がるので,気をつけたい。
各テストメソッドの実行の直前に呼び出されるsetUp()メソッドの作用によって,JSFでおなじみのFacesContextオブジェクトやApplicationオブジェクトなどが準備完了となる。あとは,テスト対象のメソッドをテストメソッド内で呼び出して,結果を検証するだけ。なんとも簡単だ。
AbstractJsfTestCaseクラスが提供してくれるJSF関連のオブジェクトを,以下に示しておこう。括弧内に,実際の型も示しておく。これらのモッククラスは,STFで提供されるものだ。
- application (MockApplication)
- config (MockServletConfig)
- externalContext (MockExternalContext)
- facesContext (MockFacesContext)
- lifecycle (MockLifecycle)
- request (MockHttpServletRequest
- response (MockHttpServletResponse)
- servletContext (MockServletContext)
- session (MockHttpSession)
では,テストメソッドを見ていこう。下のコードは,fvパラメータ値が”1″だった際に,JRの選択肢がJSON形式で正しく得られるかどうかを確認するためのコードである。
外部(Webブラウザ)からサブミットされたリクエストパラメータは,ExternalContextオブジェクトに格納される。”fv”パラメータの値に関しても,実行時をシミュレートしてあげるためには,テスト対象のメソッドを呼び出す前に,ExternalContextオブジェクトに値を詰めてあげないといけない。

AbstractJsfTestCase#setUp()メソッドにて,ExternalContextオブジェクトはMockExternalContextクラスのインスタンスとしてしっかり準備完了状態になっている。MockExternalContextクラスには,テスト用のリクエストパラメータ値をセットアップするために,addRequestParameterMap()メソッドが提供されている。このメソッドを使用して,”fv”パラメータをセットしている。
リクエストパラメータの準備が整ったところで,テスト対象のメソッドを呼び出している。getRightSelectItems()メソッドの処理によって,ResponseWriterオブジェクトに対して出力処理が行われる。
・・・と,ここから先の説明は長くなると想像できるので,今回はここで終わり。getRightSelectItems()メソッドの出力結果の検証について,次回の内容としよう。
- Posted:
- 12.22.2006
- Category:
- Shale

前回のエントリで予告した通り,今回はShale Test Framework(以下STFと略す)を試すための題材を紹介することにしよう。
STFの対象問題領域は,JSF APIやServlet APIに依存したコードを持つManagedBeanクラスが主な領域となる。「JSF+AjaxでUIコンポーネント開発 with Shale Remoting」の一連のエントリの中で,double-selectコンポーネントの選択肢をJSON形式のテキストで返却するManagedBean,SelectItemsProducerクラスを作成した(このエントリを参照)。SelectItemsProcuderクラスが持つメソッドでは,以下のような依存関係が存在している。
- リクエストパラメータ値の取得 – ExternalContext(JSF)に依存
- 使用するResponseWriterの生成 – ResponseFactory(Shale Remoting)に依存
- JSON形式テキストの返送 – ResponseWriter(JSF)に依存
- フェーズの完了 – FacesContext(JSF)に依存
STFを試す題材としてはうってつけのコードであることがわかるだろう。では,実際のSelectItemsProducerクラスのコードを以下に示す。今回はSTFを試すことが目的なので,前のエントリと比べて,メソッドを1つに限定した。
“fv”という名前のリクエストパラメータ値に従って,返送する選択肢を変化させている。import文を見てもわかる通り,JSFやShale Remotingに依存したコードとなっている。
では,単体テストについて考えていこう。まず,このクラスのgetRightSelectItems()メソッドの単体テストを行うためには,以下の条件が必要となる。
- FacesContextオブジェクトを取得できること。
- ExternalContextオブジェクトが持つRequestParameterMapコレクションに,”fv”パラメータが格納されていること。
- ResponseWriterオブジェクトに対して出力された内容を取り出すことができること。
これらの条件は,全てSTFによってクリアすることが可能である。
SelectItemsProdcer#getRightSelectItems()メソッドは,2種類の”fv”パラメータの値を受け付ける。”1″を受け取った場合はJRの路線を,”2″を受け取った場合は東京メトロの路線を,それぞれ選択肢として出力している。カバレッジを確保するためには,それ以外の値だったら,とか,○○例外が発生したら,などのパターンをテストしなければならないが,今回はそれが本質ではないので省略する。
実際にテストを体験できるプロジェクトを,Maven2のpomファイルと共に作成してある。アーカイブをここからダウンロードして,任意の場所に展開し,展開の結果作られたtest-stfディレクトリで以下のコマンドを実行して欲しい。
mvn eclipse:eclipse
その後,Eclipseの外部プロジェクトのimport機能を使って,test-stfディレクトリをEclipseプロジェクトとして登録する。さっそくテストケースを実行してみよう。src/test/javaディレクトリにSelectItemsProducerTestクラスがあるので,このクラスをJUnit TestとしてRunしてみる。

上の図のように,緑になればOK。JSFの実行時環境がシミュレートされた中で,SelectItemsProducerTestクラスのテストメソッドが実行された瞬間である。めでたしめでたし。
test-stfプロジェクトのpom.xmlファイルでは,以下のライブラリを使用するように定義してある。
[Compile scope]
- javax.faces.jsf-api.1.1_02
- javax.faces.jsf-impl.1.1_02
- org.apache.shale.shale-remoting.1.0.3
[Test scope]
- junit.junit.3.8.1
- org.apache.shale.shale-test.1.0.3
- net.sf.json-lib.json-lib.0.9
json-libは,JSON形式のテキストとJavaBeansやXML形式のテキストとの相互変換を行ってくれる,とっても便利なライブラリである。これをテストメソッドの中で使用して,JSON形式のテキストの検証に使ってみようという企みだ。
次回は,いよいよSTFを使ったテストケースの作成を紹介する予定である。
- Posted:
- 12.21.2006
- Category:
- Shale

JSFの機能を補完することで,より生産性の高さを求めることができるApache Shale。もちろんJSFのテストの領域にも足を踏み入れている。今回から数回,JSFの単体テストを楽にしてくれる「Shale Test Framework」について紹介してみようと思う。
JSFの大きな特徴として「ManagedBeanをPOJOで作ることができる」ということが真っ先にあげられる。Strutsやその他の普及したWebアプリケーションフレームワークでは,フレームワークが提供するinterfaceや抽象クラスを継承して業務的なクラスを作成することが基本だった。もちろんそれが悪いことではなく,実装者に縛りを強いることで,クラス粒度が揃えられたり,業務的な共通機構が作りやすくなったり,というような一定の効果をもたらしてくれた。ただし,その代償として,単体テストの敷居を一気に高めてしまったことは,否定できない事実だろう。これはWebアプリケーションフレームワークというよりは,そもそもServlet APIが原因だとも言える。つまり,単体テストを行うためには,サーブレットコンテナを強烈に意識しなくてはならないわけだ。
そこでJSFでは,バリューバインディングやメソッドバインディングという仕組みを設けることで,Servlet APIからの独立を実現した。特殊なインタフェースや抽象クラスが提供するメソッドに頼ることなく,JavaBeans規約に沿った手法(つまりPOJO)にて,情報を受け取って処理したり情報を外部に提供したりすることができるようになった。ManagedBeanは,能動的に外部から渡ってくる値を取りに行くことはせず,プロパティのsetterメソッドにて値が渡されることを待っていれば良い。これは,DIの考えにも通じている。そのおかげで,ManagedBeanに対する単体テストコードが非常に書きやすくなったことは,言うまでもないだろう。
簡単なアプリケーションを,JSFの標準実装が提供する機能を普通に使って開発していれば,バリューバインディングやメソッドバインディングといった機構のみで十分であり,ManagedBeanに対する単体テストコードも苦労することなく作れるだろう。
しかし,時代はそれを許してはくれない。
Ajaxの普及によって,HTMLとJavaScriptによるWebブラウザサイドでのリッチなUIが一気に主流になってしまった。その結果,従来のページ更新による画面書き換えよりも,処理の流れは複雑になる。つまり,画面を構成する個々のUIコンポーネントのイベント処理を非同期通信でサーバに依頼し,その結果を元に画面の一部を書き換える,というパターンで実装を行うことになる。これは,JSFの仕様策定時点では全くメジャーでなかった考えであり,個人的には,新参者な割にトレンドに乗り切れていない感がJSFにあることの理由となっていると思っている。
しかし,JSFのスペックリードだったCraigによって,その印象は払拭されようとしている。Apache Shaleによって,JSFは技術のトレンドにマッチしたものになる。特にShale Remotingはその代表格であり,JSFが目指すコンポーネント・イベント指向について,より進化させてくれる。これについては,「JSF+AjaxによるUIコンポーネント開発 with Shale Remoting」という一連のエントリを是非読んでみて欲しい。
ただし,やはり仕様策定時点でAjaxが見据えられていないJSFは,Shale Remotingを使ったとしても,弱点が見え隠れしてしまう。ManagedBeanをPOJOで作成できることがJSFの強みだったが,残念ながらShale Remotingによって呼び出されるManagedBeanは,JSFのAPIに依存したコードが現時点では必要になってしまう。具体的には,Webブラウザから送られたパラメータ値の取得や,処理結果のストリームへの送出処理についてが対象となる。つまり,Shale Remoting対応のManagedBeanに関する単体テストは,実行時の環境をシミュレートしてあげないといけない。
UIコンポーネントを自作した場合についても,そのコードはJSFに依存した内容となる。ServletやJSPの単体テストがCactusを必要としたのと同じように,JSFに関しても実行時の環境を再現してくれる単体テストソリューションが必要になるのだ。
この問題を解決してくれるのが,Shale Test Frameworkである。長いので,以後STFと略すことにしよう。STFでは,JUnitでの単体テストコードの記述を楽にしてくれる抽象クラスが提供されている。
- AbstractJsfTestCase – STFが提供するモッククラスを使用してJSF機構の各オブジェクトが提供される。
- AbstractJmockJsfTestCase – JMockを使用してJSF機構の各オブジェクトが提供される。
- AbstractHtmlUnitTestCase – HtmlUnitを統合した抽象テストケース。
- AbstractViewControllerTestCase – ViewControllerを実装したManagedBeanクラスをサポートする抽象テストケース。
最も良く使われるのは,一番上のAbstractJsfTestCaseクラスだろう。

このクラスのsetUp()メソッドにて,ApplicationやFacesContextなどのJSFが提供するオブジェクトや,HttpServletRequestやHttpSessionなどのServlet APIに対するオブジェクトを,モックとして利用可能な状態にしてくれる。テストメソッドの中で適切にこれらのモックオブジェクトに対していろいろと前準備を施してあげることで,実行時のJSF環境がシミュレートされるというわけである。
次回のエントリでは,STFを適用する題材を取り上げる予定である。
- Posted:
- 12.19.2006
- Category:
- Shale

Ajax対応JSFコンポーネントをApache Shale Remotingを使って作成する方法を,全15回に渡ってエントリした。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (1)」
[全般] やってみようと思った理由と,Shale Remotingの紹介。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (2)」
[全般] 作成するコンポーネント(double-selectコンポーネント)の紹介。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (3)」
[全般] 開発のための準備(Eclipseプロジェクトの作成)。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (4)」
[全般] JSFコンポーネントのパッケージング方法と,double-selectコンポーネントのファイル構成の説明。Shale Remotingの基本的な機能紹介(なぜShale Remotingが便利なのか)。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (5)」
[全般] double-selectコンポーネントのJSP上でのタグ記述の内容と,double-selectプロジェクトおよびtest-dsプロジェクトのファイル構成の説明。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (6)」
[double-selectプロジェクト] taglib.tldファイルの説明
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (7)」
[double-selectプロジェクト] DoubleSelectTagクラスの説明。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (8)」
[double-selectプロジェクト] double-selectコンポーネントのレンダリング内容と,Shale Remotingの動的ManagedBeanメソッド呼び出し機構の説明。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (9)」
[double-selectプロジェクト] DoubleSelectRendererクラスの説明(エンコード処理)。Shale Remotingが提供しているXhtmlHelperクラスの使い方も紹介。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (10)」
[double-selectプロジェクト] double-select.jsファイルの説明。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (11)」
[double-selectプロジェクト] DoubleSelectRendererクラスの説明(デコード処理)。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (12)」
[double-selectプロジェクト] faces-config.xmlファイル(renderKitの定義)の説明と,double-selectコンポーネントの仕上げ。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (13)」
[test-dsプロジェクト] 検証用ページ(index.jspファイル)の説明。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (14)」
[test-dsプロジェクト] 検証用ManagedBeanクラス(ParameterBean,SelectItemsProducer)の説明。
「
JSF+AjaxでUIコンポーネント開発 with Shale Remoting (15)」
[test-dsプロジェクト] faces-config.xml,web.xml,log4j.xmlファイルの説明と,動作確認手順の紹介。まとめ。
第1回目が11月18日で,第15回目が12月13日。気がつけば1ヶ月近くもかかっている。もっと簡潔に説明できただろうに。。。改めて自己嫌悪。orz
最後の回でも書いたが,JSFコンポーネントの一般的な作り方も合せて解説したつもりなので,JSFコンポーネントを作ってみたいと思っている人にも役に立つ情報かと思っている。もちろんAjaxという言葉が重要なキーワードとなっている現在では,Shale Remotingを使ったJSFコンポーネントの直感的かつ迅速な開発は非常に有効だろう。
日々の開発に役立てて欲しい。
[2006/12/26 追記] 以下のURLで実際に動作するものを公開したので,試してみて欲しい。
http://www.eisbahn.jp:8080/test-ds/index.faces
- Posted:
- 12.14.2006
- Category:
- Shale

Shale Remotingを使ったJSFコンポーネントの作成について長らくエントリしてきたが,今回でtest-dsプロジェクトも完成し,実行ができるようになる。残りの3つ(前回のエントリで2つと紹介したが1つ忘れてた)をサクッとやっつけることにしよう。
まずは,double-selectコンポーネントが使用する2つのManagedBeanを,faces-config.xmlファイルに定義する。
ParameterBeanクラスを”parameterBean”という名前で,SelectItemsProducerクラスを”selectItemsProducer”という名前でそれぞれ定義している。スコープについてはrequestとapplicationを指定しているが,これについて特別な理由はない。
では,faces-config.xmlファイルをここからダウンロードし,以下の場所に配置して欲しい。
・[Eclipseワークスペース]/test-ds/src/main/webapp/WEB-INF
次に,Webアプリケーションとするためのweb.xmlファイルを紹介しよう。
FacesServletサーブレットの定義のみであることがわかるだろう。test-dsプロジェクトでは,JSFリクエストを”*.faces”というマッピングにしている。
とかくweb.xmlファイルなどは,初期化パラメータやタグライブラリの宣言,フィルタやリスナーなどの記述で結構派手になりがちだが,JSFの場合はfaces-config.xmlファイルの扱いが比較的高級(jarファイル分割&自動検索機構がしっかり考慮されている)なために,最低限の記述のみで駆動させることが可能となっている。JSFはコンポーネント指向が強いことがわかると思う。
このweb.xmlファイルをここからダウンロードして,以下の場所に配置して欲しい。
・[Eclipseワークスペース]/test-ds/src/main/webapp/WEB-INF
さあ最後のファイルだ。別になくても構わないのだが,一応ログ出力のためのlog4j.xmlファイルを準備しておこう。
ま,これは説明するまでもないだろう。このlog4j.xmlファイルをここからダウンロードして,以下の場所に保存して欲しい。
・[Eclipseワークスペース]/test-ds/src/main/webapp/WEB-INF/classes
以上で全ファイルが揃った。test-dsプロジェクトは以下のようになっているはずだ。

さっそく実行してみよう。
まず前提として,double-selectコンポーネントがmavenのローカルリポジトリにインストールされていることが必要なので,以下のコマンドをコマンドプロンプトやシェルで実行して欲しい。
> cd [Eclipseワークスペース]/double-select
> mvn install
次に,test-dsプロジェクトをWebアプリケーションとしてTomcatに登録する。それには,Package Explorerビュー内のtest-dsプロジェクトノード上で右クリックし,コンテキストメニューの[Tomcat プロジェクト] – [コンテキスト定義を更新]を選択する。「操作が成功しました。」と表示されれば,メッセージ通り成功。

では,いよいよtest-dsプロジェクトを実行しよう。TomcatプラグインのTomcat起動ボタンを押下し,起動後にWebブラウザで以下のURLにアクセスしてみよう。
http://localhost:8080/test-ds/index.faces
左のコンボボックスの選択を変更すると,右の選択肢が変更されることがわかると思う。さらに,「Go!」ボタンを押下すると,EclipseのConsoleビューに選択値が表示されるのが見てとれるはずだ。
—
実は「Go!」ボタンを押すたびに,左右両方のコンボボックスの選択肢が消えてしまう現象が,FireFoxを利用している場合に発生してしまう。これは,double-select.jsファイルがFireFoxのキャッシュに入った際に,FireFoxがキャッシュの有効性をサーバに問い合わせる時に送信する更新日時の書式が,Tomcatが期待する米国ロケールではなく日本ロケールになっていて,結果としてHttpServletRequest#getDateHeader()メソッドでIllegalArgumentException例外が発生する,という不具合(実際にはdouble-select.jsをレスポンスする際にヘッダに更新日時を入れる時に日本ロケールが使われてしまっていることが原因)である。これは,イタリア人によって既に不具合報告が下記のようにされているので,次の1.0.4のバージョンアップで解決する予定である(Nightlyビルドでは既に修正済み)。
「SHALE-270 Illegal data format」- Shale JIRA
ソースコードを追って原因を突き止めた時に「よし!バグ報告で貢献できる!」と思ったのだが。。。ちょっと悔しい。
—
ここまでくるのに15回も費やしてしまったが,以上でdouble-selectコンポーネントの解説は終わりである。JSFコンポーネントの作成方法も同時に説明をしてきたので,Shale Remotingを使わない素のJSFコンポーネントを作る際にも参考になるだろう。くどくどと説明してきたので,JSFコンポーネントの作成がすごく大変な作業に思えてしまったかも知れないが,わかってしまえば非常にシンプルだということに気付いてくれることだろう。もちろんコンバータやバリデータ,HTMLのスタイル属性などについては完全に説明を省略したので,実用的なコンポーネントに仕上がっているとは言えない。しかし,Ajax対応JSFコンポーネントの作成が,Shale Remotingを使用することで,より直感的に,より手軽に開発可能なことは伝わったのではないだろうか。
皆さんがJSFを利用する時は必ず来る。その時の準備知識として役に立てば幸いである。
- Posted:
- 12.13.2006
- Category:
- Shale

double-selectコンポーネントの動作確認を行うためのtest-dsプロジェクト作りも2回目となった。前回のエントリでは,double-selectコンポーネントをページに配置するためのJSPファイルを作成し,double-selectタグの属性値としていくつかManagedBeanとの連携を記述した。今回は,連携するManagedBeanのクラスを紹介しよう。
まずは簡単な方から。double-selectコンポーネントの選択値を得るためのManagedBeanを,ParameterBeanという名前のクラスとして作成する。
selectedValueプロパティを持つだけのシンプルなクラスである(本来はSerializableインタフェースを実装する必要があるが省略)。前のエントリで,double-selectコンポーネントの2つのselectタグがサブミットされた結果は,Stringの配列でUIコンポーネントに渡されると紹介した。今回はコンバータの指定を行っていないので,EditableValueHolder#setSubmittedValue()メソッドに渡したオブジェクトがそのままバリューバインディングされる。よって,selectedValueプロパティもString[]型にしている。setterメソッドが呼び出されたことがわかるように,メッセージを出力するようにしておこう。
ParameterBean.javaファイルをここからダウンロードして,以下の場所に配置して欲しい。
・[Eclipseワークスペース]/test-ds/src/main/java/jp/eisbahn/testprograms/jsf/test
では,難しい方に取り掛かろう。double-selectコンポーネントの選択肢をJSON形式のテキストで出力する処理を持つManagedBeanを,SelectItemsProducerという名前のクラスで作成する。
SelectItemsProducerクラスも,特に変わったことはない,普通のPOJOである(本来はSerializableインタフェースを実装する必要があるが省略)。このクラスは,左右の選択肢を出力するための2つのメソッドを持つ。では最初に,左の選択肢を返す処理を行うgetLeftSelectItems()メソッドから見ていこう。
getLeftSelectItems()メソッドでは,選択肢をJSON形式の文字列として構築し,それをResponseWriterオブジェクトを使用してWebブラウザに送信している。
ResponseWriterオブジェクトは,Shale Remotingが提供するResponseFactoryクラスを使用して取得している。FacesContextクラスにもResponseWriterオブジェクトを得るためのgetResponseWriter()メソッドはあるのだが,これは基本的にHTMLを送信するためのResponseWriterオブジェクトを返す。例えば,Sun RIで提供されるHtmlResponseWriterクラスでは,script,style,そして”javascript:”で始まるURIへの対応などが処理される。それに対して,Shale Remotingが提供するBasicResponseWriterクラスでは,HTMLに特化した処理が省略されているため,XML形式やJSON形式でコンテンツを出力するのであれば,HtmlResponseWriterクラスに比べて効率が良い。よって,ここではResponseFactoryクラスを用いてBasicResponseWriterオブジェクトを取得し,それを使ってJSON形式のテキストを出力している。

JSON形式のテキストを送信する場合は,Content Typeとして”text/javascript”を指定する。また,マルチバイト文字を正しくWebブラウザに処理してもらうために,UTF-8をキャラクタセットとして同時に指定している。選択肢は,ここでは”JR”と”東京メトロ”の2つとしている。JSON形式とするために,各選択肢を中括弧で括り,全体を大括弧で括っている。この文字列を,取得したResponseWriterオブジェクトのwrite()メソッドに渡して出力している。
AjaxとShale Remotingの機能によって呼び出されたこのメソッドの最後の処理として,FacesContextオブジェクトのresponseComplete()メソッドを呼び出している。Shale Remotingによる動的ManagedBean呼び出しでは,基本的にそのメソッドが処理結果をWebブラウザに出力することで処理が完結するため,以降のJSFのフェーズを実行する必要がない。よって,ここでresponseComplete()メソッドを呼び出すことで,LifeCycleオブジェクトにフェーズの完了を指示している。
もう一つの右の選択肢を出力する処理を行うgetRightSelectItems()メソッドは,基本的にgetLeftSelectItems()メソッドとやっていることは変わらない。ただし,Webブラウザから送られた左の選択値を得て,出力内容を変化させている。
Webブラウザから送信されたリクエストパラメータの取得方法は,前のエントリで紹介した,double-selectコンポーネントのDoubleSelectRendererクラスのdecode()メソッドと同じである。つまり,ExternalContextオブジェクトにあるRequestParameterMapオブジェクトから取得すれば良い。
test-dsプロジェクトでは,double-selectコンポーネントの動作確認ができれば良いので,左右の選択肢は固定的なものを出力している。double-selectコンポーネントを実際に開発案件の中で使用するときには,選択肢の内容をデータベースから取得したりするなどの処理が行われるだろう。それに伴ってエラー処理などが必要となるだろうが,説明したいことの本質ではないので内容としないでおく。
SelectItemsProducer.javaファイルをここからダウンロードして,以下の場所に配置して欲しい。
・[Eclipseワークスペース]/test-ds/src/main/java/jp/eisbahn/testprograms/jsf/test
上記の例では,JSON形式の文字列を原始的な手段で構築したが,実際には「JSON-lib」などのJavaBeans-JSON変換を行ってくれるライブラリを使用すると良いだろう。
今回の内容で,説明すべき内容はほぼ網羅した。あとはfaces-config.xmlファイルとweb.xmlファイルを記述するのみである。次回は,残り2つのファイルを紹介し,いよいよtest-dsプロジェクトを実行してdouble-selectコンポーネントの動作を確認してみよう。つまり,次回が最終回となる,予定である。が,たぶん最終回にならない。。。
- Posted:
- 12.12.2006
- Category:
- Shale

Shale Remotingを使ったAjax対応JSFコンポーネントの作成も,今回で13回目を迎えた。かなり気合いが入ったエントリが続いているが,前回までの1〜12回で,double-selectコンポーネントができ上がった。今回からは,double-selectコンポーネントを利用するためのtest-dsプロジェクトを解説していこうと思う。
まずは,test-dsプロジェクトをどんなアプリケーションにするかだが,単純に1つのページにdouble-selectコンポーネントを配置して,左右のコンボボックスの選択肢がAjaxとShale Remotingによって動的に変更されるのを確認する。そして,コマンドボタンも配置して,double-selectコンポーネントの選択値がManagedBeanに正しくバリューバインディングされてるかどうかについても確認をする。
では,さっそくJSPから見ていこう。全体をドカンと紹介してもいいのだが,もったいぶって小出しにする。では,htmlタグの前の部分から。
注目は4行目。double-selectコンポーネントのタグライブラリをtaglibディレクティブによって使用可能としている。この際,前のエントリで決定したURIを記述し,接頭語を”my”とした。これに関してはJSFだからといって特別なことはない。
では,htmlタグからdouble-selectコンポーネントの前までのコードを示す。
ここでの注目は5行目。double-selectコンポーネントは,double-select.jsファイルの中で,prototype.jsを前提としたJavaScriptコードが記述されている。よって,上記5行目でprototype.jsファイルを読み込んでいる。
1ページ内にShale Remotingを使ったJSFコンポーネントのみが配置されるのであれば,このような汎用的に使うjsファイルを,JSFコンポーネント自身がレンダリングしても良いかもしれない(前のエントリ参照)。しかし,例えばmyfacesのtomahawkなどに代表されるサードベンダー提供のJSFコンポーネントも同一ページで使用するとなると,prototype.jsファイルのような有名なライブラリを複数回読み込んでしまう危険性が増してしまう。よって,極力prototype.jsファイルのような汎用的なjsファイルは,JSFコンポーネントが提供するのではなく,JSFコンポーネントを利用する側が準備するようにした方が問題が出にくくなるのではないかと思う。
さて,目玉となるdouble-selectコンポーネントを配置する部分のコードを示そう。
ビュールートを示すf:viewタグとh:formタグで,double-selectコンポーネントとコマンドボタンのh:commandButtonコンポーネントを括っている。h:formタグは,HTMLのフォームになると共に,その中に配置される各コンポーネントのIDを決定する際にも使用される。そして,接頭語”my”を使って,double-selectタグを記述している。

value属性に記述したバリューバインディング式は,”parameterBean”という名前のManagedBeanオブジェクトが持つselectedValueプロパティを指定している。また,leftSelectItems属性とrightSelectItems属性に記述したメソッドバインディング式は,”selectItemsProducer”という名前のManagedBeanオブジェクトが持つgetLeftSelectItems()メソッドおよびgetRightSelectItems()メソッドを指定している。このメソッドバンディング式は,実際にはメソッドバインディングされずに,AjaxとShale Remotingを使って選択値を取得する際に使用される。
最後に,bodyタグとhtmlタグを閉じるための記述を行って,index.jspファイルの記述が完了する。
protoptye.jsファイルをインポートしてはいるが,JavaScriptコードを一切記述していないのがわかるだろう。さらに,選択肢をAjaxで取得するために呼び出すManagedBeanのメソッドの記述として,メソッドバンディング式で記述できることも直感的である。
今回紹介したindex.jspファイルをここからダウンロードして,以下の場所に保存して欲しい。
・[Eclispeワークスペース]/test-ds/src/main/webapp
次回は,double-selectコンポーネントの選択肢を提供するManagedBeanとしてdouble-selectタグの属性値で指定した,SelectItemsProducerクラスを紹介する予定である。
- Posted:
- 12.10.2006
- Category:
- Shale

Previous »