アクションクラスの共通的な処理は、以下のように共通アクションに記述し、継承して個々のアクションクラスから利用すると便利です。 共通アクションには本当に共通的な処理のみ置いてください。いくつかのアクションクラスや特定のユースケースのみで使用するような処理は、Service/Logic/Helper/Utilクラスなどを用意して共通処理を移譲したほうが良い場合が多いです。 Cubbyでは、あえてBeseActionのような共通の便利機能を用意していません。それぞれのプロジェクトにおいて、必要な共通アクションを自由に作成することを推奨します。
共通アクション
// 共通アクションクラス
public class BaseAction extend Action {
...
/**
* 通知用のフラッシュメッセージをセットします。
* @param message メッセージ
*/
protected void notice(String message) {
flash.put("notice", message);
}
}
// それぞれのアクションクラス
private clsss TodoAction extend BaseAction {
...
}
コンバータを利用することで、リソースを表すエンティティのキー等が埋め込まれた /app/{employee,[0-9a-zA-Z]}/bar のような URL を定義したとき、データベースにないリソースが指定された場合に 404(NOT FOUND) を返すような処理が簡潔に書けます。
ここでは、cubby-showcase に含まれるコンバータの例を解説します。 ソースコードは cubby-showcase のパッケージ org.seasar.cubby.showcase.other.web.converter を参照してください。
URL に埋め込まれたリソースの有無は、パラメータの型チェック(DATA_TYPE)以前に実行したいので、 DefaultValidationRules を継承して、検証フェーズ RESOURCE を追加しています。
BookDao を利用して、ISBN を表す文字列をキーにテーブルを検索し、Book のインスタンスを返すコンバータです。
/convert/[ISBNを表す文字列] という URL でアクセスできる detail メソッドを持ちます。
Book 型のプロパティ book に @RequestParameter をつけてリクエストパラメータのバインド対象であることを定義しています。 通常は Book 型へのコンバータが存在しないので値が設定されないはずですが、ここでは BookConverter を定義しているので、 このコンバータによって ISBN -> Book という変換が行われ、該当のデータがテーブルに存在した場合はコンバータが返す Book のインスタンスが プロパティ book に設定されます。存在しない場合はコンバータが null を返すのでプロパティ book には null が設定されます。
その後、バリデーションが行われ、プロパティ book が null の場合は 404 を返します。 RequiredValidator による検証はアクションのプロパティではなくリクエストパラメータに対して行われるので、このようなケースでは有効ではありませんのでご注意ください。
Cubby では 共通の画面部品(他のフレームワークではコンポーネントなどと呼ばれます)を何もサポートしませんが、 画面部品が必要な場合、以下のように「JSTLのc:importタグ」+「JSP標準のスクリプトレット」+「Seasar2 の SingletonS2Container」を使って 画面部品を作成することを推奨します。
画面部品では、引数を元にデータベースへの検索などを行いたい場合があります。 その場合、画面部品のJSPページの先頭に画面描画に必要な情報取得のスクリプトレットを記述します。 通常はSeasar2を使用する場合、スクリプトレット中でLogicクラスやDaoのメソッドを実行すれば良いでしょう。 スクリプトレットは多用するとメンテナンス性が落ちますので、画面部品の先頭でのみで限定的に使用することをおすすめします。
なお、EclipseのWTP(Web Tools Platform)プラグインを使用するとスクリプトレット中の「Javaコードの補完」「import文の自動設定」「コンパイルエラーの表示」などほぼ完璧に行ってくれます。 スクリプトレットでも通常のJavaコード同様にさくさく開発できるのでぜひ導入してみてください。
import(単純な場合):メイン画面
<h2>1.c:importを使用したサンプル<br/>
(S2やDBデータと絡まない単純なパターン)</h2>
<c:import url="img.jsp">
<c:param name="x" value="100"/>
<c:param name="y" value="100"/>
<c:param name="imageUrl" value="http://www.seasar.org/images/seasar_logo_blue.gif"/>
</c:import>
<c:import url="img.jsp">
<c:param name="x" value="200"/>
<c:param name="y" value="200"/>
<c:param name="imageUrl" value="http://www.seasar.org/images/seasar_banner.gif"/>
</c:import>
import(単純な場合):画面部品(img.jsp)
${param.imageUrl}:<br/>
<img src="${param.imageUrl}" width="${param.x}" height="${param.y}"/><br/>
<hr/>
import(Seasar2のDaoを利用):メイン画面
<h2>2.c:importを使用したサンプル<br/> (S2やDBデータを読み込み先のJSPのスクリプトレットで直接使用(WTPの使用をおすすめ))</h2> <c:import url="import_scriptlet.jsp"/>
import(Seasar2のDaoを利用):画面部品(import_scriptlet.jsp)
<%@page import="java.util.List"%>
<%@page import="org.seasar.framework.container.SingletonS2Container"%>
<%@page import="org.seasar.cubby.showcase.todo.dao.TodoTypeDao"%>
<%@page import="org.seasar.cubby.showcase.todo.entity.TodoType"%>
<%
TodoTypeDao todoTypeDao = SingletonS2Container
.getComponent(TodoTypeDao.class);
List<TodoType> types = todoTypeDao.seletAll();
pageContext.setAttribute("types", types);
%>
<br />
<c:forEach var="type" items="${types}">
<li>${type.name}</li>
</c:forEach>
<hr />
以下の設定をおこなうことで、Cubbyで作成したアプリケーションのルーティング情報の一覧、URIの適用テストを行える管理ツールを利用できます。
... <dependency> <groupId>org.seasar.cubby</groupId> <artifactId>cubby-admin</artifactId> <version>1.1.0-rc1</version> </dependency> ...
...
<servlet>
<servlet-name>cubbyAdminServlet</servlet-name>
<servlet-class>org.seasar.cubby.admin.servlet.CubbyAdminServlet</servlet-class>
</servlet>
...
<servlet-mapping>
<servlet-name>cubbyAdminServlet</servlet-name>
<url-pattern>/cubby-admin</url-pattern>
</servlet-mapping>
...
