Oracle® Fusion Middleware Oracle WebCenter Portal開発者ガイド 11g リリース1 (11.1.1.7.0) B72084-02 |
|
前 |
次 |
この章では、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を使用してポートレット機能を提供できるようにすることでポートレット開発を簡略化します。
JSR 286ポートレット・コンシューマへのOracle WebCenter PortalなどのJSFアプリケーションの公開を簡略化します。
アプリケーションが通常のWebアプリケーションとして、および同じインストールからのポートレットとして同時に実行できるようにすることで、アプリケーションから別々にポートレットを格納、維持およびデプロイするという要件を排除します。
ポートレットをタスク・フローとして公開することで、より精度の高いレベルでポートレットを作成できます。ポートレット化されたタスク・フローはJSR 286ポートレットであるため、これによってタスク・フローを分散環境で使用することもできます。
注意: Oracle JSF Portlet Bridgeは、JSR 329のApache Reference実装を拡張します。JSR 329は、Portlet 2.0 Bridge for JavaServer Face対応Portlet 2.0 Bridgeの機能を定義するための標準化への取組みです。オラクル社はこの標準化の仕様において指導的地位にあります。詳細は次でご覧いただけます。
|
Oracle JSFポートレット・ブリッジを使用すると、JSFアプリケーションまたはタスク・フローをポートレットとして公開できます。これは、「ポートレット・エントリの作成」ダイアログを使用して宣言的に実行できます。コーディングは不要です。「ポートレット・エントリの作成」ダイアログを使用すると、JSFアプリケーション上にOracle JSF Portlet Bridgeを構成してJSFアプリケーションをJSR 286ポートレットとして公開できます。この構成の一部として、ポートレットがレンダリングされるときに呼び出す最初のJSFビュー(またはタスク・ビュー)を示します。その時点から、Oracle JSF Portlet BridgeはJSFアプリケーションと連動して、この初期ビューから到達できる追加ビューを介して移動します。そのため、JSFアプリケーション全体をポートレットとして公開する通常の状況では、ポートレットでのアプリケーションの初期のビューをレンダリングしてナビゲーションの残りは同じポートレット内で自然に動作するようにOracle JSF Portlet Bridgeを構成する必要があります。
この項には次のサブセクションが含まれます:
JSFアプリケーションからポートレットを作成する最も簡単な方法とは、ページに基づいてポートレットを生成するというものです。
既存のアプリケーション・ページからJSFポートレットを作成するには:
JDeveloperで、ポートレット化するJSPXページを含むアプリケーションを開きます。
アプリケーション・ナビゲータで、JSPXページを右クリックして、「ポートレット・エントリの作成」を選択します。
「ポートレット・エントリの作成」ダイアログで、「ポートレット名」フィールドにポートレットの名前を入力します。
「表示名」フィールドに、ポートレットの記述名を入力します。
「ポートレット・タイトル」フィールドに、ポートレットを説明するタイトルを入力します。
ポートレット・タイトルは、「リソース・パレット」または「アプリケーション・リソース」パネルに表示されるため、ポートレットが便利かどうかどうかをユーザーが決定するのに役立つタイトルにしてください。ポートレットのタイトルは、ポートレットがページに表示されるとポートレットのヘッダーにも表示されます。
「短いタイトル」フィールドに、ポートレットの短いタイトルを入力します。この短いタイトルは、モバイル・デバイスでポートレットがページに表示されるとポートレットのヘッダーに表示されます。
「説明」フィールドに、ポートレットの説明を入力します。
「コンテキスト・イベント用ポートレット・イベントの作成」を選択して、ページによって公開されるコンテキスト・イベントのportlet.xml
ファイル内にポートレット・イベントを作成します。このオプションはデフォルトで選択されます。
ポートレット・イベントによってポートレットは自らが存在するページと、およびそのページ上のその他のポートレットと通信できます。
「OK」をクリックします。
ページに基づいたJSFポートレットを作成すると、portlet.xml
ファイルがページのポートレット・エントリ(例58-1)を含めるように作成(またはこのファイルがすでに存在する場合は更新)されます。ファイルが開き、表示と編集ができます。デフォルトでは、ファイルは設計ビューで開きます。ソース・コードを表示または編集するには、「ソース」タブをクリックします。
<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
注意:
その他のポートレット・モードに |
ポートレット・モードの詳細は、第57.4.1項「ポートレット・モード」を参照してください。
Oracle ADFを使用することの利点とは、タスク・フローの存在です。これはアプリケーションでコントロール・フローを定義するためのモジュール式アプローチを提供します。アプリケーションを1つの大きなJSFページフローとして表すかわりに、再利用可能なタスクフローの集合として分類することができます。各タスク・フローで、アプリケーション・アクティビティ、つまり、アプリケーションが完了するために実行される必要のある作業単位を特定してください。アクティビティとは、タスク・フローの実行時に行うことができる作業を意味しています。
タスク・フローはバインドなしでもバインドありでも可能です。
バインドなしタスク・フローは、ユーザーがタスクを完了できるように相互作用する一連のアクティビティ、制御フロー・ルールおよびマネージドBeanです。バインドなしタスク・フローは、アプリケーションのどのバインド・タスク・フローにも含まれていないすべてのアクティビティと制御フローで構成されます。
バインド・タスク・フローはタスク・フローの特殊な形式であり、単一エントリ・ポイントと1つ以上の終了ポイントがあります。プライベート制御フロー・ルール、アクティビティおよびマネージドBeanの独自のセットが含まれています。Oracle ADFバインド・タスク・フローでは、再利用、パラメータ、トランザクション管理および再開が可能です。また、多くの終了ポイントでゼロとなることも可能です。バインド・タスク・フローは、ページまたはページ・フラグメントを使用できますが、ページ・フラグメントを使用するものだけポートレット化できます。
一般的なアプリケーションは、1つのバインドなしタスク・フローと1つ以上のバインド・タスク・フローを組み合せたものです。このため、アプリケーションでは、バインドなしタスク・フロー内のアクティビティからバインド・タスク・フローをコールできます。バインド・タスク・フローおよびバインドされないタスク・フローの詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』を参照してください。
この項には次のサブセクションが含まれます:
「ポートレット・エントリの作成」ダイアログを使用して単一のタスク・フローからポートレットを作成します。
「ポートレット・エントリの作成」ダイアログを使用してタスク・フローからのポートレットを作成するには:
JDeveloperで、ポートレットを作成するタスク・フローを含むJSFアプリケーションを開きます。
アプリケーション・ナビゲータで、ポートレット化するタスク・フローを右クリックして、「ポートレット・エントリの作成」を選択します。
「ポートレット・エントリの作成」ダイアログで、「ポートレット名」フィールドにポートレットの名前を入力します。
タスク・フローがバインドされていない場合、「エントリ・ポイント・ビュー」ドロップダウン・リストには、タスク・フローのすべてのビュー・アクティビティが表示されます。このドロップダウン・リストから、ポートレットのエントリ・ポイントとして使用するビュー・アクティビティを選択します。デフォルトでは、タスク・フローの最初のビュー・アクティビティが選択されます。
タスク・フローがバインドされている場合、可能なエントリ・ポイントは1つしかないため「エントリ・ポイント・ビュー」ドロップダウン・リストは表示されません。
「表示名」フィールドに、ポートレットの記述名を入力します。
「ポートレット・タイトル」フィールドに、ポートレットを説明するタイトルを入力します。
ポートレット・タイトルは、「リソース・パレット」または「アプリケーション・リソース」パネルに表示されるため、ポートレットが便利かどうかどうかをユーザーが決定するのに役立つタイトルにしてください。ポートレットのタイトルは、ポートレットがページに表示されるとポートレットのヘッダーにも表示されます。
「短いタイトル」フィールドに、ポートレットの短いタイトルを入力します。この短いタイトルは、モバイル・デバイスでポートレットがページに表示されるとポートレットのヘッダーに表示されます。
「説明」フィールドに、ポートレットの説明を入力します。
「コンテキスト・イベント用ポートレット・イベントの作成」を選択して、タスク・フローによって公開されるコンテキスト・イベントのportlet.xml
ファイル内にポートレット・イベントを作成します。このオプションはデフォルトで選択されます。
ポートレット・イベントによってポートレットは自らが存在するページと、およびそのページ上のその他のポートレットと通信できます。
「OK」をクリックします。
プロジェクトがタスク・フローを含んでいる場合は、タスク・フローを選択してリストからポートレットとして作成する方が簡単な場合もあります。これは「タスク・フローのポートレット・エントリの管理」ダイアログを使用して実行できます。また、このダイアログでは、ポートレットを個々に作成するのではなく複数のタスク・フローから一度にポートレットを作成することもできます。
「タスク・フローのポートレット・エントリの管理」ダイアログを使用してたタスク・フローからのポートレットを作成するには:
メイン・メニューから「ファイル」を選択して「新規」を選択します。
「新規ギャラリ」で「Web層」を展開し、「ポートレット」→「タスク・フローのポートレット・エントリの管理」→「OK」の順に選択します。
「タスク・フローのポートレット・エントリの管理」ダイアログで、シャトル・ボタンを使用してポートレットとして作成するタスク・フローを選択します。
「コンテキスト・イベント用ポートレット・イベントの作成」を選択して、タスク・フローによって公開されるコンテキスト・イベントのportlet.xml
ファイル内にポートレット・イベントを作成します。このオプションはデフォルトで選択されます。
ポートレット・イベントによってポートレットは自らが存在するページと、およびそのページ上のその他のポートレットと通信できます。
「OK」をクリックして選択されているタスク・フローのポートレットを作成します。
1つ(または複数)のポートレットが作成されると、次のように示すメッセージを受け取ることになります。
New portlet has been successfully created
また、portlet.xml
ファイルが作成されます。ポートレット・エントリ(例58-2)を含むportlet.xml
ファイルが開き、表示や編集が行えます。
例58-2 タスク・フローに応じて生成されたポートレット・エントリ
<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 &adf.tfId=adfp-portlet-bridge-container&_fragmentTaskFlowDoc=/WEB-INF/ department.xml&_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>
注意:
|
JSFポートレットを作成している場合は、これをJDeveloperに同梱されている統合WebLogic Serverを使用してテストできます。
始める前に
ポートレット化されているページまたはタスク・フローをテストする前に、実行中のADFアプリケーションでそのページまたはタスク・フローが正しく動作することをまずはテストすることをお薦めします。これは、統合WebLogic Serverを使用してページを実行することで、またはタスク・フローについてはタスク・フローをページに追加してページを実行することで行えます。
詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』の統合WebLogic ServerでのADFアプリケーションの実行に関する項を参照してください。
JSFポートレットをテストするには:
メイン・メニューから「実行」を選択し、「サーバー・インスタンスの起動」を選択します。
統合WLSの起動には数分かかる場合があります。インスタンスが起動すると、「ログ」パネルに次のようなメッセージが表示されます。
IntegratedWebLogicServer started.
詳細は、第4.3項「統合WebLogic Serverの使用」を参照してください。
これでポートレット・プロデューサ・アプリケーションを統合WLS上で実行する準備ができました。Webアプリケーションとポートレット・プロデューサ・アプリケーションは、1つで同じもの(ポートレット・プロデューサ・アプリケーションは、ポートレット・アーティファクトが追加されている既存のアプリケーションです)であるため、Webアプリケーションは通常どおり実行することも(『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』の統合WebLogic ServerでのADFアプリケーションの実行に関する項を参照してください)、第59.4.1項「統合WebLogic ServerでWSRPポートレット・プロデューサを実行する方法」の指示に従って実行することもできます。
アプリケーションがデプロイされると、次に進むことでWSRPプロデューサ・テスト・ページを表示できます。
http://host:port/context-root/info
ここで:
host
は、アプリケーションがデプロイされているサーバーの名前です。
port
はHTTPリスナー・ポートです。通常、これは7101です。サーバーが起動すると、ポートがコンソールに表示されます。
context-root
は、Webアプリケーションのコンテキスト・ルートです。
ポートレットを含むアプリケーションのデプロイに成功すると、それを他の任意のアプリケーションにポートレット・プロデューサとして登録できます。詳細は、第62.2.1項「WSRPポートレット・プロデューサの登録方法」を参照してください。
注意: Oracle JSF Portlet BridgeがWSRP 2.0機能を使用している場合、WSRPプロデューサ・テスト・ページに一覧されているWSRP v2 WSDL URLを使用してプロデューサを登録する必要があります。 |
アプリケーションは、通常のWebアプリケーションとして引き続きアクセスすることも、ポートレット・プロデューサとして使用することもできます。
ポートレット・プロデューサをデプロイし、登録すると、自分のJSFアプリケーションのポートレットを他のポートレットと同じように使用できます。詳細は、第62.6項「ページへのポートレットの追加」を参照してください。
アプリケーションの動作がWebアプリケーションとポートレット・アプリケーションの両方として正しく動作していることが確認できたら、これを本番のOracle WebLogic管理対象サーバーにデプロイできます。
Webアプリケーションとポートレット・アプリケーションは、1つで同じものであるため(ポートレット・アプリケーションはポートレット・アーティファクトが追加されている既存のWebアプリケーション)、Webアプリケーションをデプロイすると、ポートレット・プロデューサ・アプリケーションもデプロイされます。
WebLogic管理対象サーバーへのアプリケーションのデプロイ方法の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のFusion Webアプリケーションのデプロイに関する項を参照してください。
注意: Oracle PortletコンテナがインストールされているJava EEコンテナにアプリケーションをデプロイするようにしてください。統合WLSにはコンテナがインストールされています。そのためテストには統合WLSをお薦めします。 |
デプロイメントに成功した後、アプリケーションとポートレット・プロデューサ・テスト・ページの両方にアクセスできます。たとえば、アプリケーションのURLは次のようになります。
http://host:port/appcontextroot/faces/pagename.jspx
また、ポートレット・プロデューサ・テストURLは次のようになります。
http://host:port/appcontextroot/info
コンテキスト・イベントをトリガーする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
というポートレット・イベントを呼び出します。
この項には次のサブセクションが含まれます:
ヒント: 本項の例をすべて含むZIPファイルは次からダウンロードできます。
|
部門タスク・フローは、タスク・フロー内で部門行が選択されている場合に、コンテキスト・イベントdepartmentSelected
を呼び出します。このイベントは、最終的にeventBinding
によって呼び出されます。これは部門タスク・フローで使用される部門ビューのページ定義の行選択リスナーからトリガーされます(例58-3)。
イベントのペイロード(hr.Department
タイプのオブジェクトで、部門表の1行を表すJavaオブジェクト)は、現在の行をdepartments
表イテレータからポイントするcustomPayload
属性を使用して生成されます。
この例で使用されている手法のような標準的なADFコンテキスト・イベント手法の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のコンテキスト・イベントの作成に関する項を参照してください。
例58-3 部門タスク・フロー(DepartmentsPageDef.xml)のページ定義でのコンテキスト・イベント
<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>
第58.2.3項「タスク・フローに基づいたJSFポートレットの作成方法」で説明されている手順を使用して部門タスク・フローをポートレット化すると、WSRPを介したポートレットとのポートレット通信中に対応するコンテキスト・イベントを転送するために使用されるポートレット・イベントの定義を含むportlet.xml
ファイルが作成されます(例58-4)。
例58-4 ポートレット化された部門タスク・フローのポートレット・エントリ(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
には対応するイベント定義もあります(例58-5)。
例58-5 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
|
従業員タスク・フローでは、標準的なADF手法を使用してdepartmentSelected
イベントを処理します。これは、データ・コントロールでメソッドを呼び出して、departmentSelected
イベントからそのメソッドへのパラメータとしてイベント・ペイロードを提供する methodAction
バインドの形となります。例58-6は、従業員ビューに関するページ定義のmethodAction
バインドの定義を示し、これが従業員タスク・フローで使用されます。
例58-6 従業員タスク・フローのページ定義でのmethodActionの定義(EmployeesPageDef.xml)
<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
に明確にマップするイベント・マップをページ定義に含みます(例58-7)。
例58-7 ポートレット化された従業員タスク・フローのページ定義でのイベント・マップ(EmployeesPageDef.xml)
<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>
注意:
現在のリクエストがOracle JSF Portlet Bridgeの下で実行している場合、 |
2つのポートレット化されたタスク・フローがページに追加されると、部門ポートレットによってトリガーされるイベントの名前が従業員ポートレットによって期待されているものと同じであるかぎり、それ以上のコーディングは不要です。ポートレットは自動的にリンクされ、部門ポートレットで部門が選択されると従業員ポートレットが更新され、選択されている部門に属する従業員が表示されます。
自動的なイベント・リストを使用しないことを選択することもできます。たとえば、同じイベントを使用する同じページ上に複数のポートレットを持ち、それらの間のイベントのフローを制御する場合などに選択できます。または、リンクするJSFポートレットで使用されているコンテキスト・イベントの名前が一致しない場合にも選択します。この場合、ポートレット化されたタスク・フローを含むページのページ定義にイベント・マップを明示的に作成する必要があります。このイベント・マップは、まとめて連結するポートレットのポートレット・イベントをリンクします。例58-8は、従業員タスク・フローがdepartmentSelected
のかわりにdepartmentId
というイベントを予測している場合に、この例でこれがどのような働きをするかを示しています。
例58-8 ページを使用して手動でJSFポートレットをリンクするためのページ定義内のイベント・マップ(BridgeToBridgeExplicitMappingPageDef.xml)
<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>
注意: ポートレット化されたタスク・フローの場合、 |
他のJSFポートレットをJSFポートレットにリンクするのと同様に、JSFポートレットは通常のJSR 286ポートレットにリンクすることもできます。これを実行するには、JSR 286ポートレットがコンテキスト・イベントを受け入れることができると明示的に宣言していることを確認する必要があります。
たとえば、前述の例から部門タスク・フローを部門アドレス・ポートレットJSR 286ポートレットにリンクして、選択されている部門のアドレスを表示できます。
自動的なイベントの関連付けが有効となるために、部門アドレス・ポートレットは、部門ポートレットからコンテキスト・イベントを受け入れ可能であることを宣言する必要があります。これは、次の2つの方法で実行できます。
ポートレット・プロデューサ・アプリケーションのportlet.xml
ファイルでは、部門アドレス・ポートレットがdepartmentSelected
コンテキスト・イベントを直接サポートします。
<supported-processing-event id="departmentSelected"> <qname xmlns:x="http://xmlns.oracle.com/adfm/contextualEvent"> x:departmentSelected </qname> </supported-processing-event>
部門アドレス・ポートレットのdepartment
イベント(portlet.xmlファイルに定義されている)のイベント定義は、これを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
実装にそのコードを含みます(例58-9)。このメソッドでは、前述の定義どおり別名とともにdepartmentSelected
とdepartment
イベントのいずれかを検索します。これらのイベントの両方に対するペイロード・タイプはhr.Department
です。ただし、例58-9に示すメソッドでは、ADFmPayloadWrapper
を使用してペイロードをアンラップする方法を示しています。ADFmPayloadWrapper
は、Oracle JSF Portlet Bridgeがイベント呼出し時にデフォルトで使用するイベント・タイプです。
注意: 部門アドレス・ポートレットは部門場所ポートレットの拡張であるため、例58-9のコードは、部門場所ポートレットのメソッドを含む |
例58-9 departmentSelectedイベントを処理するポートレット・コード
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ページにまとめて表示される場合、部門ポートレットで部門を選択すると、部門アドレス・ポートレットが自動的に更新され、選択されている部門のアドレスが表示されます。
部門アドレス・ポートレットがdepartmentSelected
イベントを明示的にサポートしていない、または適切な別名を定義していない場合でも、ポートレットを使用するページのページ定義にイベント・マップを作成することで2つのポートレットをリンクできます(例58-10)。
例58-10 部門ポートレットと部門アドレス・ポートを明示的にリンクするイベント・マップ
<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
を使用してポートレットにイベントを送信することになります。
注意:
|
ポートレット・イベントをJSR 286ポートレットからJSFポートレットに送信することもできます。ポートレット・イベントは、Oracle JSF Portlet Bridgeによってコンテキスト・イベントに変換され、使用されるプロデューサADFアプリケーションに標準的なコンテキスト・イベント手法を使用して配信されます。
部門タスク・フローに使用される部門ビューのページ定義は、DepartmentsDataControl
上のメソッドにバインドするmethodAction
バンドを含みます(例58-11)。
例58-11 部門タスク・フローのページ定義でのmethodActionの定義(DepartmentsPageDef.xml)
<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にマップするイベント・マップをページ定義に含みます(例58-12)。
例58-12 ポートレット化部門タスク・フローのページ定義でのイベント・マップ(DepartmentsPageDef.xml)
<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>
注意: イベント・マップは、イベントの発信元であるリージョンは参照できません。これはタスク・フローがポートレットとして実行しているときに存在しないためです。そのためイベント・マップではイベント・ソースとしてワイルドカードを使用します。 |
部門場所ポートレットでは、場所が選択されている場合、processAction
メソッドによってポートレット・イベントlocationId
が呼び出され、選択されている場所の場所IDが付与されます(例58-13)。
例58-13 部門場所ポートレットのポートレット・コードでのprocessActionの定義(DepartmentLocationsPortlet.java)
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()))); } }
注意:
同様に、呼び出すイベントのQNameは次のようになります。 {http://xmlns.oracle.com/adfm/contextualEvent}locationId |
ポートレットをページ上にドロップし、部門場所ポートレット内で場所を選択すると、選択した場所に部門を表示する部門ポートレットが自動的に更新されます。
2つのポートレットが一致する名前でイベントを宣言していない(たとえば、部門ポートレットからのコンテキスト・イベントがlocId
とコールされる)場合や、自動イベント・リスニングが無効化されている場合であっても、ポートレットを使用するページのページ定義において、部門ポートレットのコンテキスト・イベントを、部門場所ポートレットのポートレット・イベントにマップするイベント・マップを作成することで、2つのポートレットをリンクすることができます(例58-14)。
例58-14 部門ポートレットと部門場所ポートを明示的にリンクするイベント・マップ
<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>
コンテキスト・イベント・ペイロードでのシリアライズされたタイプの使用
JSR 286イベントのペイロードの一部は、シリアライズされるラップされたコンテキスト・イベント・ペイロードです。そのため、コンテキスト・イベント・ペイロードがいずれのオブジェクト・タイプでも可能である間は、WSRP経由でコンテキスト・イベントを送信するときにはシリアライズされたタイプのみがサポートされます。
このラップされたコンテキスト・イベントが配信されると、コンテキスト・イベント・ペイロードはコンシューマで非シリアライズされなければ、コンシューマ・アプリケーションに転送できません。イベントを非シリアライズするには、ペイロード・クラスがコンシューマとプロデューサで使用可能でなければなりません。この条件は、元のペイロードがjava.lang.String
のようなJava Runtime Environmentクラスであれば自動的に満たされます。
宣言されていないイベントの呼び出し
Oracle ADFタスク・フローがportlet.xml
ファイルに宣言されている対応するポートレット・イベントを持たないADFmイベントを含む場合、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
に設定されている場合、対応するポートレット・イベント宣言を持つイベントのみが転送されます。コンテナ・ランタイム・オプションの詳細は、第59.3.4.3項「個々のポートレットに対するコンテナ・ランタイム・オプションの設定」を参照してください。
また、宣言されていないポートレット・イベントを有効にして、コンシューマ・アプリケーションのポートレット・バインドから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イベントが、リモート・アプリケーションでイベントが呼び出されたときと同じ名前を持つのはこのためです。
部分ページ・レンダリングの使用
Oracle JSF Portlet Bridgeは、ポートレット・イベントを使用してコンシューマ・アプリケーションとの間でコンテキスト・イベントをトランスポートします。ただし、部分ページ・レンダリング(PPR)リクエストは、Portlet 2.0リソース・リクエストを使用して実装されます。リソース・リクエストのポートレット・イベントを送受信することはできません。そのため、PPRリクエストの場合、JSFポートレットからコンシューマ・アプリケーションにコンテキスト・イベントをトランスポートするには専用のメカニズムが使用されます。つまり、これらの非標準メカニズムをサポートしていないポータルでは、イベントは送信されません。
JSR 286ポートレット・マークアップ・フラグメント・ルールに準拠したマークアップを生成するようにJSFページをコーディングする必要があります。Oracle ADFを使用することを選択している場合、ページのマークアップの大部分は、Oracle ADF Facesのコンポーネントからのもので、マークアップは当然ポートレットと互換性のあるスタイルでレンダリングされるか、または互換性のあるスタイルにOracle JSF Portlet Bridgeが自動解釈できます(たとえば、ポートレットをインライン・フレームにレンダリングすることで)。
次の項では、ポートレットとして後で公開することにしたOracle ADFページをコーディングする際に生じる一般的な問題を回避する方法についてのガイダンスを示します。
この項には次のサブセクションが含まれます:
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; } }
アプリケーションが保護されている場合は、第68.17項「WS-Securityを使用したWSRPプロデューサを介するアイデンティティ伝播の保護」に説明されているとおりに保護されたアイデンティティ伝播を実施していることを確認してください。
ポートレットとの通常の対話処理については、コンシューマとプロデューサとの間で保持されるセッションがあります。これは、コンシューマにセッションCookieを保存し、それをリクエストの度にプロデューサに送信することで実行されます。元のリクエストでは、このセッションが確立され、以降のリクエストでは、ポートレットがセッションCookieをプロデューサに送信し、セッションが再利用されます。
ディープ・リンク、つまりポートレットからプロデューサ・アプリケーションへのリンクについては、リクエストはブラウザからプロデューサ・アプリケーションに直接送られます。この場合、セッションCookieは送信できないため新しいセッションが確立されます。ディープ・リンクに共有セッションが必要な場合、これは開発者が実装する必要があります。共通実装とは、この状態を、プロデューサおよびアプリケーションからアクセスできる共通の場所に書き込み、この状態に対する参照をディープ・リンクで渡すことです。
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
要素)で制限されていることに注意してください。
JSFポートレットを使用している場合、コンシューマ・アプリケーションはインライン・フレーム内でポートレット・コンテンツを自動的にレンダリングします。これは、いずれのインライン・ポップアップもインライン・フレーム内に限定されることを意味します。これは、ポートレットのサイズを指定する際に考慮する必要があります。
JSFポートレットがポートレット化されたページである場合、コンテンツの完全なコントロールが可能で、コンテンツ・ファイルがインライン・フレーム・ウィンドウを埋める方法を決定でき、コンテンツがブラウザのウィンドウを埋める方法を決定するときとまったく同じテクニックを活用できます。
ポートレットがコンシューマ・アプリケーション内のその先祖までストレッチされている場合、Oracle JSF Portlet Bridgeによって生成されたドキュメントのaf:document
コンポーネントのmaximized
属性がtrue
に設定されます。つまり、これをサポートするpanelStretchLayout
などのコンポーネントはインライン・フレーム全体を埋めます。
ポートレットのサイズ変更の詳細は、第62.6.5項「ポートレットのサイズ変更に関する必知事項」を参照してください。
リソースおよびリンクについては、web-app-context-root
を基準として場所を指定する必要があります。そうしないと、ポートレットがイメージやその他のリソースを見つけられません。相対パスの表記(../)を使用しないでください。Oracle WebCenter Portal: Frameworkのポートレットは、リモートで実行され、SOAPプロトコル(WSRP)を使用してアクセスされます。後者は、通常のWebアプリケーションのリクエスト・パスの概念が、JSR 286コンテナでは意味がないということです。JSR 286仕様では、すべてのリソースURLが絶対パスまたはコンテキスト相対パスのいずれかであることが規定されていることにこれが反映されています。
リクエストをJSP内でリダイレクトまたは転送しないでください。JSR 286では、requestDispatcher.include()
のみがサポートされます。httpServletResponse.sendRedirect()
またはrequestDispatcher.forward()
を使用すると、例外やエラーが発生します。ポートレット環境で正常に作業を行うには、faces-config.xml
でのJSFナビゲーション・ルールまたはOracle ADFタスク・フローの制御フロー・ルールを実装する必要があります。
Oracle JSF Portlet Bridgeは、リクエスト間のリクエスト・スコープのコンテンツを保存し、リクエスト・スコープがActionポートレットとRenderポートレット(これらは2つの別個のリクエスト)との間で予約されるようにします。このため、メモリー使用量全体を最小限に抑えるには、アプリケーションがJSFポートレットを含む場合にリクエスト・スコープ内にあまりデータを保存しすぎないようにする必要があります。
Oracle JSF Portlet Bridgeは、Portlet 2.0機能を利用します。そのため、これはWSRP V2以外では使用しないようにしてください。ポートレットのminimumWsrpVersion
コンテナ・ラインタイム・オプションは2
に設定する必要があります。詳細は、第59.3.4項「JSR 286ポートレットのランタイム環境をカスタマイズする方法」を参照してください。
「ポートレット・エントリの作成」または「タスク・フローのポートレット・エントリの管理」ダイアログを使用して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ポートレットはコンテンツをレンダリングしません。
プロデューサへのWS-Securityの設定の詳細は、第68.17項「WS-Securityを使用したWSRPプロデューサを介するアイデンティティ伝播の保護」を参照してください。
使用するアプリケーションでプロデューサを登録する場合、必ず適切なセキュリティ・プロパティを設定する必要があります。詳細は、第62.2.1項「WSRPポートレット・プロデューサの登録方法」を参照してください。
h:commandLink
JSF標準HTMLコンポーネントを使用する場合、JSFリファレンス実装が外部JavaScriptリソースを生成しないようにweb.xml
に次のcontext-param
を設定していることを確認する必要があります。これは、JavaScriptリソースへの参照が適切にエンコードされないというJSFリファレンス実装での問題を回避することが目的です。
<context-param> <param-name>com.sun.faces.externalizeJavaScript</param-name> <param-value>false</param-value> </context-param>
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.trinidadinternal.skin.SkinUtils" level=FINEST"/>
コンシューマ・ページを実行すると、コンシューマとプロデューサのログ・ファイルと一致しないスキン・エントリはスキン不一致の原因となります。
ADF Facesダイアログ・フレームワークはサポートされていません。アプリケーションがセカンダリ・ブラウザ・ウィンドウを起動するボタンまたはアイコンを含む場合、アプリケーションがポートレットとして実行される場合に新しいウィンドウの内容は正しく表示されません。そのため、アプリケーションのポートレット化を計画している場合は、これらのコンポーネントの使用は避ける必要があります。セカンダリ・ウィンドウを起動するコンポーネントの例は次のとおりです。
<tr:inputDate>
<tr:inputColor>
<tr:popup>
<af:commandButton>
のuseWindow
属性
コンポーザ・コンポーネントを含むページのポートレット化はサポートされていません。
<af.fileDownloadActionListener>
コンポーネントはサポートされていません。
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
フェーズで、ページ・パラメータを参照しないでください。この問題は、第58.6.5.7項「リクエスト・パラメータへのアクセス」でリクエスト・パラメータについて説明されている問題に関連します。一般的に、ページ・パラメータはリクエスト・パラメータに依存し、restoreView
フェーズ中に評価されます。このフェーズが、ポートレットのレンダリング中にもう一度コールされ、リクエスト・パラメータがないと、失敗に終わります。かわりに、JSFの実行フェーズからレンダリング・フェーズへの遷移の前に、ページ・パラメータ値に対する依存性をモデルに移動します。
Trinidadコンポーネントのみ(<tr:>
タグのみ)を含むアプリケーションをポートレット化する場合は、プロジェクトに次のライブラリを手動で含める必要があります。
jdeveloper\modules\oracle.adf.view_11.1.1\adf-richclient-api-11.jar
jdeveloper\modules\oracle.adf.view_11.1.1\adf-richclient-impl-11.jar
これは、プロデューサに対して生成されたスタイル・シート内のアイコンに対するURLが正しくエンコードされるようにするためです。
ポートレットはネーミング・コンテナであるため、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 Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』のネーミング・コンテナの注意事項に関する項を参照してください。
デフォルトでは、ポートレット化されたページまたはタスク・フローの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">
注意: このパラメータは、プロデューサ・サーバーにあるリソースへのアクセスには使用しないでください。これらのリソースにはポートレット・クライアントのプロキシを使用してアクセスする必要があります。 |
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"/>
WebCenter Portalアプリケーションでは、リソース・マネージャを使用して実行時にスキンを作成できます。これを実行すると、JSFポートレットを含むページ上にレンダリングの問題が発生する場合があります。これは、WebCenter Portalアプリケーションが使用するスキンが、タスク・フローをレンダリングするリモート・アプリケーションで使用できないためです。
この問題を是正するには、実行時に作成されたスキンを、タスク・フローがポートレット化されたときに作成されたポートレット・プロデューサ・アプリケーションにコピーする必要があります。
実行時作成スキンをポートレット・プロデューサ・アプリケーションにコピーするには:
スキンをFrameworkアプリケーションからEARファイルにエクスポートします。
方法の詳細は、第16.4.1項「リソース・マネージャを使用してリソースをダウンロードする方法」を参照してください。
エクスポートしたスキンを共有ライブラリ(JARファイル)として再パッケージ化します。
transport.mar
ファイルを抽出します。
$ jar xvf myskin.ear inflated: transport.mar
メタデータ・ファイルを抽出します。
$ jar xvf transport.mar inflated: oracle/webcenter/siteresources/.../Skin.css inflated: oracle/webcenter/siteresources/.../generic-site-resources.xml ...
メタデータ・ファイルの中からgeneric-site-resources.xml
ファイルを見つけて表示します。通常、このファイルは次のようなディレクトリにあります。
oracle/webcenter/siteresources/scopedMD/scopeGUID/generic-site-resources.xml
ファイルには、次の例のような、エクスポートされたスキンを説明するセクションがあります。
<resourceType name="skin" ...> <resource displayName="MySkin" metadataFile="/oracle/webcenter/siteresources/.../Skin.css" ...> <customAttributes> <customAttribute name="skinId" value="gsr616d879d_99e0_4bd9_8c10_98e7ea272a6a.desktop" .../> <customAttribute name="skinFamily" value="gsr616d879d_99e0_4bd9_8c10_98e7ea272a6a" ...> <customAttribute name="skinExtends" Value="webcenter-fusion-internal.desktop" .../> </customAttributes> </resource> </resourceType>
generic-site-resources.xml
からの次の情報に注意してください。
skinId
(たとえばgsr616d879d_99e0_4bd9_8c10_98e7ea272a6a.desktop
)
skinFamily
(たとえばgsr616d879d_99e0_4bd9_8c10_98e7ea272a6a
)
skinExtends
(たとえばwebcenter-fusion-internal.desktop
)
JARファイルのディレクトリ構造を次のように構築します。
$ mkdir META-INF
次のようにSkin.css
ファイルをMETA-INF
ディレクトリにコピーします。
$ cp oracle/webcenter/siteresources/.../Skin.css META-INF
META-INF
ディレクトリの下にtrinidad-skins.xml
という新しいファイルを作成します。
$ edit META-INF/trinidad-skins.xml
次のXMLを新しいtrinidad-skins.xml
ファイルに追加します。
<?xml version="1.0" encoding="ISO-8859-1"?> <skins xmlns="http://myfaces.apache.org/trinidad/skin"> <skin> <style-sheet-name>Skin.css</style-sheet-name> <id>skinId</id> <family>skinFamily</family> <extends>skinExtends</extends> <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id> </skin> </skins>
ここで、skinId
、skinFamily
、およびskinExtends
は、前述の値です。
JARファイルを次のようにパッケージ化します。
$ jar cvf myskin.jar META-INF adding: META-INF/trinidad-skins.xml(in = 359) (out= 171)(deflated 52%) adding: META-INF/Skin.css(in = 5560) (out= 1413)(deflated 74%)
JARファイルはSkin.css
とtrinidad-skins.xml
という2つのファイルを含む必要があります。
新しいmyskin.jar
ファイルをポートレット・プロデューサ・アプリケーションにコピーします。
これを行う最も簡単な方法とは、ファイルをポートレット・プロデューサのWebアプリケーションのWEB-INF/lib
ディレクトリにコピーするというものです。