本文へジャンプ

Lotus > Lotus Developer Domain > 
   
 

WebSphere Portal V5.1.0.1プログラミング・モデルを活用する:第2部:高度なURL生成

ポータル・ナビゲーション制御の実装
 
   
 
コンテンツ
はじめに
ステート・ハンドリングの確認
ナビゲーション・ステートのエンコード
Navigational State SPIを調べる
ナビゲーション・ステートとURLを表す
URLエンコードを理解する
アクセサーAPIを使用したナビゲーション・ステートの読み取りと書き込み
PortalStateManagerServiceを使用したURLの生成
URLAccessorFactoryを使用したURLの作成
例:テーマ用のパンくずリスト・ナビゲーション・コントロール
まとめ
既知の問題
ダウンロード
リソース
筆者について(原文のまま)

Stefan Behl (stefan.behl@de.ibm.com),Software Engineer,IBM
Stefan Hepper (sthepper@de.ibm.com),WebSphere Portal Programming Model Architect,IBM
Stefan Koch (stefkoch@de.ibm.com),Software Engineer,IBM
Carsten Leue (CLEUE@de.ibm.com),WebSphere Portal Runtime Architect, IBM

レベル:初級
原文の掲載:2006年03月08日
更新日:2006年09月01日更新
原文はこちら (US)


これは、WebSphere Portal V5.1.0.1プログラミング・モデルの企業ポータルへの適用を支援する連続記事の第2部です。第1部では、モデルについて解説しました。 第2部では、従来のWebアプリケーション業界のプログラマーにとって難しい領域であるUniformResource Locator(URL)の生成方法を取り上げます。 ポータル環境は、URLの作成が必要なコンポーネントにとって特殊な要件をもたらします。このため、ポータル環境でのURLの生成は少し複雑になります。 この記事では、ポータル・コンポーネントが、ポータルJSPタグよりも優れた機能を持つWebSphere Portalバージョン5.1.0.1 System Programming Interface (SPI)を使用してURLを生成する方法を解説します。 また、ナビゲーション用のパンくずリストを実装した例を用いて、これらのSPIの使用方法についても解説します。

はじめに

モノリシックなWebアプリケーションを作成する開発者は、アプリケーション内のすべてのアスペクトを完全に制御できます。アプリケーション開発者は、必要に応じてURLを自由に設計できます。しかし、ポータル環境では事情が異なります。ポータル・アプリケーション開発者は、他のコンポーネントと結合されて1つの大きなポータル・アプリケーションに組み込まれるコンポーネントを提供します。このため、独自の方法でURLを生成することはできず、開発者はポータル・フレームワークによって提供されるメカニズムに従ってURLを作成する必要があります。

WebSphere Portalでは、マークアップを生成する(このため、URLの作成機能を必要とする)主要コンポーネントは次のとおりです。

  • テーマ:ページ全体のルック・アンド・フィールとページのレイアウトを作成します。
  • スキン:ポートレット・ウィンドウのルック・アンド・フィールを作成します。ウィンドウの状態やポートレットのポートレット・モードを変更するボタンも含まれます。
  • ポートレット:ポートレット・ウィンドウ内のコンテンツをレンダリングします。

この記事では、Java APIを使用したテーマとスキンのURLの生成方法を説明します。テーマとスキンのURLは、ポータルJSPタグ・ライブラリー(リソース・リストの「WebSphere Portal Information Center, Portal tag library」セクションを参照)のURLタグとURLGenerationタグを使用しても作成できます。これらのタグはほとんどのユース・ケースをカバーするため、一般的なユース・ケースではこれらのタグを使用してください。ただし、Java APIまたは追加機能が必要な状況では、Navigational State SPIと呼ばれるWebSphere Portal V5.1.0.1 System Programming Interface(SPI)を使用することができます。このようなユース・ケースの1つとして、URLを使用して別のテーマのテンプレートに切り替える場合が挙げられます。

