プライマリ・コンテンツに移動
Oracle® Fusion Middleware Oracle JDeveloperによるWebCenter Portalアセットとカスタム・コンポーネントの開発
12c (12.2.1.1)
E79323-01
目次へ移動
目次

前
次

12 Oracle JSF Portlet Bridgeを使用したJSFアプリケーションからのポートレットの作成

この章では、Oracle JSF Portlet Bridgeを使用してJSFアプリケーションをポートレットとして公開する方法について説明します。

この章の内容は次のとおりです。

注意:

Oracle JSF Portlet Bridgeは、JSR 329のApache Reference実装を拡張します。JSR 329は、Portlet 2.0 Bridge for JavaServer Face対応Portlet 2.0 Bridgeの機能を定義するための標準化への取組みです。オラクル社はこの標準化の仕様において指導的地位にあります。詳細は次でご覧いただけます。

http://www.jcp.org/en/jsr/detail?id=329

12.1 Oracle JSF Portlet Bridgeを使用したJSFアプリケーションからのポートレットの作成について

Oracle JSF Portlet Bridgeを使用すると、アプリケーション開発者は、短時間で簡単に既存のJSFアプリケーション、Oracle ADFアプリケーションおよびタスク・フローをJSR 286ポートレットとして公開できます。

注意:

特に断りのないかぎり、JSFアプリケーションという用語にはOracle ADFアプリケーションが含まれます。

Oracle JSF Portlet Bridge:

  • JSR 286ポートレットAPIに依存せずにJSFを使用してポートレット機能を提供できるようにすることでポートレット開発を簡略化します。

  • WebCenter PortalなどのJSR 286ポートレット・コンシューマへのJSFアプリケーションの公開を簡略化します。

  • アプリケーションが通常のWebアプリケーションとして、および同じインストールからのポートレットとして同時に実行できるようにすることで、アプリケーションから別々にポートレットを格納、維持およびデプロイするという要件を排除します。

  • ポートレットをタスク・フローとして公開することで、より精度の高いレベルでポートレットを作成できます。ポートレット化されたタスク・フローはJSR 286ポートレットであるため、これによってタスク・フローを分散環境で使用することもできます。

注意:

Oracle JSF Portlet Bridgeによって使用されるWSRP拡張機能が原因で、JSFポートレットが想定どおりにサード・パーティのWSRPコンシューマと連携して動作しない場合があります。

12.2 JSFアプリケーションからのポートレットの作成

Oracle JSFポートレット・ブリッジを使用すると、JSFアプリケーションまたはタスク・フローをポートレットとして公開できます。これは、「ポートレット・エントリの作成」ダイアログを使用して宣言的に実行できます。コーディングは不要です。「ポートレット・エントリの作成」ダイアログを使用すると、JSFアプリケーション上にOracle JSF Portlet Bridgeを構成してJSFアプリケーションをJSR 286ポートレットとして公開できます。この構成の一部として、ポートレットがレンダリングされるときに呼び出す最初のJSFビュー(またはタスク・ビュー)を示します。その時点から、Oracle JSF Portlet BridgeはJSFアプリケーションと連動して、この初期ビューから到達できる追加ビューを介して移動します。そのため、JSFアプリケーション全体をポートレットとして公開する通常の状況では、ポートレットでのアプリケーションの初期のビューをレンダリングしてナビゲーションの残りは同じポートレット内で自然に動作するようにOracle JSF Portlet Bridgeを構成する必要があります。

この項には次のトピックが含まれます:

12.2.1 ページに基づいたJSFポートレットの作成方法

JSFアプリケーションからポートレットを作成する最も簡単な方法とは、ページに基づいてポートレットを生成するというものです。

既存のアプリケーション・ページからJSFポートレットを作成するには:

  1. JDeveloperで、ポートレット化するJSFページを含むアプリケーションを開きます。
  2. アプリケーション・ナビゲータで、JSFページを右クリックして、「ポートレット・エントリの作成」を選択します。

    注意:

    ポートレットを含むページに基づいてポートレットを生成することはできません。

  3. 「ポートレット・エントリの作成」ダイアログで、「ポートレット名」フィールドにポートレットの名前を入力します。
  4. 「表示名」フィールドに、ポートレットの記述名を入力します。
  5. 「ポートレット・タイトル」フィールドに、ポートレットを説明するタイトルを入力します。

    ポートレット・タイトルは、「リソース・パレット」または「アプリケーション・リソース」パネルに表示されるため、ポートレットが便利かどうかどうかをユーザーが決定するのに役立つタイトルにしてください。ポートレットのタイトルは、ポートレットがページに表示されるとポートレットのヘッダーにも表示されます。

  6. 「短いタイトル」フィールドに、ポートレットの短いタイトルを入力します。この短いタイトルは、モバイル・デバイスでポートレットがページに表示されるとポートレットのヘッダーに表示されます。
  7. 「説明」フィールドに、ポートレットの説明を入力します。
  8. 「コンテキスト・イベント用ポートレット・イベントの作成」を選択して、ページによって公開されるコンテキスト・イベント用のportlet.xmlファイル内にポートレット・イベントを作成します。このオプションはデフォルトで選択されます。

    ポートレット・イベントによってポートレットは自らが存在するページと、およびそのページ上のその他のポートレットと通信できます。

  9. 「OK」をクリックします。

ページに基づいたJSFポートレットを作成すると、ページのポートレット・エントリ(次の例を参照)が含まれるようにportlet.xmlファイルが作成(またはこのファイルがすでに存在する場合は更新)されます。ファイルが開き、表示と編集ができます。デフォルトでは、ファイルは設計ビューで開きます。ソース・コードを表示または編集するには、「ソース」タブをクリックします。

<portlet id="adf_jsf__testPage_jspx">
 <description>PortletBridgeApplication_testPage_jspx</description>
 <portlet-name>PortletBridgeApplication_testPage_jspx</portlet-name>
 <display-name>PortletBridgeApplication_testPage_jspx</display-name>
 <portlet-class>
 oracle.portlet.bridge.adf.application.ADFBridgePortlet
 </portlet-class>
 <init-param>
 <name>javax.portlet.faces.defaultViewId.view</name>
 <value>/myPage.jspx</value>
 </init-param>
 <supports>
 <mime-type>text/html</mime-type>
 <portlet-mode>VIEW</portlet-mode>
 </supports>
 <supported-locale>en</supported-locale>
 <portlet-info>
 <title>PortletBridgeApplication_testPage_jspx</title>
 <short-title>PortletBridgeApplication_testPage_jspx</short-title>
 </portlet-info>
 <supported-processing-event id="DepartmentSelectedEvent">
 <qname xmlns:x="http://xmlns.oracle.com/adfm/contextualEvent">
 x:DepartmentSelectedEvent
 </qname>
 <supported-publishing-event id="DepartmentSelectedEvent">
 <qname xmlns:x="http://xmlns.oracle.com/adfm/contextualEvent">
 x:DepartmentSelectedEvent
 </qname>
 </supported-publishing-event>
 <supported-public-render-parameter>
 _adf_event_DepartmentSelectedEvent
 </supported-public-render-parameter>
 <container-runtime-option>
 <name>com.oracle.portlet.requireIFrame</name>
 <value>true</value>
 </container-runtime-option>
 <container-runtime-option>
 <name>com.oracle.portlet.minimumWsrpVersion</name>
 <value>2</value>
 </container-runtime-option>
</portlet>

選択したページは、ポートレットの編集モードのエントリ・ポイントとして使用されます。これは、javax.portlet.faces.defaultViewId.view初期化パラメータによってportlet.xmlファイルに示されます。portlet.xmlファイルを手動で編集して、WebCenter Portalがサポートするその他のデフォルトの拡張ポートレット・モードに対応したページを定義できます。

  • 編集モード: javax.portlet.faces.defaultViewId.edit

  • ヘルプ・モード: javax.portlet.faces.defaultViewId.help

  • 情報モード: javax.portlet.faces.defaultViewId.about

  • 構成モード: javax.portlet.faces.defaultViewId.config

  • デフォルト編集モード: javax.portlet.faces.defaultViewId.edit_defaults

  • プレビュー・モード: javax.portlet.faces.defaultViewId.preview

  • 印刷モード: javax.portlet.faces.defaultViewId.print

注意:

defaultViewIdの値は、アプリケーション・コンテキスト・ルートに対して相対的であり、常に/で始まる必要があります。前述の例では、defaultViewId.viewの値は/myPage.jspxです。

その他のポートレット・モードにdefaultViewIdを追加する場合は、<supports>タグにもモードを追加するようにしてください。たとえば、<portlet-mode>HELP</portlet-mode>のようになります。

ポートレット・モードの詳細は、「ポートレット・モード」を参照してください。

12.2.2 タスク・フローに基づいたJSFポートレットの作成方法

この項には次のトピックが含まれます:

12.2.2.1 タスク・フローからのポートレットの作成について

Oracle ADFを使用する利点とは、タスク・フローの存在であり、アプリケーションで制御フローを定義するためのモジュール式アプローチとなります。アプリケーションを1つの大きなJSFページフローとして表すかわりに、再利用可能なタスクフローの集合として分類することができます。各タスク・フローで、アプリケーション・アクティビティ、つまり、アプリケーションが完了するために実行される必要のある作業単位を特定してください。アクティビティとは、タスク・フローの実行時に行うことができる作業を意味しています。

