1.9.3. RESTful アプリケーションの「プッシュ」型 MVC の使用
RESTful ページの処理にプッシュ型 MVC が使われることがあるため、 Seam では ページアクション という概念を提供しています。 ブログのサンプルはブログの記入ページ
entry.xhtml にページアクションを使用しています。
注記
ここでは一例として示すためにプッシュ型を使用していますが、 この特定の機能についてはプル型 MVC を使った実装の方がシンプルです。
entryAction コンポーネントの動作は Struts のような従来のプッシュ型 MVC アクション指向のフレームワークでのアクションクラスの動作とよく似ています。
@Name("entryAction")
@Scope(STATELESS)
public class EntryAction
{
@In Blog blog;
@Out BlogEntry blogEntry;
public void loadBlogEntry(String id) throws EntryNotFoundException {
blogEntry = blog.getBlogEntry(id);
if (blogEntry==null) throw new EntryNotFoundException(id);
}
}
ページアクションは、
pages.xml でも宣言されます。
<pages>
...
<page view-id="/entry.xhtml">
<rewrite pattern="/entry/{blogEntryId}" />
<rewrite pattern="/entry" />
<param name="blogEntryId"
value="#{blogEntry.id}"/>
<action execute="#{entryAction.loadBlogEntry(blogEntry.id)}"/>
</page>
<page view-id="/post.xhtml" login-required="true">
<rewrite pattern="/post" />
<action execute="#{postAction.post}"
if="#{validation.succeeded}"/>
<action execute="#{postAction.invalid}"
if="#{validation.failed}"/>
<navigation from-action="#{postAction.post}">
<redirect view-id="/index.xhtml"/>
</navigation>
</page>
<page view-id="*">
<action execute="#{blog.hitCount.hit}"/>
</page>
</pages>
注記
このサンプルは検証後およびページビューのカウンタにページアクションを使用している点に留意してください。 また、 ページアクションのメソッドバインディングでのパラメータの使い方にも注意してください。 これは標準 JSF EL の機能ではありませんが、 Seam ではページアクションだけでなく JSF メソッドバインディングでも使用することができます。
entry.xhtml ページが要求されると Seam はまずページパラメータ blogEntryId をそのモデルにバインドします。 URL を書き換えているため blogEntryId パラメータ名は URL に表れないことを思い出してください。 次に Seam はページアクションを実行して、 必要なデータ blogEntry を読み出し、 それを Seam イベントコンテキスト内に配置します。 最後に以下を表示させます。
<div class="blogEntry">
<h3>#{blogEntry.title}</h3>
<div>
<s:formattedText value="#{blogEntry.body}"/>
</div>
<p>
[Posted on 
<h:outputText value="#{blogEntry.date}">
<f:convertDateTime timeZone="#{blog.timeZone}" locale="#{blog.locale}" type="both"/>
</h:outputText>]
</p>
</div>
ブログエントリがデータベースで見つからない場合、
EntryNotFoundException 例外が送出されます。 この例外は 505 エラーではなく 404 エラーにさせたいので例外クラスにアノテーションを付けます。
@ApplicationException(rollback=true)
@HttpError(errorCode=HttpServletResponse.SC_NOT_FOUND)
public class EntryNotFoundException extends Exception {
EntryNotFoundException(String id) {
super("entry not found: " + id);
}
}
メソッドバインディングでパラメータを使用しない別の実装例を示します。
@Name("entryAction")
@Scope(STATELESS)
public class EntryAction {
@In(create=true)
private Blog blog;
@In @Out
private BlogEntry blogEntry;
public void loadBlogEntry() throws EntryNotFoundException {
blogEntry = blog.getBlogEntry( blogEntry.getId() );
if (blogEntry==null) throw new EntryNotFoundException(id);
}
}
<pages>
...
<page view-id="/entry.xhtml" action="#{entryAction.loadBlogEntry}">
<param name="blogEntryId" value="#{blogEntry.id}"/>
</page>
...
</pages>
使用する実装はその選択により完全に異なります。
また、 ブログのサンプルでは非常にシンプルなパスワード認証、 ブログへの投稿、 ページの部分的なキャッシング、Atom フィードの生成も示しています。