他のポートレットを指すURLを生成する必要があるポートレットは、ポートレットAPIを使用しなければなりません(詳細については、リソース・リストの「JSR 168 Portlet Specification」リンクを参照してください)。たとえば、ポートレットAが別のページにあるポートレットBにパラメーターを送信し、ユーザーをそのページに移動させるユース・ケースを考えます。この場合、ポートレットBを指すURLを作成してページ階層をポートレットAにハード・コーディングする代わりに、ポートレットAでプロパティー・ブローカーのインフラストラクチャーを使用し、イベントを発生させる必要があります。ポータル管理者は、ポートレットAのイベントをポートレットBの入力に結び付けます。この結果、ポータルはそのページへの切り替えを自動的に実行します。詳細については、「リソース」の『Developing JSR 168 compliant cooperative portlets』を参照してください。

この記事は、ポータルの基本概念(第1部参照)とJSPの基礎を理解し、Javaプログラミングに習熟していることを前提として書かれています。


上に戻る

ステート・ハンドリングの確認

WebSphere Portal V5.1は、ポートレットについてのJSR168ナビゲーション・ステートの概念をポータル・サーバーのステートに拡張します。JSR168モデルは、ポートレットが使用できるステートとして、次のタイプのステートをサポートします。

  • パーシスタント・ステート(Persistent state):PortletPreferences APIを介して公開されます。ポートレットの実装者は、プリファレンスを使用して、ポータルのエンド・ユーザー・セッションでデータを保存および取得できます。
  • セッション・ステート(Session state):PortletSession APIを介して公開されます。セッション・ステートはサーバー上で保持されるデータを表し、このデータはポートレット・コンテナーによって管理される限られたライフタイムを持ちます。セッション・ステートの目的は、一時的な特性を持ち、他のステートや現在の対話からは再計算できない情報(たとえば、ショッピング・カートの中身)を保持することです。テーマとスキンは、HttpSessionを使用してセッション・ステートを使用できます。
  • ナビゲーション・ステート:PortletRequestを使用したレンダリングまたは対話パラメーターの形で公開されます。ナビゲーション・ステートは、ポートレット上の現在のビューに特有な情報(たとえば、選択されているタブ)を表します。このステートのライフタイムは、ポートレット要求のライフタイムと同じです。ポートレットのナビゲーション・ステートは、ポートレット・コンテナーによって、エンド・ユーザーと他のポータル成果物(たとえば、ページ上の他のポートレットまたはテーマ内のナビゲーション)との対話に沿って管理されます。ナビゲーション・ステートの使用は、WebSphere Portalでブラウザーの「戻る」と「進む」ボタンを有効にする際に重要です。ポートレットのレンダリング・パラメーターに加え、WebSphere Portalは、ページ選択、ページ・ナビゲーション・ツリーの展開状態、ポートレットのモードなどのナビゲーション・ステート情報を管理します。すべての指定済みポートレットの結合されたレンダリング・パラメーターは、システムの完全なナビゲーション・ステートを形成します。これは、ポータル・ページの各URLにエンコードしなければなりません。

図1.WebSphere Portalのさまざまなステート


ポートレットを設計するときは、ポートレットが管理するステートを識別し、これらを適切にエンコードする必要があります。特に、ナビゲーション・ステートとセッション・ステートはお互いに直交するよう設計しなければなりません。異なるナビゲーション・ステートと組み合わせて、同じセッションにアクセスできるからです。一般に、これが発生するのは、ユーザーが「戻る」ボタンを使用するとき、ポートレット特有のステートが含まれるブックマークを呼び出すとき、またはオリジナルのウィンドウとセッションを共有する新しいブラウザー・ウィンドウを開き、双方のウィンドウを個別にナビゲートするときなどです。