タスク・フローはバインドなしでもバインドありでも可能です。

  • バインドなしタスク・フローは、ユーザーがタスクを完了できるように相互作用する一連のアクティビティ、制御フロー・ルールおよびマネージドBeanです。バインドなしタスク・フローは、アプリケーションのどのバインド・タスク・フローにも含まれていないすべてのアクティビティと制御フローで構成されます。

  • バインド・タスク・フローはタスク・フローの特殊な形式であり、単一エントリ・ポイントと1つ以上の終了ポイントがあります。プライベート制御フロー・ルール、アクティビティおよびマネージドBeanの独自のセットが含まれています。Oracle ADFバインド・タスク・フローでは、再利用、パラメータ、トランザクション管理および再入力が可能です。また、多くの終了ポイントでゼロとなることも可能です。バインド・タスク・フローは、ページまたはページ・フラグメントを使用できますが、ページ・フラグメントを使用するものだけポートレット化できます。

一般的なアプリケーションは、1つのバインドなしタスク・フローと1つ以上のバインド・タスク・フローを組み合せたものです。このため、アプリケーションでは、バインドなしタスク・フロー内のアクティビティからバインド・タスク・フローをコールできます。バインド・タスク・フローおよびバインドなしタスク・フローの詳細は、『Oracle Application Development FrameworkによるFusion Webアプリケーションの開発』を参照してください。

12.2.2.2 「ポートレット・エントリの作成」ダイアログを使用したタスク・フローからのポートレット作成

「ポートレット・エントリの作成」ダイアログを使用して単一のタスク・フローからポートレットを作成します。

「ポートレット・エントリの作成」ダイアログを使用してタスク・フローからのポートレットを作成するには:

  1. JDeveloperで、ポートレットの作成元となるタスク・フローを含むJSFアプリケーションを開きます。
  2. アプリケーション・ナビゲータで、ポートレット化するタスク・フローを右クリックして、「ポートレット・エントリの作成」を選択します。
  3. 「ポートレット・エントリの作成」ダイアログで、「ポートレット名」フィールドにポートレットの名前を入力します。
  4. タスク・フローがバインドされていない場合、「エントリ・ポイント・ビュー」ドロップダウン・リストには、そのタスク・フローのすべてのビュー・アクティビティが表示されます。このドロップダウン・リストから、ポートレットのエントリ・ポイントとして使用するビュー・アクティビティを選択します。デフォルトでは、タスク・フローの最初のビュー・アクティビティが選択されます。

    タスク・フローがバインドされている場合、可能なエントリ・ポイントは1つしかないため「エントリ・ポイント・ビュー」ドロップダウン・リストは表示されません。

  5. 「表示名」フィールドに、ポートレットの記述名を入力します。
  6. 「ポートレット・タイトル」フィールドに、ポートレットを説明するタイトルを入力します。

    ポートレット・タイトルは、「リソース・パレット」または「アプリケーション・リソース」パネルに表示されるため、ポートレットが便利かどうかどうかをユーザーが決定するのに役立つタイトルにしてください。ポートレットのタイトルは、ポートレットがページに表示されるとポートレットのヘッダーにも表示されます。

  7. 「短いタイトル」フィールドに、ポートレットの短いタイトルを入力します。この短いタイトルは、モバイル・デバイスでポートレットがページに表示されるとポートレットのヘッダーに表示されます。
  8. 「説明」フィールドに、ポートレットの説明を入力します。
  9. 「コンテキスト・イベント用ポートレット・イベントの作成」を選択して、タスク・フローにより公開されるすべてのコンテキスト・イベント用のportlet.xmlファイル内にポートレット・イベントを作成します。このオプションはデフォルトで選択されます。

    ポートレット・イベントによってポートレットは自らが存在するページと、およびそのページ上のその他のポートレットと通信できます。

  10. 「OK」をクリックします。

1つ(または複数)のポートレットが作成されると、次のように示すメッセージを受け取ることになります。

New portlet has been successfully created

また、portlet.xmlファイルが作成されます。portlet.xmlファイルにはポートレット・エントリ(次の例を参照)が含まれており、表示や編集が可能な状態で開かれます。

<portlet id="adf_taskflow_WEB_INF_department_xml">
 <description>PortletBridgeApplication department</description>
 <portlet-name>PortletBridgeApplication_department</portlet-name>
 <display-name>PortletBridgeApplication department</display-name>
 <portlet-class>oracle.portlet.bridge.adf.application.ADFBridgePortlet</portlet-class>
 <init-param>
 <name>javax.portlet.faces.defaultViewId.view</name>
 <value>
 /adf.task-flow?adf.tfDoc=/WEB-INF/adfp-portlet-bridge-container.xml
 &amp;adf.tfId=adfp-portlet-bridge-container&amp;_fragmentTaskFlowDoc=/WEB-INF/
 department.xml&amp;_fragmentTaskFlowId=department
 </value>
 </init-param>
 <supports>
 <mime-type>text/html</mime-type>
 <portlet-mode>VIEW</portlet-mode>
 </supports>
 <supported-locale>en</supported-locale>
 <portlet-info>
 <title>PortletBridgeApplication department</title>
 <short-title>PortletBridgeApplication department</short-title>
 </portlet-info>
 <supported-publishing-event id="DepartmentSelectedEvent">
 <qname xmlns:x="http://xmlns.oracle.com/adfm/contextualEvent">
 x:DepartmentSelectedEvent
 </qname>
 </supported-publishing-event>
 <supported-public-render-parameter>
 _adf_event_DepartmentSelectedEvent
 </supported-public-render-parameter>
 <container-runtime-option>
 <name>com.oracle.portlet.requireIFrame</name>
 <value>true</value>
 </container-runtime-option>
 <container-runtime-option>
 <name>com.oracle.portlet.minimumWsrpVersion</name>
 <value>2</value>
 </container-runtime-option>
</portlet>

注意:

portlet.xmlファイルは複数のポートレットを含む場合もあり、ポートレットとして公開されページとタスク・フローの組合せを持つ場合もあります。また、標準JSR 286(非ブリッジ)ポートレットが含まれる場合もあります。

12.2.2.3 「タスク・フローのポートレット・エントリの管理」ダイアログを使用したタスク・フローからのポートレット作成

プロジェクトがタスク・フローを含んでいる場合は、タスク・フローを選択してリストからポートレットとして作成する方が簡単な場合もあります。これは「タスク・フローのポートレット・エントリの管理」ダイアログを使用して実行できます。また、このダイアログでは、ポートレットを個々に作成するのではなく複数のタスク・フローから一度にポートレットを作成することもできます。

「タスク・フローのポートレット・エントリの管理」ダイアログを使用してたタスク・フローからのポートレットを作成するには:

  1. メイン・メニューから「ファイル」を選択して「新規」を選択します。
  2. 「新規ギャラリ」で「Web層」を展開し、「ポートレット」「タスク・フローのポートレット・エントリの管理」「OK」の順に選択します。
  3. 「タスク・フローのポートレット・エントリの管理」ダイアログで、シャトル・ボタンを使用してポートレットとして作成するタスク・フローを選択します。
  4. 「コンテキスト・イベント用ポートレット・イベントの作成」を選択して、タスク・フローにより公開されるすべてのコンテキスト・イベント用のportlet.xmlファイル内にポートレット・イベントを作成します。このオプションはデフォルトで選択されます。

    ポートレット・イベントによってポートレットは自らが存在するページと、およびそのページ上のその他のポートレットと通信できます。

  5. 「OK」をクリックして選択されているタスク・フローのポートレットを作成します。

1つ(または複数)のポートレットが作成されると、次のように示すメッセージを受け取ることになります。

New portlet has been successfully created

また、portlet.xmlファイルが作成されます。portlet.xmlファイルにはポートレット・エントリ(次の例を参照)が含まれており、表示や編集が可能な状態で開かれます。

<portlet id="adf_taskflow_WEB_INF_department_xml">
 <description>PortletBridgeApplication department</description>
 <portlet-name>PortletBridgeApplication_department</portlet-name>
 <display-name>PortletBridgeApplication department</display-name>
 <portlet-class>oracle.portlet.bridge.adf.application.ADFBridgePortlet</portlet-class>
 <init-param>
 <name>javax.portlet.faces.defaultViewId.view</name>
 <value>
 /adf.task-flow?adf.tfDoc=/WEB-INF/adfp-portlet-bridge-container.xml
 &amp;adf.tfId=adfp-portlet-bridge-container&amp;_fragmentTaskFlowDoc=/WEB-INF/
 department.xml&amp;_fragmentTaskFlowId=department
 </value>
 </init-param>
 <supports>
 <mime-type>text/html</mime-type>
 <portlet-mode>VIEW</portlet-mode>
 </supports>
 <supported-locale>en</supported-locale>
 <portlet-info>
 <title>PortletBridgeApplication department</title>
 <short-title>PortletBridgeApplication department</short-title>
 </portlet-info>
 <supported-publishing-event id="DepartmentSelectedEvent">
 <qname xmlns:x="http://xmlns.oracle.com/adfm/contextualEvent">
 x:DepartmentSelectedEvent
 </qname>
 </supported-publishing-event>
 <supported-public-render-parameter>
 _adf_event_DepartmentSelectedEvent
 </supported-public-render-parameter>
 <container-runtime-option>
 <name>com.oracle.portlet.requireIFrame</name>
 <value>true</value>
 </container-runtime-option>
 <container-runtime-option>
 <name>com.oracle.portlet.minimumWsrpVersion</name>
 <value>2</value>
 </container-runtime-option>
