1.9. ブログサンプルを使ったブックマーク可能な URL の説明

Seam によりサーバー側で状態を保持するアプリケーションの実装が容易になります。 しかし、 特にコンテンツを提供する機能の場合など、 サーバー側の状態が常に適切であるとは限りません。 このため、 アプリケーションの状態は URL の一部として保存されることが多く、 これによりいつでもどのページにもブックマークを使ってアクセスが可能となります。 ブログサンプルでは検索結果ページも含め全体的にブックマーク機能に対応するアプリケーションの実装方法を示しています。 このサンプルでは Seam による URL でのアプリケーション状態の管理を示します。
ブログのサンプル
このブログサンプルでは「プル (PULL)」スタイルのモデルビューコントロール (MVC) の使い方を示します。ビュー用のデータ取得および準備にアクションリスナーのメソッドを使用するのではなく、データは表示されているためビューはコンポーネントからデータを引き出します。

1.9.1. 「プル」型 MVC の使用

index.xhtml Facelets ページの一部は最新のブログエントリの一覧を表示しています。
<h:dataTable value="#{blog.recentBlogEntries}" var="blogEntry" rows="3">
  <h:column>
    <div class="blogEntry">
      <h3>#{blogEntry.title}</h3>
      <div>
        <s:formattedText value="#{blogEntry.excerpt==null ? 
                                blogEntry.body : blogEntry.excerpt}"/>
      </div>
      <p>
        <s:link view="/entry.xhtml" rendered="#{blogEntry.excerpt!=null}" 
                propagation="none" value="Read more...">
          <f:param name="blogEntryId" value="#{blogEntry.id}"/>
        </s:link>
      </p>
      <p>
        [Posted on&#160;
        <h:outputText value="#{blogEntry.date}">
          <f:convertDateTime timeZone="#{blog.timeZone}" 
                             locale="#{blog.locale}" type="both"/>
          </h:outputText>]
          &#160;
          <s:link view="/entry.xhtml" propagation="none" value="[Link]">
            <f:param name="blogEntryId" value="#{blogEntry.id}"/>
          </s:link>
      </p>
    </div>
  </h:column>
</h:dataTable>
ブックマークからこのページに移動した場合、 <h:dataTable> で使用される #{blog.recentBlogEntries} データは要求されると Seam の blog というコンポーネントにより遅延して読み出されます(「プルされる」)。 この制御の流れは従来の動作ベースの Web フレームワーク Struts で使用されているものとは逆です 。

例1.34

 @Name("blog")
@Scope(ScopeType.STATELESS)
@AutoCreate
public class BlogService 
{
   @In EntityManager entityManager;                                                                             1

   @Unwrap                                                                                                      2
   public Blog getBlog()
   {
      return (Blog) entityManager.createQuery("select distinct b from Blog b left join fetch b.blogEntries")
         .setHint("org.hibernate.cacheable", true)
         .getSingleResult();
   }
}

1

このコンポーネントは Seam 管理永続コンテキスト を使用しています。 これまで見てきた他のサンプルとは異なり、 この永続コンテキストは EJB3 コンテナではなく Seam によって管理されます。 永続コンテキストは Web 要求全体におよび、 ビューでフェッチしていない関連にアクセスすると発生する例外を回避することができます。

2

@Unwrap アノテーションは Seam にクライアントに対する実際の BlogService コンポーネントではなく Blog メソッドの戻り値を与えるよう指示します。 これが Seam の マネージャコンポーネントパターン です。
これは基本的なビューコンテンツを保存しますが、 検索結果ページのようなフォームサブミッションの結果もブックマークします。 この他必要な定義がいくつかあります。