ポートレットによって生成された各リンクは、次の2つのカテゴリーに分類されます。

  • アクション・リンクは、ポートレットのアクション・フェーズを呼び出すトリガーとなります。ポートレットは、このフェーズでセッション・ステートまたはバックエンド・ステートを自由に変更でき、アクション・フェーズの最後に新しいレンダリング・パラメーターを関連付けます。これらのレンダリング・パラメーターは、アクション要求に続くレンダリング要求で有効になります。アクション・フェーズは、ページ上の他のポートレットがレンダリングを開始する前に呼び出されるため、この柔軟性の短所としてパフォーマンスが低下します。アクションの完了後にのみ、これらのポートレットはレンダリングを開始できます。しかし、WebSphere Portalのパラレル・ポートレット・レンダリング(Parallel Portlet Rendering)機能を有効にすると、これらのレンダリングを並列して実行できます。アクション・リンクは、WWW1のW3Cアーキテクチャー推奨(「リソース」参照)に適合させるために、常にPOSTリンクとしてエンコードする必要があります。
  • レンダー・リンクは、レンダリング・パラメーターのセットをリンクの呼び出し時に発行される要求と結び付けます。レンダー・リンクの呼び出しの結果として、ポートレットのアクション・フェーズは呼び出されず、ポートレットはレンダリング・パラメーターの新しいセットを使用してそのビューをレンダリングする必要があります。また、レンダー・リンクの呼び出しの結果として、ポートレットはセッション・ステートまたはバックエンド・ステートを変更することはできません。レンダー・リンクは、ポートレットと対話するために最も効率的な方法を提供し(JavaScriptを使用した未加工のクライアント・サイドの対話を除く)、ナビゲーション・ステートが変更された場合にのみ使用します。レンダー・リンクはGETリンクとしてエンコードしなければなりません(「リソース」参照)。

ポートレットの概念と同様に、テーマとスキンもアクション/レンダー・リンクのセマンティクスを持つリンクを生成します。これは、ポートレット・ステートではなく、ポータル・ステートの変更に関連します。

  • エンジン・アクション(Engine Actions)へのリンクは、ポートレットのアクション・リンクに相当します。このリンクは、サーバー・サイド・ステートを変更できるサーバー・サイド・コマンドを参照するためです。
  • それ以外のすべてのリンク(たとえば、ページ選択またはポートレット・ステート/モードの変更)は、ポートレットのレンダー・リンクに相当します。これらのリンクは、サーバーのステートを変更せずにポータル・サーバーだけの異なるビューを要求し、GETリンクとして表す必要があります(「リソース」参照)。


上に戻る

ナビゲーション・ステートのエンコード

ナビゲーション・ステートは、特定のクライアントに関連するポータルのビューを表します。クライアントはWebページと対話することにより(たとえば、新しいページへの移動により)、異なるビューを要求(照会)することができます。このタイプの対話はサーバー上の何も変更せず、サーバーによって提供される新しいビューだけを要求します。このため、これはHTTP用語でいう「安全な」オペレーションです。この対話は、ユーザーが最新のビュー間を前後に移動できる特性を持ちます。また、ビューをブックマークしておき、後でブラウザーのブックマークを呼び出すことにより、そのビューに戻ることができます。

開発者は、WebSphere Portalのナビゲーション・ステートをURLにエンコードすることで、この動作を実装します。異なるナビゲーション・ステートからは、異なるURLが生成されます。


上に戻る

Navigational State SPIを調べる

次に、新しいNavigational State SPIの主な概念と、これらの概念がお互いにどのように関連するのかを見ていきましょう。また、アクセサー・アプリケーション・プログラミング・インターフェース(Accessor Application Programming Interface)についても解説します。これは、ナビゲーション・ステート情報へのタイプ付きアクセスを可能にする便利なインターフェースです。

次のセクションで説明するすべてのインターフェースとクラスは、com.ibm.portal.state.* にパッケージングされています。


上に戻る

ナビゲーション・ステートとURLを表す