</portlet>

注意:

portlet.xmlファイルは複数のポートレットを含む場合もあり、ポートレットとして公開されページとタスク・フローの組合せを持つ場合もあります。また、標準JSR 286(非ブリッジ)ポートレットが含まれる場合もあります。

12.2.3 JSFポートレットの作成時の必知事項

JSR 286ポートレット・マークアップ・フラグメント・ルールに準拠したマークアップを生成するようにJSFページをコーディングする必要があります。Oracle ADFを使用することを選択している場合、ページのマークアップの大部分はOracle ADF Facesのコンポーネントからのものであるため、マークアップはJSFポートレットと互換性のあるスタイルでレンダリングされるか、または(たとえば、ポートレットをインライン・フレーム内にレンダリングすることで)Oracle JSF Portlet Bridgeによって互換性のあるスタイルに自動解釈できます。

次の各項では、ポートレットとして後で公開することにしたOracle ADFページをコーディングする際に発生する一般的な問題を回避する方法についてのガイダンスを示します。

この項には次のトピックが含まれます:

12.2.3.1 JSFポートレットを作成するための一般的なガイドライン

JSFポートレットを作成する際には、次の一般的なガイドラインを考慮してください。

  • アプリケーションはWebアプリケーションとして実行する必要がある。JSFアプリケーションからポートレットを作成する前に、そのページとタスク・フローをすべて含むアプリケーションが、統合WLSにデプロイされた後で適切に動作している必要があります。通常のWebアプリケーションとして実行できない場合、これはポートレット・プロデューサとしても実行できません。

  • ポートレットは様々なページに含まれる。ポートレットとして公開されるタスク・フローの作成時に考慮するべき領域とは、タスク・フローをポートレットとしてレンダリングするページが元のプロデューサ・アプリケーションのページと異なるということです。

    発生する主な共通エラーは次のとおりです。

    • 使用ページでJavaScriptへのアクセスを期待します。

    • 使用ページの一部としてスコープに追加されたマネージドBeanまたはオブジェクトの検索を期待します。

    • コンシューマからのJSFコンポーネント・ツリーにコンポーネントの存在を期待します。

  • サーブレットの依存性。サーブレット環境とポートレット環境の両方での実行がサポートされているアプリケーションを記述する場合には、HttpServletオブジェクトへのキャストを回避します(またはポートレットとして実行時にClassCastExceptionを取得してください)。かわりに、Faces ExternalContextオブジェクトが提供する抽象化を使用します。たとえば、次のかわりに:

    HttpServletRequest request =getRequestFromFacesContext();
    String localContextPath =request.getContextPath();
    

    次を使用します。

    String localContextPath=
    FacesContext().getCurrentInstance().getExternalContext().getRequestContextPath();
    

    ExternalContextが抽象化を提供しないかぎり、サーブレットまたはポートレット固有のコードを記述できます。アプリケーションがポートレットとして実行されているかどうかは次の例に示すメソッドを使用して確認できます。

    public static boolean isPortletRequest()
     {
    Map<String, Object> m =
    FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
     Object phase =m.get("javax.portlet.faces.phase");
     if (phase != null)
     {
    return true;
     }
    else
     {
    return false;
     }
    }
    
  • 保護されているアプリケーション。アプリケーションが保護されている場合、必ずアイデンティティ伝播を保護しておきます。

  • ディープ・リンク。ポートレットとの通常の対話処理については、コンシューマとプロデューサとの間で保持されるセッションがあります。これは、コンシューマにセッションCookieを保存し、それをリクエストの度にプロデューサに送信することで実行されます。元のリクエストでは、このセッションが確立され、以降のリクエストでは、ポートレットがセッションCookieをプロデューサに送信し、セッションが再利用されます。

    ディープ・リンク、つまりポートレットからプロデューサ・アプリケーションへのリンクについては、リクエストはブラウザからプロデューサ・アプリケーションに直接送られます。この場合、セッションCookieは送信できないため新しいセッションが確立されます。ディープ・リンクに共有セッションが必要な場合、これは開発者が実装する必要があります。共通実装とは、この状態を、プロデューサおよびアプリケーションからアクセスできる共通の場所に書き込み、この状態に対する参照をディープ・リンクで渡すことです。

  • Java EE認証。Java EEログインはサポートされていません。Java EEアプリケーションは、BasicやDigestなどの様々な認証テクニックを使用して構成できます。ポートレットはコンシューマのページに組み込まれたフラグメントであるため、Direct認証はクライアントとポートレット・プロデューサとの間ではなく、クライアントとコンシューマとの間で発生することが一般に予想されます。結果として、これらの認証テクニックはJSR 286ではサポートされていません。JSR 286の場合、Java EE認証がWS-Securityメカニズムを通じて発生し、これによってWebサービス・コンシューマはプロデューサに認証および検証され、ユーザー認証および認可に向けてユーザー・アイデンティティが伝播できます。公開されるOracle ADFアーティファクトには、Java EE認証をトリガーするログイン・リンクを含めることができません。

  • タイムアウト期間。レンダリングに時間のかかるアプリケーションについては、Oracle JSF Portlet Bridgeで作成されたプロデューサを登録するときに、タイムアウト期間を増やすことを検討してください。ただし、プロデューサ登録中に指定されたタイムアウト期間がadf-config-xmlで指定された最大タイムアウト期間(maximumTimeout要素)で制限されていることに注意してください。

12.2.3.2 ポートレットのガイドライン

JSFポートレットを作成する際には、次のポートレットのガイドラインを考慮してください。

  • ポートレットのサイズ変更。JSFポートレットを使用している場合、コンシューマ・アプリケーションはインライン・フレーム内でポートレット・コンテンツを自動的にレンダリングします。これは、いずれのインライン・ポップアップもインライン・フレーム内に限定されることを意味します。これは、ポートレットのサイズを指定する際に考慮する必要があります。

    JSFポートレットがポートレット化されたページである場合、コンテンツの完全なコントロールが可能で、コンテンツ・ファイルがインライン・フレーム・ウィンドウを埋める方法を決定でき、コンテンツがブラウザのウィンドウを埋める方法を決定するときとまったく同じテクニックを活用できます。

    ポートレットがコンシューマ・アプリケーション内のその先祖までストレッチされている場合、Oracle JSF Portlet Bridgeによって生成されたドキュメントのaf:documentコンポーネントのmaximized属性がtrueに設定されます。つまり、これをサポートするpanelStretchLayoutなどのコンポーネントはインライン・フレーム全体を埋めます。

  • リソースとリンク。リソースおよびリンクについては、web-app-context-rootを基準として場所を指定する必要があります。そうしないと、ポートレットがイメージやその他のリソースを見つけられません。相対パスの表記(../)を使用しないでください。Oracle WebCenter Portalのポートレットは、リモートで実行され、SOAPプロトコル(WSRP)を使用してアクセスされます。後者は、通常のWebアプリケーションのリクエスト・パスの概念が、JSR 286コンテナでは意味がないということです。JSR 286仕様では、すべてのリソースURLが絶対パスまたはコンテキスト相対パスのいずれかであることが規定されていることにこれが反映されています。

  • リクエストのリダイレクト。リクエストをJSP内でリダイレクトまたは転送しないでください。JSR 286では、requestDispatcher.include()のみがサポートされます。httpServletResponse.sendRedirect()またはrequestDispatcher.forward()を使用すると、例外やエラーが発生します。ポートレット環境で正常に機能するには、faces-config.xmlまたはOracle ADFタスク・フローの制御フロー・ルールにJSFナビゲーション・ルールを実装する必要があります。

  • メモリー使用量。Oracle JSF Portlet Bridgeは、リクエスト間のリクエスト・スコープのコンテンツを保存し、リクエスト・スコープがActionポートレットとRenderポートレット(これらは2つの別個のリクエスト)との間で予約されるようにします。このため、メモリー使用量全体を最小限に抑えるには、アプリケーションがJSFポートレットを含む場合にリクエスト・スコープ内にあまりデータを保存しすぎないようにする必要があります。

  • WSRPバージョン。Oracle JSF Portlet Bridgeは、Portlet 2.0機能を利用します。そのため、これはWSRP V2以外では使用しないようにしてください。ポートレットのminimumWsrpVersionコンテナ・ラインタイム・オプションは2に設定する必要があります。詳細は、「JSR 286ポートレット用のランタイム環境のカスタマイズ方法」を参照してください。

12.2.3.3 セキュリティのガイドライン

