目次
Teeda
SeasarプロジェクトのJSF実装。S2コンテナによるDI、各種開発を簡単にする拡張機能などを搭載。
最大の特徴は、JSPではなくXHTMLをテンプレートとして使う事ができること。面倒なface-configを書かなくてよいこと。また、バッキングビーンの代わりにPageというJavaBeansを用いる。
Teedaのインスタンスライフサイクルについて
Pageにインジェクションされるコンポーネントは基本的にRequest単位でインスタンス化されるようだ。
よってサーブレットのようにインスタンスフィールドを使っても他人のデータが表示されるようなことは無い。
Pageの状態管理は良く分からない。あとで調べる。
Teeda クラス設計方針案
- パッケージ構成は必ずSMART Deploy規約に従う
- 従うメリットと従わないデメリットはあまりにも大きい、従わないならばTeedaを使うべきではない。
- ロジック処理する型とHTML上の表現型が違う場合は、Converterを使う、作る
- 例:時間処理で内部処理は秒単位の精度で行うが、表示は分単位にしたい場合など
- Pageクラスに変換処理を入れないこと。
- 階層構造をどうするか案
- 「Page - Dao」DBマスタ管理の場合、直接DAO呼ぶのが楽
- 「Page - Logic - Dao」Logicが単純で一つで終わる場合。ロジッククラスはトランザクションスクリプトでもドメインロジックでも好きなように、
- 「Page - Service - Logic - Dao」Logicが複数にわたる場合はServiceをLogicに対するファサードクラスとして使う
-
- Effective Java 項目32を参照のこと
- 上記リンク先のケースに当てはまる場合は、JavaBeansを作る。
- JavaBeansをPageプロパティにすると、toStringメソッドの戻り値がHTMLに出力される。
- Converterを使えばユーザ入力値をJavaBeansとして取得可能。
画面遷移
<input type="button" id="jumpHoge" /> <input type="button" id="jumpFuga_Hoge" />
上:同じサブアプリケーションのhoge.htmlへ移動、下:fugaサブアプリケーションのhoge.htmlへ移動
バリデーション
必須チェックをするにはPage側に
@Required private String hogeName
というノリでアノテーション付ける。エラーメッセージはHTMLに「id名+Message」なspanタグを付けると表示される。
<input type="text" id="hogeName" /><span id="hogeNameMessage" class="error" />
とやるとspanのところにエラーメッセージが表示される。しかし「値を入力してください(hogeName)」のようにエラーメッセージにプロパティ名が出るのでダサい。
input属性にtitleを付けると
<input type="text" id="hogeName" title="ほげ名称" /><span id="hogeNameMessage" class="error" />
エラーメッセージは「値を入力してください(ほげ名称)」になる。
それもダサい、独自のエラーメッセージを出したいというならば以下のように書く。 appMessage.propertiesに以下の記述(当然、2バイト文字はプロパティ用にエンコードする必要がある、EclipseのプラグインResourceBundleEditor等を使うと良い)
hogeName.required=ほげ名称を入力してください
アノテーションを修正
@Required(messageId="hogeName.required") private String hogeName
- labelを使うやり方(国際化するとき?)
Requiredバリデーション
Teeda 1.0.10
selectOneRadioにはRequiredバリデーションが利かないのでラジオボタンが押されているかどうかは独自にチェックするしかない。ラジオボタンで選択されていなければプロパティがnullになる。
エラーメッセージは
facesContext.addMessage("formのId:inputのId", FacesMessageUtil.getMessage(facesContext, "appMessages.propertiesのキー", new Object[0]));
で設定できる。Actionには何故かFacesContextがDIされないので
FacesContext facesContext = FacesContext.getCurrentInstance();
で取得する。
ValidatorとConverterのtigerアノテーション
Tigerアノテーションはフィールドにもゲッタセッタメソッド好きなものに付けられる。ただしPageクラスを継承したとき、親クラスにフィールド、ゲッタ、セッタがある場合は、フィールドに付けても有効にならない。ゲッタかセッタに付ける。
おそらくアノテーションを調べる時に親クラスのprivateフィールドまで見に行かないのだと思う。
フィールドがpublicでゲッタセッタ無しなら効くかもしれない…(要確認)
forEach
forEachのためにPage側には、
- 繰り返し項目のDTOを格納するLIST、配列型プロパティ
- 繰り返し項目の中身を格納するプロパティ
が必要。
// DTO public class Person { private Date birthDay; // Getter、Setterは脳内補完してください private String name; // Getter、Setterは脳内補完してください } // Page public class MemberListPage { // 繰り返し項目格納のItems private List<Person> personItems; // 繰り返すPersonの中身 private String name; private Date birthDay; }
MemberListPageのPersonの中身プロパティの型と名前は、繰り返しするPersonクラスのプロパティの型と名前に一致させる。クラスは完全一致、サブクラスとかでもダメ。
PageのプロパティはString等だけではなくJavaBeansでもいい。この場合は、toStringされた値が出力される。複数の値を組み立てて値を組み立てる必要がある場合に便利。
日付、数値のフォーマット
Pageクラスのgetterにアノテーションを付ける
@DateTimeConverter(pattern = "yyyy年MM月dd日") public Date getMyBirthDay() { return myBirthDay; }
Getterではなくフィールドでも良いっぽい。
数字は
@NumberConverter(pattern="#,###.#") private double hoge;
labelとvalueをもつDTO
TeedaのselectOneMenu、selectManyCheckbox、selectOneRadioを動的出力するために、valueとlabelというプロパティを持つJavaBeansのリストを、hogeItemsというプロパティ名でPageに設定する。
JavaBeansには、javax.faces.model.SelectItemというクラスを使うことができる。これを使った場合、javax.faces.model.SelectItemGroupでラップするとoptgroupも出力することができる。
わざわざDTOを作るのがだるい、hogeエンティティをhogeItemsとして使いたいというならば、valueとlabelというプロパティをエンティティに作ってしまえばいい。プロパティidをvalue、プロパティnameをlabelとして使いたいならば…
public Integer getValue() { return this.id; } public Integer getLabel() { return this.name; }
といったメソッドをエンティティに追加してしまう。
selectOneMenu
<select id="hoge"></select>
- Pageに必要なプロパティは「hogeItems」、型は配列またはList。中身はMapまたはlabelとvalueプロパティを持つJavaBeans(DTO)
- hogeプロパティは入力値が格納される。表示時にセットしておくと、それと同じ値がhogeItemsにあればselectedになる。
selectManyCheckBox
- 可変式のチェックボックス、チェックボックスの項目を動的に出力する。
- Pageに必要なプロパティは「hogeItems」と「hoge」
- 「hogeItems」プロパティの型は配列またはList。中身はMapまたはlabelとvalueプロパティを持つJavaBeans(DTO)
- 「hoge」プロパティは配列、submit時にチェックした項目のvalueが格納される。表示時にセットしておくとhogeItemsの同じ値がcheckedになる。
Teeda Ajax
まずTeeda Ajaxのライブラリを取り出す。teeda-ajaxのjarファイルにjsファイルが含まれているのでjarを解凍して取り出す(ホントか?)。言うまでもないがjarの正体はzip圧縮ファイル。
Smart Deployを使う場合は、Pageクラスにプレフィックスがajaxで始まるメソッドを用意する。Pageのサブアプリケーションがhoge、PageクラスがFugaPage、呼び出されるサーバ側のJavaメソッドがajaxExecuteの場合、JavaScript側は
Kumu.Ajax.executeTeedaAjax(hoge_fugaPage_ajaxExecute, [], Kumu.Ajax.RESPONSE_TYPE_JSON); // コールバック関数 function hoge_fugaPage_ajaxExecute(response) { // Ajaxコールバック処理 }
と書く。
Kumu.Ajax.executeTeedaAjaxの引数は…
- Ajax処理のコールバック関数
- サーバ側のajaxメソッドに渡す
- 戻り値の形式(デフォルトはJSON)
- Kumu.Ajax.RESPONSE_TYPE_JSON : JSON形式
- Kumu.Ajax.RESPONSE_TYPE_TEXT : テキスト形式
- Kumu.Ajax.RESPONSE_TYPE_XML : XML形式
- Kumu.Ajax.RESPONSE_TYPE_HTML : HTML形式?
Java側のajaxメソッドをアクションに記述する場合はfugaPageをfugaActionに
Kumu.Ajax.executeTeedaAjax(hoge_fugaAction_ajaxExecute, [], Kumu.Ajax.RESPONSE_TYPE_JSON); function hoge_fugaAction_ajaxExecute(response) { }