WebSphere Portal Version 5.1から、ナビゲーション・ステートは、ステート情報の階層として表されます。オブジェクト・モデルはタイプなしのステート情報を含むDOMに似た文書モデルで、java.lang.Stringとして表されます。この設計の決定は、「一般的なポータル・ページは多数のURLを含み、1つの要求につきナビゲーション・ステートが複数回シリアライズされる必要がある」という前提に基づいています。ストリング・ベースのメモリー表現によって、ナビゲーション・ステートのURLへの効率的なシリアライズが可能になります。つまり、シリアライズ・プロセスの際に、時間とCPUを消費する、オブジェクトからストリングへの変換を避けられます。

しかし、プログラマーの観点からは、厳密にタイプ付けされたインターフェースを使用してステート情報にアクセスする方がより便利でフェイルセーフとなります。このため、ステート・ハンドリングAPIには、ナビゲーション・ステート情報へのタイプ付きの読み取りおよび書き込みアクセスを提供する使いやすいインターフェース(アクセサーAPIの一部)が含まれています。「アクセサーAPIを使用したナビゲーション・ステートの読み取りと書き込み」を参照してください。

新しいステート・ハンドリングSPIの設計では、一般的なパターンとして、読み取り専用インターフェースを、読み取りおよび書き込み可能インターフェース(コントローラー)から分離する方法が使用されています。このため、APIはナビゲーション・ステートへの次の2つのインターフェースを提供します。

  • com.ibm.portal.state.StateHolderは、ナビゲーション・ステート情報への読み取りアクセスを提供します。
  • com.ibm.portal.state.StateHolderControllerはステート情報の変更を可能にします。

図2では、ステート・ホルダーが、タイプなしの文書モデルを内包するラッパーであることが示されています。このような設計となっているのは、まず、現在のナビゲーション・ステートを複製し、その後で、生成されたURLの特定のセマンティクスに従ってナビゲーション・ステートを変更する必要があるためです。たとえば、プログラマーが特定のポータル・ページを指すURLを作成したいとき、ステート文書モデル内のページ選択情報を変更しなければなりません。しかし、ページ上のすべてのURLでこの変更を有効にすべきではありません。

図2.タイプなしのDocumentModelを内包するStateHolder


ステート・ホルダーのライフタイムは1つの要求が処理されるまでの間です。要求を処理するときに、ステート・ホルダーが通過するライフサイクルのフェーズを図3に示します。

  • URLのデコード時に、ポータルはステート・ホルダーを作成し、受信した要求URLから取得したナビゲーション・ステートを割り当てます。次に、URLに含まれるフラットで文字ベースのステート表現を、階層的なオブジェクト表現(前述の文書モデル)に変換します
  • アクションの処理時に、ポータル・エンジンとポートレットはステートを変更できます。アクション・フェーズの処理が完了した後、ポータルはステートを固定し、変更できないようにします。
  • レンダリング時に、指定済みポータル・ページの一部であるポートレットとナビゲーション・コントロールは、URLを生成し、それらをマークアップに含めます。通常、生成されたURLはターゲットのナビゲーション・ステートをエンコードします。このナビゲーション・ステートは、固定されたステート・ホルダー(ベース・ステートとも呼ばれます)と、対応するURLの特定のセマンティクスを表す部分的なステート情報によって構成されます(「URLエンコードを理解する」を参照)。この段階ではベース・ステートを変更できないため、ポータル・エンジンは新しい各URL用に、このベース・ステートの(論理的な)コピーを作成します。このベース・ステートは、URLの目的とするセマンティクスに応じて変更できます。ベース・ステートを維持することにより、前の対話のナビゲーション・ステートは失われません。

図3.StateHolderオブジェクトのライフタイム