JSFポートレットを作成する際には、次のセキュリティのガイドラインを考慮してください。

  • Oracle ADF保護されたアプリケーション「ポートレット・エントリの作成」ダイアログまたは「タスク・フローのポートレット・エントリの管理」ダイアログを使用して、Oracle ADF保護されたアプリケーション(セキュリティ・スキームが認証および認可)内のタスク・フローをポートレット化する場合は、プロデューサ・アプリケーションのjazn-data.xmlファイルで、次のラッパー・タスク・フローに手動で権限を付与する必要があります。

    /WEB-INF/adfp-portlet-bridge-container.xml#adfp-portlet-bridge-container
    

    権限を付与しないと、ポートレットはレンダリングしません。

    たとえば、表示権限のあるauthenticated-roleと、カスタマイズ、編集、付与、パーソナライズ、表示権限のあるtestroleの2つのロールをアプリケーションが持つ場合、各ロールの<permissions>タグ内に次のエントリを追加する必要があります。

    • authenticated-roleの場合:

      <permission>
       <class>oracle.adf.controller.security.TaskFlowPermission</class>
       <name>
       /WEB-INF/adfp-portlet-bridge-container.xml#adfp-portlet-bridge-container
       </name>
       <actions>view</actions>
      </permission>
      
    • testroleの場合:

      <permission>
       <class>oracle.adf.controller.security.TaskFlowPermission</class>
       <name>
       /WEB-INF/adfp-portlet-bridge-container.xml#adfp-portlet-bridge-container
       </name>
       <actions>customize,edit,grant,personalize,view</actions>
      </permission>
      
  • ロール・ベースの認証。ロール・ベースの認証を持つタスク・フローまたはページをポートレット化する(つまりタスク・フローまたはページに特定のロールが付与される)場合、ユーザーに正しく伝播するためにWS-Securityが必要です。WS-Securityを設定する場合、伝播されたユーザーがタスク・フローを表示する権限を持たないと、JSFポートレットはコンテンツをレンダリングしません。

12.2.3.4 JSFのガイドライン

JSFポートレットを作成する際には、次のJSFのガイドラインを考慮してください。

  • h:commandLinkの使用。h:commandLink JSF標準HTMLコンポーネントを使用する場合は、必ずweb.xmlexternalizeJavaScriptパラメータを設定し、JSF参照実装により外部JavaScriptリソースが生成されないようにします(次の例を参照)。これは、JavaScriptリソースへの参照が適切にエンコードされないというJSFリファレンス実装での問題を回避することが目的です。

    <context-param>
     <param-name>com.sun.faces.externalizeJavaScript</param-name>
     <param-value>false</param-value>
    </context-param>

12.2.3.5 Oracle ADFのガイドライン