URLはcom.ibm.portal.state.EngineURLインターフェースによってモデル化されます。EngineURLはナビゲーション・ステートを含むURLを表します(「URLエンコードを理解する」を参照)。適切なURLファクトリーから新しいEngineURLインスタンスを要求するときに、EngineURLが参照する初期ステート・ホルダーを指定します。通常、これは要求固有のベース・ステートのコピーです。

APIの中心的なオブジェクトであるEngineURLインターフェースの簡単な概要をリスト1に示します。最も重要なメソッドは、この特定のEngineURLインスタンスが参照するステート・ホルダー・オブジェクトを返すgetState()メソッドです。このメソッドは変更可能なインターフェース(StateHolderController)をステート・ホルダーに返すため、プログラマーはこのEngineURL用にステートを変更できます。ステートの変更方法の詳細については、「アクセサーAPIを使用したナビゲーション・ステートの読み取りと書き込み」を参照してください。

writeCopy()メソッドおよびwriteDispose()メソッドによって、EngineURLを指定されたWriter(たとえば、HTTP応答から取得したマークアップPrintWriter)へストリーミングすることができます。(toString()を使用することもできますが、これはかなりコストの高いオペレーションなので、推奨できません。)

リスト1.EngineURLインターフェース

 public interface EngineURL extends DisposableURL {	
    /** Returns a read-write interface to the state carried by this URL */
    StateHolderController getState();
    /** Specifies whether the URL should point to public /protected area */
    void setProtected(Boolean bFlag);	
    /** Specifies whether a secure connection is requested */
    void setSecure(Boolean bFlag);
    /**
     * Streams the URL to the given writer. Maintains the state of the URL
     * i.e. this method can be called multiple times.
     */
    Writer writeCopy(Writer out)
       throws IOException, OutputMediatorException, 
              PostProcessorException, DocumentModelException;
    /**
     * Streams the URL to the given writer and finally releases the state
     * of the URL. The EngineURL object must not be accessed after 
     * invoking this method
     */
    Writer writeDispose(Writer out)
       throws IOException, OutputMediatorException, PostProcessorException;
}


上に戻る

URLエンコードを理解する


WebSphere Portal V5.1に導入されたURLエンコードの実装は、次の点でパフォーマンスが最適化されています。

  • URLの生成に必要な処理時間を最小限にします。特に、URLに含めなければならないナビゲーション・ステートのシリアライズに要する時間が短縮されます。
  • URLをできるだけ短くします。これにより、マークアップのサイズが減少すると共に、一部のブラウザーで行われているURLの長さの制限(2KBまで)に適合します。

これらの要件を満たすために、URLエンコードはデルタ・エンコードと呼ばれる手法を用いて実装されます。デルタ・エンコードは、プログラマーが明示的に他のステートにURLのベースを置かない限り、固定されたベース・ステート(アクション・フェーズの後で利用可能)を、(少なくとも概念的に)各URLに含める必要があるという考えに基づいています。作成された各URLのベース・ステートがシリアライズされるのを防ぐため、アクション・フェーズの直後に前もってシリアライズ(プレシリアライズ)が行われます。URLの生成時に、プレシリアライズされたベース・ステートは、非相対的な各URLに設定されます。URL固有のセマンティクスを指定するステート・デルタは、相対URLのパス情報に個別にエンコードされます。

次の例は、コーデック識別子kcxmlの後にシリアライズされたベース・ステート部分を含む絶対「デルタURL」です。デルタ・コーデック識別子delta/base64xmlの直後に、ステート・デルタ部分があります。


http://myserver.com:9081/wps/portal/kcxml/04_Sj9SPykssy0xPLMnMz0vM0Y_QjHvm5qf
oFuaE6KigCBh9CG/delta/base64xml/Y2BkbGBgYlrDwMDE3srCasTUq!