JSFポートレットを作成する際には、次のADFのガイドラインを考慮してください。

  • タスク・フロー・リターン。ADFバインド・タスク・フローが完了すると、これはタスク・フロー・リターンを使用してコール元のタスク・フローに制御を戻すことができます。ポートレット化されたタスク・フローには、コール元のタスク・フローはないため、この状況ではタスク・フロー・リターンは意味がありません。これによって、タスク・フローはビューが選択されていない状況に移動するために、空のポートレットのようなものが表示される場合があります。タスク・フローは、入力パラメータの変更時に、またはプロデューサのセッションのリセット時にリフレッシュされるまで、この状態のままとなります。

    タスク・フローのポートレット化を計画している場合は、タスク・フロー・リターンの使用を避ける必要があります。タスク・フロー・リターンを使用する必要がある場合、ポートレット化するタスク・フローのデフォルトのアクティビティを持つダミーのタスク・フローを提供する必要があります。タスク・フロー・リターンが実行されると、これはダミーのタスク・フローに戻ります。ダミー・タスク・フローは、そのデフォルトのアクティビティを実行します。これは元のタスク・フローにコール・バックすることであり、したがってそのタスク・フローはポートレットが次にコールされるときに再起動されます。

  • 不一致のスタイル・シート。一般に、Oracle JSF Portlet Bridgeを使用してタスク・フローを使用すると、ポートレット・プロデューサがコンシューマ・ページのスキンを使用しようとします。プロデューサがコンシューマ・スキンと一致できない場合、ポートレットはその独自のスタイル・シートを生成して参照します。これは不一致と呼ばれます。スキンの不一致は次のような場合に発生することがあります。

    • コンシューマとプロデューサが異なるバージョンのADF Facesを使用している。この場合、プロデューサはまだコンシューマ・スキンを使用します。

    • コンシューマがプロデューサが持たない追加のskin-additionsを持つ(またはその逆)。この場合、プロデューサはまだコンシューマ・スキンを使用します。

    • プロデューサがコンシューマ・スキンを持たない。この場合、プロデューサはポートレット・スキンを使用します。

    スキンの不一致によって、パフォーマンスの問題が生じる可能性があります。これは、ブラウザが余分なスタイル・シートをフェッチしなければならず、生成されたポートレット・マークアップが圧縮されていないスタイルを使用することで、マークアップがより大きくなってしまうためです。

    スキンの不一致が発生すると、プロデューサ・ログには次が含まれます。

    The skin skinName specified on the requestMap will not be used because the
    styleSheetDocument id on the requestMap does not match the local skin's
    styleSheetDocument's id. It could mean the jars are not identical. For example,
    one might have trinidad-skins.xml skin-additions in a jar file on the class path
    that the other does not have.
    

    インライン・フレーム内のポートレット・マークアップには、たとえば次のようなポートレット・スタイル・シート・リソースへのリンク・タグも含まれます。

    <link rel=\"stylesheet\" charset=\"UTF-8\" type=\"text/css\" href=\"http:.../resourceproxy/portletId...252525252Fadf%252525252Fstyles%252525252Fcache%252525252Fblafplus-rich-portlet-d1062g-en-ltr-gecko.css...
    

    HTTP監視ツールを使用すると、リクエストがポートレット・スタイル・シート・リソースに対して実行されることを確認できます。

    スキンの不一致の理由は様々です。スキンが一致するには、プロデューサとコンシューマが次のすべての状態が同じである必要があります。

    • ADF Facesバージョン: ADF Facesのバージョンが異なると、そのスタイル・セレクタが異なる可能性があります。

    • web.xmlに定義された、たとえば次のようなスタイル圧縮:

      <context-param>
       <param-name>
       org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION
       </param-name>
       <param-value>false</param-name>
      </context=param>
      
    • web.xmlに定義された、たとえば次のようなTonalスタイル圧縮:

      <context-param>
       <param-name>xyz</param-name>
       <param-value>xyz</param-value>
      </context-param>
      
    • スキン追加の可用性。スキン追加はJARファイルのMETA-INF/trinidad-skins.xmlで定義されます。これらはクラス・パスのすべてのJARファイルから集約されます。JARファイルがプロデューサには存在してもコンシューマには存在しない、またはその逆の場合、不一致が生じます。

      <skin-addition>
       <skin-id>blafplus-rich.desktop</skin-id>
       <style-sheet-name>
       adf/styles/flexComponents-blafplus-rich-desktop.css
       </style-sheet-name>
      </skin-addition>
      

      JARファイルが一致するかどうかを決定するには、どのskin-additionを処理しているかを示すTrinidadロギングをオンにします。これを行うには、次のようにプロデューサとコンシューマの両方のWebLogic Serverのlogging.xmlログ・レベルをFINESTに更新し、サーバーを再起動します。

      <logger name="org.apache.myfaces.trinidad.skin.SkinUtils" level=FINEST"/>
      

      コンシューマ・ページを実行すると、コンシューマとプロデューサのログ・ファイルと一致しないスキン・エントリはスキン不一致の原因となります。

  • ADF Facesダイアログ・フレームワークADF Facesダイアログ・フレームワークはサポートされていません。アプリケーションがセカンダリ・ブラウザ・ウィンドウを起動するボタンまたはアイコンを含む場合、アプリケーションがポートレットとして実行される場合に新しいウィンドウの内容は正しく表示されません。そのため、アプリケーションのポートレット化を計画している場合は、これらのコンポーネントの使用は避ける必要があります。セカンダリ・ウィンドウを起動するコンポーネントの例は次のとおりです。

    • <tr:inputDate>

    • <tr:inputColor>

    • <tr:popup>

    • <af:commandButton>useWindow属性

  • コンポーザ・コンポーネント。コンポーザ・コンポーネントを含むページのポートレット化はサポートされていません。

  • fileDownloadActionListenerコンポーネント。<af.fileDownloadActionListener>コンポーネントはサポートされていません。

  • prepareModelフェーズ。prepareModelを処理するOracle ADFコンポーネント/コードは複数回コールしても結果が同じでなければなりません。prepareModelフェーズ中に実行されるコードは、基礎となるデータ/ビジネス・ロジックに影響することなく再実行可能でなければなりません。ポートレット環境で実行する場合、prepareModelは、一度コールされる通常のWebアプリケーション内での実行時とは異なり、完全なJSFライフ・サイクル中には二度コールされます。

    この違いの理由は、Oracle JSF Portlet BridgeがJSFを1つのリクエストではなく2つのリクエストで実行することにあります。これは、すべてのJSFリクエストがレンダリング・フェーズ前にリダイレクトされるかのように実装されます。このアプローチでは、リクエストが最初に送信されるとき、およびレンダリングへのリクエストの受信時に再び送信されるときの両方で両方でJSF restoreViewフェーズがコールされることになります。

  • リクエスト・パラメータへのアクセス。ページ・パラメータ内を除き、モデル・コードからリクエスト・パラメータをアクセスまたは参照しないでください。よりきれいなMVC2実装であることに加えて、このガイドラインに従うことで、そのようなアーティファクトがポートレットとして公開された場合に問題を回避します。通常のJSFアーティファクトが1つのリクエストで全ライフサイクルを実行するのに対して、Oracle JSF Portlet Bridgeは、すべてのJSFリクエストがレンダリング・フェーズの前にリダイレクトされるかのように、これらのアーティファクトを2つのリクエストで実行します。

    この2フェーズ・モデルでは、レンダリング前に送信済パラメータのクリーニングを、そのクリーニングをクライアントまで遡って通知可能な方法でできるようにします。これによって、このリクエストのブックマークが可能になります。結果として、リクエスト・パラメータはレンダリング・フェーズ中には存在しません。前述のとおり、prepareModelはこのレンダリング・フェーズで再度呼び出されます。そのため、このフェーズ・ハンドラでのリクエスト・パラメータへの参照はいずれも失敗します。次のようなフラグメントのコードはいずれも避ける必要があります。

    <invokeAction id="doExecuteWithParams" 
    Binds="ExecuteWithParams" 
    Refresh="prepareModel" 
    RefreshCondition="${param.id != null}"
    />
    
    <invokeAction id="doExecuteWithParams" 
    Binds="ExecuteWithParams" 
    Refresh="renderModel" 
    RefreshCondition="${param.id != null}"
    />
    
  • ページ・パラメータの参照。prepareModelフェーズで、ページ・パラメータを参照しないでください。この問題は、前述のガイドラインでリクエスト・パラメータについて説明されている同じ問題に関連します。一般に、ページ・パラメータはリクエスト・パラメータによって決まり、restoreViewフェーズ中に評価されます。このフェーズが、ポートレットのレンダリング中にもう一度コールされ、リクエスト・パラメータがないと、失敗に終わります。かわりに、JSFの実行フェーズからレンダリング・フェーズへの遷移の前に、ページ・パラメータ値に対する依存性をモデルに移動します。

  • コンポーネントを見つけるためのADF Facesクライアント側APIの使用。ポートレットはネーミング・コンテナであるため、ADF Facesクライアント側のAPIを使用してコンポーネントを見つける場合には特別な配慮が必要とされます。コンポーネントIDの例:

    • 通常のWebアプリケーションとして実行する場合: id="demoTemplate:popup"

    • ポートレット・プロデューサ・アプリケーションとして実行する場合: id="__ns12345678:demoTemplate:popup"

    特別に配慮すること:

    • AdfPage.PAGE.findComponentByAbsoluteId() APIを使用しないようにします。かわりにgetSource()メソッドとfindComponent()メソッドを使用してください。次に例を示します。

      <trh:script text="
      function showPopup(event) {
      event.cancel();
       //var popup =
      //AdfPage.PAGE.findComponentByAbsoluteId("demoTemplate:popup");
       var source =event.getSource();
       var popup =source.findComponent("popup");
       popup.show({align:"after_end", alignId:"button"});
      }
      "/>
      
    • clientIdには絶対パス(「:」で始まる)ではなく相対パスを使用します。たとえば、次のように使用します。

      <af:showPopupBehavior popupId="demoTemplate:iteratorpop"
       triggerType="mouseHover"/>
      

      次は使用しません。

      <af:showPopupBehavior popupId=":demoTemplate:iteratorpop"
       triggerType="mouseHover"/>
      
    • 詳細は、『Oracle ADF FacesによるWebユーザー・インタフェースの開発』のネーミング・コンテナの使用に関する必知事項に関する項を参照してください。

  • URLのエンコーディング。デフォルトでは、ポートレット化されたページまたはタスク・フローのURLはコンシューマ・アプリケーションによってプロキシされるようにエンコードされます。状況次第では、これらのURLをエンコードしたくない場合もあります。たとえば、コンテンツ配信ネットワークからJavaScriptライブラリをリクエストする場合や、ユーザーのブラウザから直接リソースにアクセスしてローカルに構成されたHTTPプロキシを利用する場合などです。

    他にも、タスク・フローがインライン・フレーム(たとえばaf:inlineFrameタグを使用)を含む場合などがあります。このような場合は、インライン・フレームURLがコンシューマのポートレット・リソース・プロキシを介して進むためにエンコードされないようにする必要があります。そうしないと、インライン・フレーム内のコンテンツの相対URLは有効となりません。これらのURLがインライン・フレームの元のURLと相対的な正しい場所ではなくリソース・プロキシへのURLと相対的となるためです。

    URLエンコーディングをバイパスするには、エンコーディングに向けてOracle JSF Portlet Bridgeに渡されるURLの_xEncodeUrlパラメータをfalseに設定してください。このパラメータはOracle JSF Portlet Bridgeによって収集され、URLがリソース・プロキシを介してエンコードされることはありません。パラメータは、タスク・フローがポートレットとして実行していない場合は無視されます。

    たとえば、次を置換します。

    <af:inlineFrame source="http://myiframe.example.com">
    

    置換後:

    <af:inlineFrame source="http://myiframe.example.com?_xEncodeUrl=false">

    注意:

    このパラメータは、プロデューサ・サーバーにあるリソースへのアクセスには使用しないでください。これらのリソースにはポートレット・クライアントのプロキシを使用してアクセスする必要があります。

  • goLinkの問題。adf:goLinkコンポーネントは、リンクURLを現在のJSFアプリケーションのアクションとしてエンコードします。つまり、これはExternalContext.encodeActionURL(...)を使用してリンクをエンコードします。これは、ExternalContext.encodeResourceURL(...)を使用してリソースとしてURLをエンコードするJSF h:outputLinkコンポーネントとは異なります。goLinkを使用してFaces Viewではないリソースにリンクする場合、URLはリソースURLとしてエンコードする必要があります。これを行うには、次のパラメータをURLに追加することで、Oracle JSF Portlet Bridgeに対してリンクがFaces Viewではないことを伝える必要があります。

    javax.portlet.faces.ViewLink=false
    

    例:

    <af:goLink text="goLink 1" id="gl1" destination="/mynonfaceslink?javax.portlet.faces.ViewLink=false"/>
    
  • プロトコル内リソース・リクエスト。Oracle JSF Portlet Bridgeの下で実行しているJSFアプリケーション内では、リソースURLがExternalContext.encodeResourceURL(...)を使用して作成される場合、そのリソースURLはプロトコル外のリソース・リクエストとして実行されるようにエンコードされます。つまり、ポートレット・コンシューマがそのリソースにアクセスする場合、これはターゲットURLに直接コールすることでそれを実行します。リソースURLがプロトコル内となることも可能です。つまり、ポートレット・コンシューマはプロデューサ・アプリケーションに対してWSRP Webサービス・コールを行うことでリソースにアクセスし、これが最終的にポートレットでコールされるserverResourceメソッドになります。その後、WSRPレスポンスで戻されるリソースの提供はポートレットが実行します。そのポートレットがOracle JSF Portlet Bridgeであれば、これはリクエスト・ディスパッチャを使用してリソースを提供し、ターゲットURLに転送します。

    一般的にプロトコル外のリソース・リクエストは、Webサービス・コールの余分なオーバーヘッドを招かないため好まれます。また、プロトコル内リクエストでは、処理されるリソースが大きな場合に、WSRP SOAPレスポンスが構成されるため、大量のメモリー割当てが生じる可能性もあります。Oracle JSF Portlet Bridgeの場合、プロトコル内リソースを使用するのは、リソース・リクエストとその他のポートレット・リクエスト(ポートレット・アクションやレンダリング・リクエストなど)との間のポートレット・スコープのHTTPセッションを共有する必要があるときだけです。

    プロトコル内リソース・リクエストとしてOracle JSF Portlet BridgeにリソースURLをエンコードさせるには、ExternalContext.encodeResourceURL(...)をコールする前に、次のパラメータをURLに追加します。

    javax.portlet.faces.InProtocolResourceLink=true
    

    例:

    <af:goLink text="goLink 1" id="gl1" destination="/mynonfaceslink?javax.portlet.faces.ViewLink=false&javax.portlet.faces.InProtocolResourceLink=true"/>

12.3 ポートレット化されたページまたはタスク・フローのポートレット・エントリの更新

編集するページまたはタスク・フローが以前にポートレット化されており、それらにタスク・フローまたはページのパラメータまたはイベントに対する更新が含まれている場合、そのページまたはタスク・フローのポートレット・エントリを更新して、ポートレットとその基になるページまたはタスク・フローの同期を取る必要があります。

注意:

ポートレット化されたページを削除する場合、そのページのポートレット・エントリを手動でportlet.xmlファイルから削除する必要があります。

ポートレット化されたページまたはタスク・フローのポートレット・エントリを更新するには:

  1. アプリケーション・ナビゲータで、更新するポートレット化されたページまたはタスク・フローを含むJSFアプリケーションを開きます。

  2. ページまたはタスク・フローを右クリックし、「ポートレット・エントリの更新」を選択します。

  3. ポートレット・エントリがバインドなしタスク・フロー用である場合、ダイアログでそのポートレットの作成に使用したビュー・アクティビティを選択するよう求められます。

ポートレット化されたページまたはタスク・フローのポートレット・エントリを更新すると、ポートレット・エントリは次のように更新されます。

  • 「コンテキスト・イベント用ポートレット・イベントの作成」オプションがtrueに設定されます。

  • ポートレット名、表示名、タイトル、短いタイトルまたは説明は更新されません。

  • 必要に応じて、event-definition要素が(ポートレット・アプリケーション・レベルで)作成されます。

  • 既存のevent-definition要素は削除または更新されません。

  • 必要に応じて、public-render-parameter要素が(ポートレット・アプリケーション・レベルで)作成されます。

  • 既存のpublic-render-parameter要素は削除または更新されません。

  • ポートレット・エントリ内のsupported-processing-eventsupported-publishing-eventおよびsupported-public-render-parameter要素は、ページまたはタスク・フローの現在のイベントと入力パラメータを反映するために再作成されます。つまり、いくつかの既存のポートレット・イベントとパブリック・パラメータが削除され、新しく追加される場合があります。

12.4 JDeveloperでのポートレット化されたページまたはタスク・フローのテスト

ページまたはタスク・フローをポートレット化したら、テストを行って、それが正しく動作することを確認する必要があります。ポートレット化されたページまたはタスク・フローのテストでは、次の手順を実行する必要があります。

  1. ページまたはタスク・フローをポートレット化して、portlet.xmlファイル内にポートレット・エントリを作成します。
  2. ポートレット化されたアプリケーションをポートレット・サーバーにデプロイします。
  3. ポートレット化されたページまたはタスク・フローを使用するためのアプリケーションを作成します。
  4. ポートレット化されたアプリケーションをコンシューマ・アプリケーションに登録します。
  5. コンシューマ・アプリケーション内にページを作成し、そこにポートレット化されたページまたはタスク・フローを追加します。
  6. コンシューマ・アプリケーションをデプロイし、ポートレット化されたページまたはタスク・フローを含むページを表示します。

12.5 統合WebLogic Serverを使用してのJSFポートレットのテスト

JSFポートレットを作成したら、JDeveloperとともにパッケージ化されている統合WebLogic Serverを使用してテストできます。

始める前に

ポートレット化されているページまたはタスク・フローをテストする前に、実行中のADFアプリケーションでそのページまたはタスク・フローが正しく動作することをまずはテストすることをお薦めします。これは、統合WebLogic Serverを使用してページを実行することで、またはタスク・フローについてはタスク・フローをページに追加してページを実行することで行えます。

詳細は、『Oracle Application Development FrameworkによるFusion Webアプリケーションの開発』の統合WebLogic ServerでのADFアプリケーションの実行に関する項を参照してください。

JSFポートレットをテストするには:

  1. メイン・メニューから「実行」を選択し、「サーバー・インスタンスの起動」を選択します。

    統合WLSの起動には数分かかる場合があります。インスタンスが起動すると、「ログ」パネルに次のようなメッセージが表示されます。

    IntegratedWebLogicServer started.
    

    詳細は、「統合WebLogic Serverの管理」を参照してください。

  2. これでポートレット・プロデューサ・アプリケーションを統合WLS上で実行する準備ができました。Webアプリケーションとポートレット・プロデューサ・アプリケーションは、1つで同じもの(ポートレット・プロデューサ・アプリケーションは、ポートレット・アーティファクトが追加されている既存のWebアプリケーション)であるため、通常どおりWebアプリケーションを実行することも(『Oracle Application Development FrameworkによるFusion Webアプリケーションの開発』の統合WebLogic ServerでのADFアプリケーションの実行に関する項を参照)、「統合WebLogic ServerでのWSRPポートレット・プロデューサの実行方法」の手順に従ってポートレットを実行することもできます。
  3. アプリケーションがデプロイされると、次に進むことでWSRPプロデューサ・テスト・ページを表示できます。
    http://host:port/context-root/info
    

    説明:

    • hostは、アプリケーションがデプロイされているサーバーの名前です。

    • portはHTTPリスナー・ポートです。通常、これは7101です。サーバーが起動すると、ポートがコンソールに表示されます。

    • context-rootは、Webアプリケーションのコンテキスト・ルートです。

  4. ポートレットを含むアプリケーションのデプロイに成功すると、それを他の任意のアプリケーションにポートレット・プロデューサとして登録できます。

    注意:

    Oracle JSF Portlet BridgeがWSRP 2.0機能を使用している場合、WSRPプロデューサ・テスト・ページに一覧されているWSRP v2 WSDL URLを使用してプロデューサを登録する必要があります。

    アプリケーションは、通常のWebアプリケーションとして引き続きアクセスすることも、ポートレット・プロデューサとして使用することもできます。

  5. ポートレット・プロデューサをデプロイし、登録すると、自分のJSFアプリケーションのポートレットを他のポートレットと同じように使用できます。

12.6 WebLogic Managed ServerへのJSFポートレットのデプロイ

アプリケーションの動作がWebアプリケーションとポートレット・アプリケーションの両方として正しく動作していることが確認できたら、これを本番のOracle WebLogic管理対象サーバーにデプロイできます。

Webアプリケーションとポートレット・アプリケーションは、1つで同じものであるため(ポートレット・アプリケーションはポートレット・アーティファクトが追加されている既存のWebアプリケーション)、Webアプリケーションをデプロイすると、ポートレット・プロデューサ・アプリケーションもデプロイされます。

WebLogic管理対象サーバーへのアプリケーションのデプロイ方法の詳細は、『Oracle Application Development FrameworkによるFusion Webアプリケーションの開発』の「Fusion Webアプリケーションのデプロイ」を参照してください。

注意:

Oracle PortletコンテナがインストールされているJava EEコンテナにアプリケーションをデプロイするようにしてください。統合WLSにはコンテナがインストールされています。そのためテストには統合WLSをお薦めします。

デプロイメントに成功した後、アプリケーションとポートレット・プロデューサ・テスト・ページの両方にアクセスできます。たとえば、アプリケーションのURLは次のようになります。

http://host:port/appcontextroot/faces/pagename.jspx

また、ポートレット・プロデューサ・テストURLは次のようになります。

http://host:port/appcontextroot/info

12.7 イベントを使用したその他のポートレットとのJSFポートレットのリンク

この項には次のトピックが含まれます:

12.7.1 その他のポートレットとのJSFポートレットのリンクについて

コンテキスト・イベントをトリガーするOracle ADFタスク・フローをポートレット化する場合、Oracle JSF Portlet BridgeはJSR 286ポートレット・イベントを作成してコンテキスト・イベントをラップします。このため、ポートレット化されたタスク・フローがページ上で使用される場合、このタスク・フローは他のJSFポートレットまたはJSR 286ポートレットにリンクできることになります。

この項の例では、次のポートレットを使用します。

  • 部門ポートレット: 部門リストを表示するポートレット化されたADFタスク・フロー。部門リストは場所IDで制限できます。このポートレットは、部門行がポートレットで選択されている場合に、コンテキスト・イベントdepartmentSelectedを呼び出します。departmentSelectedイベントは、hr.Department (Departments表の1行を表すJavaオブジェクト)タイプのオブジェクトです。

  • 従業員ポートレット: 従業員リストを表示するポートレット化されたADFタスク・フロー。従業員リストは部門IDで制限できます。

  • 部門アドレス・ポートレット: 特定部門のアドレスを表示するJSR286ポートレット。

  • 部門場所ポートレット: 場所のリストを表示するJSR286ポートレット。このポートレットは、リストされている場所の1つが選択されるときに、ネームスペースhttp://xmlns.oracle.com/adfm/contextualeventとともにlocationIdというポートレット・イベントを呼び出します。

12.7.2 別のJSFポートレットへのJSFポートレットのリンク方法

部門タスク・フローは、タスク・フロー内で部門行が選択されている場合に、コンテキスト・イベントdepartmentSelectedを呼び出します。このイベントは最終的に、行選択リスナーからトリガーされるeventBindingによって発生します(次の例を参照)。

イベントのペイロード(hr.Departmentタイプのオブジェクトで、部門表の1行を表すJavaオブジェクト)は、現在の行をdepartments表イテレータからポイントするcustomPayload属性を使用して生成されます。

この例で使用されている手法のような標準的なADFコンテキスト・イベント手法の詳細は、『Oracle Application Development FrameworkによるFusion Webアプリケーションの開発』のコンテキスト・イベントの作成に関する項を参照してください。

<eventBinding Listener="org.apache.myfaces.trinidad.event.SelectionListener"
 id="DepartmentSelectedEvent">
 <events xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
 <event name="departmentSelected"
 customPayLoad="#{bindings.departments.currentRow.dataProvider}"/>
 </events>
</eventBinding>

「タスク・フローに基づいたJSFポートレットの作成方法」で説明されている手順を使用して部門タスク・フローをポートレット化すると、WSRPを介したポートレットとのポートレット通信中に対応するコンテキスト・イベントを転送するために使用されるポートレット・イベントの定義を含むportlet.xmlファイルが作成されます。

<portlet id="adf_taskflow_WEB_INF_departments_xml">
 ...
 <supported-publishing-event id="departmentSelected">
 <qname xmlns:x="http://xmlns.oracle.com/adfm/contextualEvent">
 x:departmentSelected
 </qname>
 </supported-publishing-event>
 ...