相対URLを生成できると、状態はさらに改善されます。ブラウザーは、相対URLを現在の要求URLまたはHTMLベース・タグの値(存在する場合)に追加します。WebSphere Portalは、プレシリアライズされたベース・ステートをHTMLベース・タグを使用してHTMLページのヘッダーに挿入することにより、相対URLを活用します。具体的な相対URLには、ステート・デルタのみが含まれます。次の例は、この規則によってマークアップ・サイズが大幅に削減されることを示します。


<head>
    <base href="http://myportal.com:9081/wps/portal/!ut/p/kcxml/04_Sj9SPykssy0xPAIuz!
    </base>
</head>
<body>
...
    <td class="wpsToolBar" valign="middle" nowrap>
       <a href="delta/base64xml/L2dJQSEvUUt3QS80SVVFLzZfQkEwN1VTOVMyMzAwR0!"
          class="wpsToolBarLink">Administration</a>
    </td>
...


相対URLを使用できないケースもあります。たとえば、プロトコルがhttpからhttpsに切り替わる場合は、生成されたURLは絶対URLでなければなりません。また、マークアップでJavaScriptが多用されていると、ブラウザーは相対URLを解決できません。ポータル・ページに含まれるカスタム・マークアップでのこのようなJavaScriptの問題を防ぐために、WebSphere Portal ではデフォルトで相対URLが無効になっています(たとえば、ポートレットによって生成されたマークアップなど)。しかし、Navigational State SPIには、明示的に相対URLを作成する方法が用意されています(詳細については、「URLAccessorFactoryを使用したURLの作成」を参照してください)。


上に戻る

アクセサーAPIを使用したナビゲーション・ステートの読み取りと書き込み

アクセサーAPIは、ステート文書モデルへのタイプ付きアクセスを提供します。アクセサーAPIにより、プログラマーは容易にナビゲーション・ステート情報を照会および変更することができます。

図4に、アクセサーAPIを示します。アクセサーAPIは、特定のノードへのアクセスを階層的な文書モデルにカプセル化する抽象化層です。ナビゲーション・ステートの各様相について(たとえば、ページ選択、展開ステート、ポートレット・ステートなど)、アクセサーAPIはアクセサー・ファクトリーを提供します。アクセサー・ファクトリーは、参照する特定のステートに応じた読み取り専用アクセサーと読み取りおよび書き込みアクセサーを提供します。アクセサーは、ステート文書モデルの対応する位置から、直接読み取りや書き込みを行います。また、アクセサーは必要な型変換も行います。

必要なナビゲーション・ステート情報はステート文書モデル内にあり、専用のアクセサー・ファクトリー・インプリメンテーション内にカプセル化されています。一般に、アクセサー・ファクトリーはパス表記を使用して、ステート文書モデル内で特定の文書ノードを検索したり、ノード(または、ノードの完全なパス)を作成します。ノードが見つかると、アクセサー・ファクトリーは、ノード参照をアクセサーまたはアクセサー・コントロールに、その初期化中に渡します。アクセサー(およびアクセサー・コントローラー)のインプリメンテーションは、ステート文書モデルの構造から独立しています。つまり、必要な情報がステート文書モデル内の別のノードに移動した場合でも、アクセサーを再使用できます。

図4にいくつかの重要なアクセサーを示します。対応するアクセサー・ファクトリーは省略されています。

図4.アクセサーAPI


それでは、選択アクセサー・ファクトリーcom.ibm.portal.state.selection.SelectionAccessorFactoryと、それに関連するすべてのインターフェースを詳しく見ていきましょう。これらをリスト2に示します。

リスト2.SelectionAccessorFactoryインターフェースと関連インターフェース

public interface SelectionAccessorFactory extends AccessorFactory {
    /** Returns a read-only accessor operating on the given state */
    SelectionAccessor getSelection(StateHolder state);
    /** Returns a read-write accessor operating on the given state */
    SelectionAccessorController getSelectionController(StateHolderController state);
}