</portlet>

部門ポートレットのdepartmentSelectedイベントについては、portlet.xmlに対応するイベント定義もあります。

<event-definition id="departmentSelected">
 <qname xmlns:x="http://xmlns.oracle.com/adfm/contextualEvent">
 x:departmentSelected
 </qname>
 <value-type>
 oracle.portlet.bridge.adf.lifecycle.ADFmPayloadWrapper
 </value-type>
</event-definition>

注意:

ポートレット・イベントでカバーされているコンテキスト・イベントのネームスペースは常に次のようになります。

http://xmlns.oracle.com/adfm/contextualEvent

ペイロード・タイプは常に次のようになります。

oracle.portlet.bridge.adf.lifecycle.ADFmPayloadWrapper

ADFmPayloadWrapperは、あらゆるシリアライズ可能なコンテキスト・イベント・ペイロードがJAXBマーシャリング化可能なラッパーにラップされるようにするために使用されます。また、これによってイベントが呼び出されるまでペイロードのタイプがわからない場合であっても、固定タイプをポートレット・イベントに宣言することができます。ペイロードは、ポートレット・イベントからコンテキスト・イベントを抽出する際にアンラップされます。

従業員タスク・フローでは、標準的なADF手法を使用してdepartmentSelectedイベントを処理します。これは、データ・コントロールでメソッドを呼び出して、departmentSelectedイベントからそのメソッドへのパラメータとしてイベント・ペイロードを提供する methodActionバインドの形となります。次の例は、methodActionバインディングの定義を示しています。

<methodAction id="updateTableForDepartmentId" RequiresUpdateModel="true"
 Action="invokeMethod" MethodName="updateTableForDepartmentId"
 IsViewObjectMethod="false" DataControl="EmployeesDataControl"
 InstanceName="EmployeesDataControl.dataProvider">
 <NamedData NDName="departmentIdPayLoad" NDType="hr.Department"/>
</methodAction>

updateTableForDepartmentIdメソッドは、departmentSelectedイベントのペイロードとして渡されるhr.Departmentオブジェクトをとり、EmployeesDataControlから問い合されるデータを、選択された部門に所属する従業員のみを示すようにフィルタ処理します。また、イテレータが再実行され、表ビュー・コンポーネントがこのリクエストで再レンダリングされる必要があるとしてマークされるようにする手順も実行されます。

従業員タスク・フローには、タスク・フローがポートレット化されるときに受信イベントを適切なmethodActionに明確にマップするイベント・マップが含まれています。

<eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
 <event name="departmentSelected">
 <producer region="*">
 <consumer region="" handler="updateTableForDepartmentId"
 handleCondition="${ADFPortletBridge.bridgeRequest}">
 <parameters>
 <parameter name="p1" value="#{payLoad}"/>
 </parameters>
 </consumer>
 </producer>
 </event>
</eventMap>

注意:

<producer region="*">属性はあらゆるリージョンからイベントを受け入れます。これは、リモート・アプリケーションからポートレットに着信するイベントとともに、タスク・フローがポートレットとして実行している場合、リモート・アプリケーションにはプロデューサ・リージョンに関する知識がまったくないためです。

現在のリクエストがOracle JSF Portlet Bridgeの下で実行している場合、handleCondition="${ADFPortletBridge.bridgeRequest}"内のEL式はtrueに評価されます。これによって、このイベント・マップはタスク・フローがポートレットとして実行している場合のみ使用されることが保証されます。このhandleConditionはなくてもかまいません。ただし、タスク・フローがポートレットとして実行している場合のみ使用される別のeventMapを定義できると便利な場合もあります。

2つのポートレット化されたタスク・フローがページに追加されると、部門ポートレットによってトリガーされるイベントの名前が従業員ポートレットによって期待されているものと同じであるかぎり、それ以上のコーディングは不要です。ポートレットは自動的にリンクされ、部門ポートレットで部門が選択されると従業員ポートレットが更新され、選択されている部門に属する従業員が表示されます。

図12-1 リンクされたJSFポートレット

図12-1の説明が続きます
「図12-1 リンクされたJSFポートレット」の説明

自動的なイベント・リストを使用しないことを選択することもできます。たとえば、同じイベントを使用する同じページ上に複数のポートレットを持ち、それらの間のイベントのフローを制御する場合などに選択できます。または、リンクするJSFポートレットで使用されているコンテキスト・イベントの名前が一致しない場合にも選択します。この場合、ポートレット化されたタスク・フローを含むページのページ定義にイベント・マップを明示的に作成する必要があります。このイベント・マップは、まとめて連結するポートレットのポートレット・イベントをリンクします。次の例は、従業員タスク・フローがdepartmentSelectedのかわりにdepartmentIdというイベントを想定している場合に、この例でこれがどのような働きをするかを示しています。

<eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
 <event name="departmentSelected">
 <producer region="EventSampleProducerdepartments1_1">
 <consumer handler="EventSampleProduceremployees1_1.
 {http://xmlns.oracle.com/adfm/contextualEvent}departmentId"/>
 </producer>
 </event>
</eventMap>

注意:

ポートレット化されたタスク・フローの場合、handler属性はイベントを処理する特定のバインド・オブジェクトだけではなく、<portletBindingId>.<eventQName>形式を使用してポートレット・イベントの完全なQNameも指定する必要もあります。ネームスペースはADFmネームスペースでなくてもかまいません。ペイロードに互換性があればどのポートレット・イベントでも可能です。

12.7.3 JSR 286ポートレットへのJSFポートレットのリンク方法

他のJSFポートレットをJSFポートレットにリンクするのと同様に、JSFポートレットは通常のJSR 286ポートレットにリンクすることもできます。これを実行するには、JSR 286ポートレットがコンテキスト・イベントを受け入れることができると明示的に宣言していることを確認する必要があります。

たとえば、前述の例から部門タスク・フローを部門アドレス・ポートレットJSR 286ポートレットにリンクして、選択されている部門のアドレスを表示できます。

自動的なイベントの関連付けが有効となるために、部門アドレス・ポートレットは、部門ポートレットからコンテキスト・イベントを受け入れ可能であることを宣言する必要があります。これは、次の2つの方法で実行できます。

  • 部門アドレス・ポートレットでは、直接departmentSelectedコンテキスト・イベントがサポートされます。

    <supported-processing-event id="departmentSelected">
     <qname xmlns:x="http://xmlns.oracle.com/adfm/contextualEvent">
     x:departmentSelected
     </qname>
    </supported-processing-event>
    
  • 部門アドレス・ポートレットのイベントdepartmentのイベント定義では、これをdepartmentSelectedコンテキスト・イベントと関連付けるための別名が提供されます。

    <event-definition id="department">
     <qname xmlns:x="http://xmlns.oracle.com/portlet/EventSample">
     x:department
     </qname>
     <alias xmlns:x="http://xmlns.oracle.com/adfm/contextualEvent">
     x:departmentSelected
     </alias>
     <value-type>hr.Department</value-type>
    </event-definition>

注意:

コンテキスト・イベントを実行するために使用されるポートレット・イベントのネームスペースは、常に次のようになります。

http://xmlns.oracle.com/adfm/contextualEvent

ネームスペースは、前述のイベント宣言または別名で使用されます。このネームスペースは、コンシューマに対して、ポートレットがポートレット・イベントとして指定された名前でコンテキスト・イベントを受け入れる必要があることを示します。これは自動的なイベントの関連付けが有効となるために不可欠です。

部門アドレス・ポートレットでは、イベントを処理するコードがprocessEvent実装に含まれています。このメソッドでは、前述の定義どおり別名とともにdepartmentSelecteddepartmentイベントのいずれかを検索します。これらのイベントの両方に対するペイロード・タイプはhr.Departmentです。ただし、次の例に示すメソッドは、ADFmPayloadWrapperを使用してペイロードをアンラップする方法を示しています。ADFmPayloadWrapperは、Oracle JSF Portlet Bridgeがイベント呼出し時にデフォルトで使用するイベント・タイプです。

public void processEvent(EventRequest request, EventResponse response)
 throws PortletException, IOException
 {
response.setRenderParameters(request);
 
Event event =request.getEvent();
 String eventName =event.getName();
 if ("departmentSelected".equals(eventName) ││
"department".equals(eventName))
 {
Object payload =event.getValue();
 if (payload instanceof ADFmPayloadWrapper)
 {
payload =((ADFmPayloadWrapper)payload).getPayload();
 }
if (payload instanceof Department)
 {
Department department =(Department)payload;
 int locationId =department.getLocation();
 response.setRenderParameter("locationId", Integer.toString(locationId));
 }
}
}

これらの2つのポートレットが1ページにまとめて表示される場合、部門ポートレットで部門を選択すると、部門アドレス・ポートレットが自動的に更新され、選択されている部門のアドレスが表示されます。

図12-2 JSR 286ポートレットにリンクされたJSFポートレット

図12-2の説明が続きます
「図12-2 JSR 286ポートレットにリンクされたJSFポートレット」の説明

部門アドレス・ポートレットがdepartmentSelectedイベントを明示的にサポートしていない、または適切な別名を定義していない場合でも、ページ定義内にイベント・マップを作成することで2つのポートレットをリンクできます。

<eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
 <event name="departmentSelected">
 <producer region="EventSampleProducerdepartments1_1">
 <consumer handler="DepartmentAddress1_1.
 {http://xmlns.oracle.com/portlet/EventSample}department"/>
 </producer>
 </event>
</eventMap>

このイベント・マッピングでは、departmentSelectedコンテキスト・イベントがEventSampleProducerdepartments1_1ポートレット・バインドによって呼び出されると、そのイベントがDepartmentAddress1_1ポートレット・バインドに配信され、次にこれがポートレット・イベントdepartmentを使用してポートレットにイベントを送信することになります。

注意:

departmentSelectedコンテキスト・イベントのペイロードは、hr.Departmentsオブジェクトです。これは、ポートレットのdepartmentポートレット・イベントが期待する同じペイロード・タイプであるため、適合し、すべてが正しく動作します。また、ポートレットは、ADFmPayloadWrapperタイプのペイロードを期待していることを宣言することができます。この場合、ポートレット・コンシューマがこれを検出し、ADFmPayloadWrapperオブジェクトにコンテキスト・イベント・ペイロードを自動的にラップします。

12.7.4 JSFポートレットへのJSR 286ポートレットのリンク方法

ポートレット・イベントをJSR 286ポートレットからJSFポートレットに送信することもできます。ポートレット・イベントは、Oracle JSF Portlet Bridgeによってコンテキスト・イベントに変換され、使用されるプロデューサADFアプリケーションに標準的なコンテキスト・イベント手法を使用して配信されます。

部門タスク・フローには、DepartmentsDataControlのメソッドにバインドされるmethodActionバインディングが含まれています。

<methodAction id="updateTableForLocationId" RequiresUpdateModel="true"
 Action="invokeMethod" MethodName="updateTableForLocationId"
 IsViewObjectMethod="false"
 DataControl="DepartmentsDataControl"
 InstanceName="DepartmentsDataControl.dataProvider">
 <NamedData NDName="locationId" NDType="int"/>
</methodAction>

updateTableForLocationIdメソッドは、場所IDをパラメータとして受け入れます。このIDによってデータ・コントロールによって返される部門のリストがその場所IDでフィルタ処理されます。

タスク・フローには、コンテキスト・イベントを適切なmethodActionにマップするイベント・マップが含まれています。

<eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
 <event name="locationId">
 <producer region="*">
 <consumer region="" handler="updateTableForLocationId"
 handleCondition="${ADFPortletBridge.bridgeRequest}">
 <parameters>
 <parameter name="p1" value="#{payLoad}"/>
 </parameters>
 </consumer>
 </producer>
 </event>
</eventMap>

注意:

イベント・マップは、イベントの発信元であるリージョンは参照できません。これはタスク・フローがポートレットとして実行しているときに存在しないためです。そのためイベント・マップではイベント・ソースとしてワイルドカードを使用します。

部門場所ポートレットでは、場所が選択されている場合、選択されている場所の場所IDを指定してprocessActionメソッドによってポートレット・イベントlocationIdが呼び出されます。

public void processAction(ActionRequest request, ActionResponse response)
 throws PortletException
 {
String locationId =request.getParameter("locationId");
 Location location =getLocation(Integer.parseInt(locationId));
 
if (location != null)
 {
//QName matches the event declared as a supported-publishing-event in
 //portlet.xml for this portlet.
 
//LocationId event. Raised in the ContextualEvent namespace makes it readily
 //consumable by ADF Bridge portlets. Likewise we wrap with the
 //ADFmPayloadWrapper payload object that the ADF Bridge expects.
 response.setEvent(new QName("http://xmlns.oracle.com/adfm/contextualEvent",
 "locationId"),
 new ADFmPayloadWrapper(Integer.valueOf(location.getLocationId())));
 }
}

注意:

processActionメソッドで呼び出されたlocationIdイベントには、Integerタイプのペイロードがあります。ただし、JSFポートレットは常にADFmPayloadWrapperでラップされたコンテキスト・ペイロードでポートレット・イベントを予測するため、イベントの自動配信を機能させたい場合には受信ポートレットの要件に適するようにペイロードをラップする必要があります。

同様に、呼び出すイベントのQNameは次のようになります。

{http://xmlns.oracle.com/adfm/contextualEvent}locationId

ポートレットをページ上にドロップし、部門場所ポートレット内で場所を選択すると、選択した場所に部門を表示する部門ポートレットが自動的に更新されます。

図12-3 JSFポートレットにリンクされたJSR 286ポートレット

図12-3の説明が続きます
「図12-3 JSFポートレットにリンクされたJSR 286ポートレット」の説明

2つのポートレットが一致する名前でイベントを宣言していない(たとえば、部門ポートレットからのコンテキスト・イベントがlocIdとコールされる)場合や、自動イベント・リスニングが無効化されている場合であっても、部門ポートレットのコンテキスト・イベントを部門場所ポートレットのポートレット・イベントにマップするイベント・マップをページ定義内に作成することで、2つのポートレットをリンクできます。

<eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
 <event name="locationId">
 <producer region="DepartmentLocations1_1">
 <consumer handler="DepartmentsADFBridgePortlet1_1.
 {http://xmlns.oracle.com/adfm/contextualEvent}locId">
 </consumer>
 </producer>
 </event>
</eventMap>

12.7.5 Oracle JSF Portlet Bridgeのポートレット・イベントに関する必知事項

この項には次のトピックが含まれます:

12.7.5.1 コンテキスト・イベント・ペイロードでのシリアライズされたタイプの使用に関する必知事項

JSR 286イベントのペイロードの一部は、シリアライズされるラップされたコンテキスト・イベント・ペイロードです。そのため、コンテキスト・イベント・ペイロードがいずれのオブジェクト・タイプでも可能である間は、WSRP経由でコンテキスト・イベントを送信するときにはシリアライズされたタイプのみがサポートされます。

このラップされたコンテキスト・イベントが配信されると、コンテキスト・イベント・ペイロードはコンシューマで非シリアライズされなければ、コンシューマ・アプリケーションに転送できません。イベントを非シリアライズするには、ペイロード・クラスがコンシューマとプロデューサで使用可能でなければなりません。この条件は、元のペイロードがjava.lang.StringのようなJava Runtime Environmentクラスであれば自動的に満たされます。

12.7.5.2 宣言されていないイベントの呼出しに関する必知事項

Oracle ADFタスク・フローにADFmイベントが含まれており、portlet.xmlファイルで対応するポートレット・イベントが宣言されていない場合、Oracle JSF Portlet Bridgeでそれらの宣言されていないイベントを呼び出すことができます。

宣言されていないイベントを呼び出すには、ポートレット化されたタスク・フローに対して次のコンテナ・ランタイムを設定してください。

<portlet id="Application5untitled1jspx1_1">
 ...
 <container-runtime-option>
 <name>oracle.portlet.bridge.adf.raiseUndeclaredContextualEvents</name>
 <value>true</value>
 </container-runtime-option>
 ...
</portlet>

このオプションをtrueに設定することで、呼び出されたあらゆるADFmイベントがポートレット・イベントとして転送されることになります。このオプションが提供されていない、またはfalseに設定されている場合、対応するポートレット・イベント宣言を持つイベントのみが転送されます。コンテナ・ランタイム・オプションの詳細は、「個々のポートレットに対するコンテナ・ランタイム・オプションの設定」を参照してください。

また、宣言されていないポートレット・イベントを有効にして、コンシューマ・アプリケーションのポートレット・バインドからADFmイベントとして自動的に転送することもできます。

ポートレット・バインドで、raiseUndeclaredContextualEvent属性をたとえば次のようにtrueに設定します。

<portlet id="Application5untitled1jspx1_1"
 portletInstance="/oracle/adf/portlet/WsrpPortletProducer4/ap/
 Application5untitled1jspx_2943bd23_012e_1000_8004_0aa7c0849010"
 class="oracle.adf.model.portlet.binding.PortletBinding"
 retainPortletHeader="false"
 listenForAutoDeliveredPortletEvents="true"
 listenForAutoDeliveredParameterChanges="true"
 raiseUndeclaredContextualEvents="true"
 xmlns="http://xmlns.oracle.com/portlet/bindings"/>

このオプションをtrueに設定することで、ポートレット・イベントが受信された場合に、ポートレット・イベントにイベント宣言がなくても対応するADFmイベントが呼び出されることになります。ADFmイベントの名前は、ポートレット・イベントのQNameから直接取得されます。Oracle JSF Portlet Bridgeから呼び出されたADFmイベントが、リモート・アプリケーションでイベントが呼び出されたときと同じ名前を持つのはこのためです。

12.7.5.3 部分ページ・レンダリングに関する必知事項

Oracle JSF Portlet Bridgeは、ポートレット・イベントを使用してコンシューマ・アプリケーションとの間でコンテキスト・イベントをトランスポートします。ただし、部分ページ・レンダリング(PPR)リクエストは、Portlet 2.0リソース・リクエストを使用して実装されます。リソース・リクエストのポートレット・イベントを送受信することはできません。そのため、PPRリクエストの場合、JSFポートレットからコンシューマ・アプリケーションにコンテキスト・イベントをトランスポートするには専用のメカニズムが使用されます。