public interface SelectionAccessor extends Accessor {
    /** Returns the object id of the currently selected portal page */
    ObjectID getSelection() throws InvalidSelectionNodeIdException;
}
public interface SelectionAccessorController extends SelectionAccessor {
    /** Selects the page that corresponds with the given id */
    void setSelection(ObjectID pageID) throws CannotInsertSelectionNodeException;
    /** Selects the page that corresponds with the given unique name */
    void setSelection(String uniqueName) throws CannotInsertSelectionNodeException;
} 


他のアクセサー・ファクトリーと同様に、SelectionAccessorFactoryは読み取り専用のSelectionAccessorを返すメソッドと、読み取りおよび書き込み可能なSelectionAccessorControllerを返すメソッドを公開します。getSelectionAccessor()メソッドは、読み取り専用のStateHolderインターフェースを引数として受け取ります。getSelectionController()には、読み取りおよび書き込み可能なStateHolderControllerインターフェースが必要です。

アクセサーが動作するステートは、必ずしも、要求URLから取得された要求固有のベース・ステートではないため、この軽量のパターン(ステートが引数として渡される)が選択されています。通常、これは特定のEngineURL用に作成されたステート・クローンです。EngineURLオブジェクトにgetState()を呼び出すことにより、URL固有のステート・ホルダーを取得できます。SelectionAccessorControllerを使用して、作成されたEngineURLが特定のポータル・ページ(たとえば、[Stock Market]ページ)を指すようにする方法をリスト3に示します。

リスト3.SelectionAccessorControllerを使用したページ・リンクの作成

 final EngineURL url = ...;
final SelectionAccessorFactory selFct = ...;

final SelectionAccessorController selCtrl = 
    selFct.getSelectionController(url.getState());

try {
    selCtrl.setSelection("wps.StockMarket");
} catch (StateException e) {
    // error handling
    ...
} finally {
    selCtrl.dispose();
}


ベース・アクセサー・インターフェースは、com.ibm.portal.Disposableインターフェースから派生しています。アクセサーが不要になったとき、プログラマーはdispose()メソッドをそのアクセサーに呼び出すことにより、不要なアクセサーを明示的に示すことが推奨されています。これにより、アクセサー・ファクトリー・インプリメンテーションはオブジェクト・プールにアクセサー・ファクトリーを保存し、パフォーマンスを改善することができます(初期化のオーバーヘッドとガーベッジ・コレクションが削減されます)。


上に戻る

PortalStateManagerServiceを使用したURLの生成

WebSphere Portalバージョン5.1.0.1の新しいサービスであるPortalStateManagerServiceを使用すると、プログラマーはポータルの高度なユース・ケースを実装するURLを容易に作成できます。

このサービスは、次の目的で使用できます。

  • WebSphere Portalタグ・ライブラリー(特に、URL-タグとURLGeneration-タグ)が十分でない場合に、テーマ(JSP)内にURLを作成します。
  • ポータル関連の成果物(カスタム・タグ、カスタム・ポータル・アクションなど)でプログラマチックにURLを作成します。
  • プログラマチックにURLを「オフライン」で作成します。これは、現在のサーブレット要求(たとえば、Enterprise JavaBeans)にアクセスしないビジネス・コンポーネントでの作成を意味します。

次のサブセクションでは、PortalStateManagerServiceへのアクセス方法とURLの作成方法を説明します。最後のサブセクションでは、この新しいサービス(SPIの一部)を使用するカスタムのパンくずリスト・ナビゲーション・タグの実装方法を説明します。

PortalStateManagerServiceへのアクセス

PortalStateManagerServiceにアクセスするには、名前検索ポータルservice/state/PortalStateManagerでJNDI検索を使用します。検索は、特定のcom.ibm.portal.state.service.PortalStateManagerServiceを取得するgetterメソッドを持つcom.ibm.portal.state.service.PortalStateManagerServiceHomeインターフェースを返します。

PortalStateManagerServiceHomeインスタンスは、ポータルのライフタイムで有効です。このため、JNDI検索は1回だけ実行し、取得したホーム・オブジェクトを保存します(たとえば、インスタンス内または静的変数内に保存します)。

PortalStateManagerHomeオブジェクトとは異なり、PortalStateManagerServiceには要求のスコープがあります。つまり、PortalStateManagerServiceは1つのサーブレット要求でのみ使用できます。それ以降のすべてのサーブレット要求では、ホーム・インターフェースからの新しいサービス・インスタンスを要求する必要があります。このサービスへのアクセス方法をリスト4に示します。

リスト4.PortalStateManagerServiceへのアクセス方法

/** the JNDI name to retrieve the PortalStateManagerServiceHome object */
private static final String JNDI_NAME = 
                               "portal:service/state/PortalStateManager";

/**
 * The PortalStateManagerServiceHome object to retrieve the service from 
 */
private static PortalStateManagerServiceHome serviceHome;

/** Any method processing request and response. */
public void anyMethod(final HttpServletRequest request,
                      final HttpServletResponse response) {
    try {
        // get the service from our home interface
        final PortalStateManagerService service
            = getServiceHome().getPortalStateManagerService(request, response);
       // use the service
       ...
       // indicate that we do not need it any longer
       service.dispose();
    } catch (Exception e) {
        // error handling
    }
}
/**
 * Looks up the PortalStateManagerServiceHome being valid
 * for the lifetime of the portal.
 */
private static PortalStateManagerServiceHome getServiceHome() {
    if (serviceHome == null) {
        try {
            final Context ctx = new InitialContext();
            serviceHome =
                (PortalStateManagerServiceHome) ctx.lookup(JNDI_NAME);
        } catch (Exception e) {
            // error handling
        }
    }
    return serviceHome;
} 


PortalStateManagerServiceインターフェースは、com.ibm.portal.Disposableインターフェースから派生しています。サービスが不要になったとき、プログラマーはdisposeメソッドを呼び出すことにより、不要なサービスを明示的に示すことが推奨されています。このサービスは要求スコープを持つため、遅くとも要求の最後ではサービスを破棄する必要があります。

サービスの要求スコープの規則に関し、1つだけ例外があります。要求の処理(または、ポータル)から完全に切り離されている環境またはコンポーネントでこのサービスが使用されている場合、サービスのライフタイムは未定です。このような場合、ホーム・インターフェースからサービスを要求し、要求と応答でnullを渡すことにより、適切なときにそれを破棄できます。

PortalStateManagerServiceの使用

com.ibm.portal.state.PortalStateManagerServiceインターフェースには、次の2つのメソッドがあります。

StateHolderController newState()
変更可能な新しいステート・ホルダーを作成します。いくつかのEngineURL用のベースとして機能する新しいナビゲーション・ステートをプログラマチックに作成するときに、このメソッドを使用します。
AccessorFactory getAccessorFactory(final Class cls)
このサービスによって提供される機能にアクセスできるようにします。決定的な役割は、いわゆるURLAccessorFactoryによって行われます。これにより、プログラマーは、さまざまなユース・ケースをサポートするURLを作成できます。その他すべての取得可能なアクセサー・ファクトリーは、ナビゲーション・ステートの対応するアスペクトを変更することにより、URLの特定のセマンティクスを表現するために必要です。

このサービスを使用するには:

  1. URLAccessorFactoryを使用して新しいEngineURLオブジェクトを取得します。
  2. EngineURLオブジェクトに関連付けられているStateHolderControllerを変更し、作成されたURLのセマンティクスを指定します。getAccessorFactory(Class)メソッドによって取得する適切なアクセサー・ファクトリーを使用します。
  3. マークアップに含めるために、EngineURLを出力ストリーム(たとえば、JSPWriter)に書き込みます。

次に、URLAccessorFactoryを使用してURLを作成する方法を見ていきましょう。


上に戻る
次のページへ