この章では、Oracle JDeveloperポータル・アドインを使用して作成したJavaポートレットを拡張する方法、およびStrutsアプリケーションからポートレットを作成する方法について説明します。この章の内容は、次のとおりです。
この章で参照される多数の例のソース・コードは、PDK-Javaの一部として利用できます。PDK-JavaはOracle Technology Network(OTN)からダウンロードできます。
http://www.oracle.com/technology/products/webcenter/index.html
PDK-Javaを解凍すると、次の場所に例があります。
../pdk/jpdk/v2/src/oracle/portal/sample/v2/devguide
PDK-Java用の参照Javadocは次の場所にあります。
../pdk/jpdk/v2/apidoc
6.3.1項「JSR 168ポートレットの作成」に示すように、ポートレット・ウィザードで初期ポートレットを作成すると、これを拡張できます。JPSポートレットはJava標準に準拠しているため、これの拡張に関する情報は、サード・パーティの書籍やWebページなど様々なソースから多数入手できます。この項では、必要性が高い最重要レベルの拡張機能である7.1.1項「パーソナライズの追加」について説明します。
この項では、6.3.1項「JSR 168ポートレットの作成」で作成したポートレットを拡張します。拡張には、ユーザーがポートレットによるレンダリング対象のフィールドに編集モードまたはデフォルト編集モードでHTMLを貼り付けるために使用できるコードを使用します。また、ポートレットを簡単に再デプロイする方法についても説明します。
この項では、コードをMy Java Portletに追加し、ポートレットを再デプロイし、これをOracle Portalでテストします。そのための手順は、次のとおりです。
Oracle JDeveloperの「アプリケーション・ナビゲータ」で、JPS標準に準拠したポートレットのview.jsp
ファイルをダブルクリックします。
次のコードの中で太字で示された部分を追加します。
<%@ page contentType="text/html" import="javax.portlet.*,java.util.*,mypackage1.Portlet1, mypackage1.resource.Portlet1Bundle"%>" <%@ taglib uri="http://java.sun.com/portlet" prefix="portlet"%> <portlet:defineObjects/> <% PortletPreferences prefs = renderRequest.getPreferences(); %> <%= prefs.getValue("portletContent", "Portlet Content") %>
ビジュアル・デザイナでedit.jsp
を開き、「設計」タブをクリックします。JSPは、図7-1で示すように、フォーム・フィールド、フォーム入力フィールドおよび2つのフォーム・ボタン・フィールドで構成されています。
次のコードの中で太字で示された部分を追加し、Contentという名前のフォーム・フィールドを実装します。
<FORM ACTION="<portlet:actionURL/>" METHOD="POST"> <TABLE BORDER="0"> <TR><TD WIDTH="20%"> <P CLASS="portlet-form-field" ALIGN="right"> <%= res.getString(Portlet1Bundle.PORTLETTITLE) %> </P></TD><TD WIDTH="80%"><INPUT CLASS="portlet-form-input-field" TYPE="TEXT" NAME="<%= Portlet1.PORTLETTITLE_KEY %>" VALUE="<%= prefs.getValue(Portlet1.PORTLETTITLE_KEY, res.getString("javax.portlet.title")) %>" SIZE="20"> </TD></TR> <tr><td width="20%"> <p class="portlet-form-field" align="right"> Content </p> </td><td width="80%"> </td></tr> <TR><TD COLSPAN="2" ALIGN="CENTER"> <INPUT CLASS="portlet-form-button" TYPE="SUBMIT" NAME= "<%= Portlet1.OK_ACTION%>" VALUE="<%= res.getString(Portlet1Bundle.OK_LABEL) %>"> <INPUT CLASS="portlet-form-button" TYPE="SUBMIT" NAME= ="<%=Portlet1.APPLY_ACTION %>" VALUE="<%= res.getString(Portlet1Bundle.APPLY_LABEL) %>"></TD></TR> </TABLE>
「設計」タブをクリックし、追加した新しいフォーム・フィールドを表示します(図7-2)。
ビジュアル・エディタでWelcomePortlet.java
を開き、processAction
メソッドに次の太字で示された2行のコードを挿入します。
// Save the preferences. PortletPreferences prefs = request.getPreferences(); String param = request.getParameter(PORTLETTITLE_KEY); prefs.setValues(PORTLETTITLE_KEY, buildValueArray(param)); String contentParam = request.getParameter("portletContent"); prefs.setValues("portletContent", buildValueArray(contentParam)); prefs.store();
ポートレットを再デプロイします。Oracle JDeveloperによりコードが自動的に保存およびコンパイルされた上で、ポートレットがデプロイされます。この手順の実行方法に関する注意は、6.3.3項「Oracle WebLogic ServerへのJSR 168ポートレットのデプロイ」を参照してください。
Oracle Portalで、ポートレットが含まれるページをリロードします。ポートレットには、Oracle JDeveloperで行った変更の1つである「Portlet Content」というテキストが表示されます。
「カスタマイズ」リンクをクリックします。Oracle JDeveloperで追加した新しいフォーム・フィールドが表示されます。
「Content」フィールドに次のHTMLを入力し、Portlet Contentというテキストを置き換えます。
<p>Read <em>The Path to Portlet Interoperability</em> by John Edwards in <strong>Oracle Magazine</strong>, Nov-Dec 2003. </p> <p>It discusses JSR 168 and WSRP open portals. </p>
「適用」をクリックし、「閉じる」をクリックします。これにより、このHTMLはポートレットでレンダリングされます。
6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」に示すように、ポートレット・ウィザードで初期ポートレットを作成すると、次のタスクを実行してこれを拡張できます。
この項では、次のことを前提にしています。
ポートレットの表示モードなど、ポートレットに関する用語の知識があること。第1章「ポートレットの概要」および6.1項「Javaポートレット作成のガイドライン」を参照してください。
Javaポートレット・コンテナをすでにダウンロードしてインストールしていること。
Oracle JDeveloperに関する知識があり、それを使用したJavaコンポーネントを構築およびデプロイする方法を習得していること。Oracle JDeveloperはOTNからダウンロードできます。次のURLでOTNの「Oracle JDeveloper」ページにアクセスします。
http://www.oracle.com/technology/products/jdev/index.html
表示モードを追加するには、ポートレット・ウィザードの各ページで該当するボックスを選択します。ウィザードの使用方法の詳細は、6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」を参照してください。ウィザードで選択した表示モードごとに、基本的なHelloWorldスケルトンが作成されています。ポートレットの作成後に表示モードを追加する必要がある場合やウィザードでは選択できないモード(プレビューまたはリンク)を追加する場合は、provider.xml
およびHTMLまたはJSPをOracle JDeveloperで更新して手動で追加できます。次の各項では、PDK-Javaポートレットに表示モードを追加する方法について説明します。
この項を終了すると、RenderManager
を使用してあらゆる表示モードを実装できます。これは、すべてのモードの原理が同じであるためです。たとえば、この項ではヘルプ・モードの実装方法は詳しく説明しませんが、プロセスはここで説明するプレビュー・モードと同じであるため、方法は理解できます。
この項で使用されているPDKランタイム・クラスの詳細は、次の「Portlet Development」ページの「Java Doc API」をクリックして、OTNのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/portlet_development_10g1014.html
provider.xml
の構文の詳細は、プロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
表示モードを手動で作成する際は、最初に、各モードのHTMLファイルまたはJSPを作成します。たとえば、プレビュー・モードを実装する場合は、HTMLファイルを作成してプレビュー・コンテンツを提供する必要があります。
HTMLファイルを作成してコンテンツをプレビューする手順は、次のとおりです。
Oracle JDeveloperで、ポートレットが含まれるプロジェクトを開きます。
Webコンテンツhtdocs\myportlet
の下に、PreviewPage.html
というHTMLページを作成します。ファイルのコンテンツは、たとえば次のようになります。
<p>This is the <i>preview</i> mode of your portlet!</p>
コンテンツをプレビューするためのHTMLファイルを作成すると、XMLプロバイダ定義を更新する準備が完了します。
追加の表示モードを公開する場合は、次のようにXMLプロバイダ定義を更新する必要があります。
ブール・フラグを設定し、そのモードへのリンクまたはアイコンをレンダリングする必要があることをPDKフレームワークに示します。
そのモードに対して作成したHTMLファイルまたはJSPを指定します。
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
たとえば、プレビュー・モードをレンダリングする手順は、次のとおりです。
プロバイダ定義ファイルprovider.xml
を編集し、<portlet></portlet>
タグでプレビュー・モードが有効になるように次のようにタグを追加します。
<showPreview>true</showPreview>
7.2.1.2項「追加の表示モードの実装」で作成したHTMLページをプレビュー・ページとして指定します。
<previewPage>/htdocs/myportlet/MyPortletPreviewPage.html</previewPage>
更新内容をprovider.xml
に保存します。
ポートレットを再デプロイします。6.5.4項「アプリケーション・サーバーへのOracle PDK-Javaポートレットのデプロイ」の手順11を参照してください。
再デプロイする場合は、Oracle JDeveloperにより、コードが自動的に保存およびコンパイルされた上で、ポートレットがデプロイされます。
新規の表示モードを表示するには、更新したXMLプロバイダ定義が再解析されるようにする必要があります。そのための手順は、次のとおりです。
7.2.1.2項「追加の表示モードの実装」で作成したHTMLファイルおよびprovider.xml
を、ポートレットをデプロイするWebLogic Serverインスタンスにコピーします。
プロバイダをリフレッシュします。
ポートレットが含まれているポータル・ページをリフレッシュします。
プレビュー・モードを表示する手順は、次のとおりです。
7.2.1項「表示モードの追加」では、PDKプロバイダ・フレームワークを使用して、ウィザードでポートレットを作成したときに無効だった表示モード、またはウィザードでは選択できない表示モード(リンク・モードとプレビュー・モードなど)を有効にしてレンダリングする方法を説明しました。この項では、2つのパーソナライズ・モード(編集およびデフォルト編集)を詳細に説明します。Javaポートレット・ウィザードで「ページを編集」と「デフォルト・ページを編集」を選択すると、この2つのパーソナライズ・モードについてスケルトン・コードが生成されます。このスケルトン・コードを使用すると、数行のコードでパーソナライズ・フレームワークにアクセスでき、パーソナライズ・フレームワークおよび値を保持するためのデータ・ストアをすべて手動でコーディングする必要がありません。ポートレットにパーソナライズを追加するには、次の作業を実行する必要があります。
ポートレットの「編集」ページを更新し、パーソナライズの変更を設定して取得します。
ポートレットの「デフォルトの編集」ページを更新し、パーソナライズの変更を設定して取得します。
ポートレットの「表示」ページを更新して、ユーザーが設定したパーソナライズを使用します。
ポートレット・ユーザーは、編集モードおよびデフォルト編集モードを使用して、ポートレットでサポートされている一連のカスタマイズ可能パラメータを変更できます。通常は、これらのパラメータによって、ポートレットを他のモードでレンダリングします。Oracle Portalページにあるポートレットの特定のインスタンスの場合、編集モードおよびデフォルト編集モードで行われたパーソナライズは、そのポートレットのそのインスタンスにのみ適用されます。このことについて説明します。
編集モードでのパーソナライズは、パーソナライズを行う個々のユーザーに適用されます。このモードを有効にするには、表示モードで、ポートレット・ヘッダーにある「パーソナライズ」リンクをクリックします。
デフォルト編集モードでのパーソナライズは、そのポートレット・インスタンスに対して特定のパーソナライズを行っていない、同じロケール内のすべてのユーザーに適用されます。通常、このモードを使用できるのはページ設計者のみで、ページ上の「編集」アイコンに従うことで有効にできます。
編集モードおよびデフォルト編集モードをレンダリングすると、PortletRenderer
は、パーソナライズ・プロセスをサポートするために、次のいずれかのタスクを実行できます。
編集フォームのレンダリング: ポートレットのカスタマイズ可能パラメータごとに、PortletRenderer
はPortletPersonalizationManager
を使用して現在の値を取得し、コントロールをHTMLフォームでレンダリングします。これによって、現在の値を編集できます。
編集フォーム操作の処理: 標準の編集フォーム・ヘッダーで「OK」または「適用」ボタンをクリックすると、PortletRenderer
はPortletPersonalizationManager
を使用して、編集フォームから送信されたパーソナライズ済パラメータを格納し、ブラウザを適切なポータル・ページにリダイレクトします。
したがって、PortletPersonalizationManager
コントローラを使用することによって、PortletRenderer
は、特定のポートレットのインスタンスやユーザーに適用されるカスタマイズ可能パラメータの現在の値を格納および取得できます。PDKフレームワークでは、一連のパーソナライズ済パラメータのコンテナとしてPersonalizationObject
の抽象化を使用し、一連のパーソナライズを格納するキーとしてPortletReference
を使用します。つまり、PortletPersonalizationManager
は、特定のPortletReference
の下にある永続的なPersonalizationObjects
の格納と取得を可能にするメカニズムです。
プリファレンス・ストアは、Oracle Portalの使用時に、ユーザー・プリファレンス・データ、ポートレットまたはプロバイダの設定、さらにポートレット・データなどの情報を格納するメカニズムです。ログアウトした後で再度ログインしても、以前保存したプリファレンスにアクセスできるという意味で、プリファレンス・ストアに格納された情報は永続的です。プリファレンス・ストアではユーザー設定項目情報が保持され、ユーザーがログインするたびにそのユーザーの設定項目が起動されます。PDK-Javaには、PreferenceStore
実装を使用してパーソナライズ済データを永続化するPrefStorePersonalizationManager
が用意されています。現在、PDK-Javaには、DBPreferenceStore
およびFilePreferenceStore
の2つのPreferenceStore
実装があります。DBPreferenceStore
は、JDBCと互換性のあるリレーショナル・データベースを使用してデータを永続化し、FilePreferenceStore
は、ファイル・システムを使用してデータを永続化します。
これらの実装の詳細は、次の「Portlet Development」ページの「Java Doc API」をクリックして、OTNのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/portlet_development_10g1014.html
注意: PDK-Javaには、プリファレンス・ストア移行/アップグレード・ユーティリティが用意されています。このユーティリティを使用すると、プリファレンス・ストアのファイル・システムからデータベースへの移行、およびパーソナライズの旧リリースからのアップグレードが簡単にできます。このユーティリティの詳細は、OTNを参照してください。
|
パーソナライズ機能をポートレットに追加するには、PrefStorePersonalizationManager
を、デフォルトのPersonalizationObject
実装であるNameValuePersonalizationObject
とともに使用します。ユーザーがポートレット・タイトルをパーソナライズできるように、ウィザードではデフォルトで、編集モードおよびデフォルト編集モードに対して簡単な編集フォームが生成されます。この項では、ポータル・ユーザーがポートレット・メッセージをパーソナライズできるように、既存のコードを更新する方法を説明します。
この項のタスクを実行するには、次の前提が必要です。
次の項を読み終えて理解していること。
「ページを編集」および「デフォルト・ページを編集」が選択された状態のウィザードで作成したポートレットをページに追加していること。
ポートレットの「編集」ページは、ユーザーがポートレットをパーソナライズするときにコールされます。ウィザードで生成されたJSPには、ポートレット・タイトルのパーソナライズに必要なコードがすべてデフォルトで含まれています。さらにパーソナライズする場合は、数行のコードを「編集」ページに挿入する必要があります。
<%@page contentType="text/html; charset=windows-1252" import="oracle.portal.provider.v2.render.PortletRenderRequest" import="oracle.portal.provider.v2.http.HttpCommonConstants" import="oracle.portal.provider.v2.personalize.NameValuePersonalizationObject" import="oracle.portal.provider.v2.render.PortletRendererUtil" %> <% PortletRenderRequest pReq = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); %> <P>Hello <%=pReq.getUser().getName() %>.</P> <P>This is the <b><i>Edit</i></b> render mode!</P> <%-- This page both displays the personalization form and processes it,. Display the form if there is no action parameter, process it otherwise --%> <% String actionParam = PortletRendererUtil.getEditFormParameter(pReq); String action = request.getParameter(actionParam); String title = request.getParameter("my2portlet_title"); NameValuePersonalizationObject data = (NameValuePersonalizationObject) PortletRendererUtil.getEditData(pReq); // Cancel automatically redirects to the page, so // will only receive OK or APPLY if (action !=null) { data.setPortletTitle(title); PortletRendererUtil.submitEditData(pReq, data); return; } // Otherwise just render the form. title = data.getPortletTitle(); %> <table border="0"> <td width="20%"> <p align="right">Title:</p> </td> <td width="80%"> <input type="TEXT" name="my2portlet_title" value="<%= title %>"> </td> </table>
JSPには、ポートレット・タイトル用の入力フィールドが含まれています。このフィールドはポートレットの「パーソナライズ」ページを表し、ユーザーはこのページでポートレット・タイトルを更新できます。生成されたコードを変更するための手順は、次のとおりです。
生成されたコード内の表に続いて、ユーザーがポートレットの新しいメッセージを入力できるテキスト・フィールドとプロンプトを含む2番目の表を追加します。
<table border="0"> <tr> <td width="20%"> <p align="right">Greeting:</p> </td> <td width="80%"> <input type="TEXT" name="myportlet_greeting" value="<%= greeting %>"> </td> </tr> </table>
このHTMLは、「編集」ページで新しいメッセージを入力するためのフィールドを指定します。この新しいメッセージは、ポートレットの共有画面モードで表示されます。次に、String title
の下に、メッセージの値を取得する文字列を追加します。
String title = request.getParameter("my2portlet_title");
String greeting = request.getParameter("myportlet_greeting");
ウィザードで「編集」ページが生成されると、パーソナライズ・フレームワークへのアクセスがページ・コードに自動的に含まれます。「編集」ページの最上部で、NameValuePersonalizationObject
が宣言されています。Oracle Portalにあるパーソナライズ用のこのフォームを使用すると、名前と値のペアを簡単に格納できます。
「編集」ページでは、ページの表示、またはページへの変更の適用を処理します。これまでに行った変更は、ページを表示するためのコードに影響を与えます。「編集」ページへの変更の適用は、if (action !=null)
で始まるコード・ブロックで処理されます。
新しいポートレット・メッセージは、このコード・ブロックで格納する必要があります。また、ユーザーが何も変更しなかったため、既存のメッセージを取得する場合にも対処する必要があります。
if (action !=null) { data.setPortletTitle(title); //Put the new greeting. data.putString("myportlet_greeting", greeting); PortletRendererUtil.submitEditData(pReq, data); return; } //Otherwise just render the form. title = data.getPortletTitle(); //Get the old greeting. greeting = data.getString("myportlet_greeting");
これで、「編集」ページの更新が完了しました。
これらの変更内容は、「デフォルトの編集」ページにそのままコピーできます。「デフォルトの編集」ページは、ページ設計者またはポータル管理者がページで「編集」をクリックしてからポートレットの「デフォルトの編集」アイコンをクリックするとコールされます。このページでは、ポートレットのこのインスタンスに対して、デフォルトのパーソナライズを設定します。JSPのコードが同じ場合でも、PDKフレームワークとOracle Portalは、表示モード(編集またはデフォルト編集)に応じて個別にパーソナライズを自動的に処理します。
ポートレットの共有画面モードでパーソナライズ・データにアクセスするには、「表示」ページに数行のコードを追加する必要があります。これらの行を追加することで、次のタスクを実行します。
import文の追加
NameValuePersonalizationObject
の宣言
パーソナライズ・データの取得
「表示」ページのパーソナライズを実装する手順は、次のとおりです。
「表示」ページを編集し、NameValuePersonalizationObject
およびPortletRendererUtil
をインポートします。これらは、必要に応じて「編集」ページからコピーすることもできます。
<%@page contentType="text/html; charset=windows-1252" import="oracle.portal.provider.v2.render.PortletRenderRequest" import="oracle.portal.provider.v2.http.HttpCommonConstants" import="oracle.portal.provider.v2.personalize. NameValuePersonalizationObject" import="oracle.portal.provider.v2.render.PortletRendererUtil" %>
NameValuePersonalizationObject
を宣言し、ポートレット・レンダリング・リクエストから編集データを取得します。この編集データは、ポートレットの「編集」ページからコピーすることもできます。
<% PortletRenderRequest pReq = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); NameValuePersonalizationObject data = (NameValuePersonalizationObject) PortletRendererUtil.getEditData(pReq); %>
パーソナライズ・フレームワークから文字列情報を取得します。
<%
String greeting = data.getString("myportlet_greeting");
%>
ポートレットの共有画面モードでメッセージを表示する「表示」ページに、テキストを追加します。
<P>Hello <%= pReq.getUser().getName() %>.</P> <P>This is the <b><i>show</i>,</b> render mode!</P> <P>Greeting: <%= greeting %></P>
これで、ポートレットの「表示」ページの更新が完了しました。
ポートレット・ウィザードでは、XMLプロバイダ定義ファイル(provider.xml
)のPreferenceStore
にアクセスするために必要なすべてのタグが生成されます。デフォルトでは、ウィザードはプロバイダ・レベルでFilePreferenceStore
クラスを使用して設定を格納します。
<provider class="oracle.portal.provider.v2.DefaultProviderDefinition"> <session>false</session> <passAllUrlParams>false</passAllUrlParams> <preferenceStore class="oracle.portal.provider.v2.preference.FilePreferenceStore"> <name>prefStore1</name> <useHashing>true</useHashing> </preferenceStore>
ポートレット・レベルでは、PrefStorePersonalizationManager
をpersonalizationManager
クラスとして使用し、NameValuePersonalizationObject
をデータ・クラスとして使用するためのタグが追加されます。
<personalizationManager class="oracle.portal.provider.v2.personalize. PrefStorePersonalizationManager"> <dataClass>oracle.portal.provider.v2.NewValuePersonalizationObject</dataClass> </personalizationManager>
FilePreferenceStore
クラスを継続して使用する場合、XMLプロバイダ定義に対する変更や更新は不要です。ただし、Oracle Portalのグローバル環境がある場合(たとえば、Oracle Containers for Java EEインスタンスのロード・バランスされた複数ノード・クラスタで実行中の場合)、または設定をデータベースに格納する場合は、クラスをFilePreferenceStore
からDBPreferenceStore
に変更できます。
DBPreferenceStore
の使用方法の詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
前述の項で行ったパーソナライズの変更を表示するには、ポートレットをアプリケーション・サーバーまたはOracle Containers for Java EEにデプロイし、ポートレットが含まれるページをリフレッシュする必要があります。ポートレットのデプロイの詳細は、6.5.4項「アプリケーション・サーバーへのOracle PDK-Javaポートレットのデプロイ」を参照してください。
ポートレットにNULLのメッセージが含まれていることを確認してください。ポートレット・タイトル・バーで「パーソナライズ」をクリックし、メッセージを更新します。ページに戻ると、変更内容が反映されています。
また、ページ上の「編集」をクリックしてから「デフォルトの編集」アイコンをクリックすると、「デフォルトの編集」をテストできます。すでにポートレットは変更されているため、パブリック・ユーザーまたは別のユーザーとしてページを表示するまで、変更内容は共有画面モードで表示されません。
Oracle PortalおよびPDKは、ポートレット開発者が再利用可能で複雑なポートレットを簡単に作成できるように、ページ・パラメータ、パブリック・ポートレット・パラメータ、プライベート・ポートレット・パラメータおよびイベントを提供しています。Oracle JDeveloperのポートレット・ウィザードは、パラメータとイベントを使用するように設定されたポートレットを作成します。この機能によって、開発者はビジネス・ロジックをポートレットに追加するのみ行い、provider.xml
を変更する必要はありません。
パラメータおよびイベントの概要は、次の項を参照してください。
この項のタスクを実行するには、次の前提が必要です。
6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」を読んで理解していること。
ウィザードで作成したポートレットがページに正常に追加されていること。
注意: 各ポートレットのデータは4Kに制限されています。パラメータ、イベント名、表示名および説明の各長さもすべてこの4Kの制限に対するカウント対象に含まれます。このため、各ポートレットに対して必要以上の数のパラメータやイベントを使用しないこと、またはこれらの名前や説明を長くしないことが必要です。 |
6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」では、ウィザードを使用して、基本的なポートレットを作成し、MyParam
というパラメータを指定しました。パラメータを作成していない場合は、ここで新しいポートレットを作成できます。ポートレットを作成するには、Oracle JDeveloperの「アプリケーション - ナビゲータ」でprovider.xml
を右クリックし、「ポートレットの追加」を選択して、6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築で説明している手順を実行します。
ウィザードでは、コードまたはファイルを更新する必要がなくページ・パラメータを簡単にマップできるポートレットがデフォルトで作成されます。この項では、ウィザードで作成されたデフォルト・パラメータを使用します。
デフォルト・パラメータを使用するには、プロバイダを登録して、ポートレットをページに追加する必要があります。追加した後に、次のタスクを実行します。
ページ・パラメータを作成します。
ページ・パラメータをJavaポートレットにマップします。
URL、またはこのページ・パラメータを渡す別のポートレットにパラメータ値を入力します。
ポートレットにパラメータを追加する手順は次のとおりです。
ページ・プロパティの「パラメータ」タブに移動します。パラメータは、デフォルトで有効になっています。無効な場合は、続行する前に有効にしてください。
MyParameter
というページ・パラメータを作成し、デフォルト値はMy Default Value
と入力します。
Javaポートレットを開き、作成したページ・パラメータをポートレット・パラメータにマップします。ポートレットのパラメータは、MyParameter
と呼ばれるページ・パラメータにマップする必要があります。
ページに戻ります。ポートレットにMy Default Value
という値が表示されていることに注意してください。
ページを表示し、URLの最後にパラメータと値を入力します。
&MyParameter=This%20portlet%20works
図7-5は、パラメータ・ポートレットの一例を示しています。
OmniPortletのシンプル・パラメータ・フォームなど、パラメータを渡すことができるポートレットがある場合は、「イベント」タブを使用して、そのポートレットからJavaポートレットにパラメータをマップできます。
ここで、ウィザードで生成されたコードおよびタグを確認すると、Javaポートレットでパラメータを有効にするには、数行のコードが必要であることがわかります。
provider.xml
を確認します。ウィザードによって、inputParameter
というタグ・グループが追加されています。これには、ポートレットがリスニングするパラメータの名前が含まれます。
<inputParameter class="oracle.portal.provider.v2.DefaultParameterDefinition"> <name>MyParam</name> <displayName>My Portlet Parameter</displayName> </inputParameter>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
また、ウィザードによって、このパラメータを受信してパラメータ名とその値を表示する「表示」ページのコードがJSPで生成されています。
<%
ParameterDefinition params[] =
pReq.GetPortletDefinition().getInputParameters();
%>
<p>This portlets input parameters are ...</p>
<table align="left" width="50%"><tr><td><span class="PortletHeading1">Value
</span></td></tr>
<%
String name = null;
String value = null;
String[] values = null;
for (int i = 0; i < params.length; i++)
{
name = params[i].getName();
values = pReq.getParameterValues(name);
if (values != null)
{
StringBuffer temp = new StringBuffer();
for (int j = 0; j < params.length; j++)
{
temp.append(values[j]);
if (j + 1 != values.length)
{
temp.append(", ");
}
}
value = temp.toString();
}
else
{
value = "No values submitted yet.";
}
%>
<tr>
<td><span class="PortletText2" <%= name %></span></td>
<td><span class="PortletText2" <%= value %></span></td>
</tr>
<%
}
%>
</table>
1つのポートレット内で使用されるパラメータを、プライベート・パラメータといいます。これらは、1つのポートレット・インスタンスでのみ表示されます。ポートレット・パラメータは、この項で説明するPDK-Java APIを使用して作成およびアクセスします。ポートレットのコンシューマで正しく処理されるように、パラメータ名は修飾されます。以下のAPIによって、この処理が行われます。
HttpPortletRendererUtil.portletParameter(HttpServletRequest request, String param);
HttpPortletRendererUtil
は、パッケージoracle.portal.provider.v2.render.http
に含まれています。
次に例を示します。
qualParamQ = HttpPortletRendererUtil.portletParameter(r, "q");
受信リクエストからポートレット・パラメータの値をフェッチするには、次のAPIを使用します。
注意: このAPIは、受信リクエストから値をフェッチする前にパラメータ名を修飾パラメータ名に変換します。このため、この手順を実行する必要はありません。 |
PortletRenderRequest.getQualifiedParameter(String name);
PortletRenderRequest
は、パッケージoracle.portal.provider.v2.render
に含まれています。
次に例を示します。
valueQ = r.getQualifiedParameter("q");
プライベート・パラメータを使用するためのユーティリティの詳細は、7.2.3.3.2項「ポートレットのURLタイプを使用したリンクの構築」および7.2.3.3.3項「ポートレットのURLタイプを使用したフォームの構築」を参照してください。
ポートレット内リンクは、ポートレットがあるOracle Portalページを参照します。多くの場合、このポートレットはOracle Portalから離れた場所で動作しています。このため、ポートレットがOracle PortalページのURLを知らなくても正しいページのリンクをレンダリングできるようにする方法を検討する必要があります。ポートレットによって使用されるリンクのタイプの詳細は、6.1.2項「ポートレット内のナビゲーションのガイドライン」を参照してください。
Oracle Portalは、ポートレットに自身でレンダリングさせる場合、このポートレットに様々なURLを渡します。ポートレットはこれらのURLを使用して、ポートレット内リンクなど必要なリンクをレンダリングします。これらのURLをフェッチおよび操作することにより、Oracle Portal内のポートレットおよびページの間のリンクを作成するタスクを簡略化できます。
Oracle Portalでは、ポートレットに対して次のURLを提供しています。
PAGE_LINK: ポートレット・インスタンスがあるページのURLです。このURLは、すべてのポートレット内リンクのベースとして使用します。ユーザーを同じポートレットの別のセクションにナビゲートするリンクをポートレットでレンダリングする場合、このナビゲーションは、PAGE_LINKを使用してパラメータ・セットとしてエンコードする必要があります。このURLは、デスクトップ・ポートレットとモバイル・ポートレットの両方で役に立ちます。
DESIGN_LINK: ポートレットのパーソナライズ・ページを示すOracle PortalページへのURLです。Oracle Portalでは、ポートレットの編集モードおよびカスタマイズ・モードはポートレットと同じページ上にはレンダリングされません。編集モードおよびカスタマイズ・モードは、ブラウザ・ウィンドウ全体を占有します。Oracle Portalのポートレットの編集/カスタマイズ・ページには、すべてのユーザーがアクセスできるわけではありません。このページは、ポートレットがそのパーソナライズまたは編集オプションを自由にレンダリングできる最小限の静的フレームワークです。このURLは、デスクトップ・クライアントでのみサポートされている編集およびカスタマイズ・リンクをレンダリングする場合のみ役に立ちます。
LOGIN_LINK: OracleAS Single Sign-On ServerのURLです(ポートレットがユーザーにログインを要求する場合(PUBLICの場合))。このリンクはまれにのみ使用され、ポートレットのデスクトップ・レンダリングにのみ適用されます。
BACK_LINK: ポートレットがそれ自体をレンダリングする現行のページからの有効な戻りポイントとしてOracle Portalが考慮するページへのURLです。たとえば、ポートレットがその「編集」ページをレンダリングする場合、このリンクは、ポートレットがありユーザーが「編集」ページへナビゲートされる元のページを参照します。このため、このリンクは、保留中のアクションを受け入れる、または取り消すボタンにエンコードします。このURLは、ポートレットのデスクトップ・レンダリングでのみ役に立ちます(通常は編集またはカスタマイズ・モード)。モバイル・ポートレットは、ポートレットがそれ自体のコンテンツをレンダリングするままにして、「戻る」リンクを自動的にレンダリングします。
EVENT_LINK: 特定のページに明示的にナビゲートするかわりにイベントを発生させるURLです。このリンクは、イベント・マネージャへのOracle Portalエントリ・ポイントを指し示します。このURLは、デスクトップ・ポートレットとモバイル・ポートレットの両方で役に立ちます。
URLパラメータを使用してリンクを構築するには、ポートレットのレンダリング・コードの作成時にこれらにアクセスして使用する必要があります。リンクのURLをフェッチするには、PDKで次のAPIをコールします。
portletRenderRequest.getRenderContext().getPageURL() portletRenderRequest.getRenderContext().getEventURL() portletRenderRequest.getRenderContext().getDesignURL() portletRenderRequest.getRenderContext().getLoginServerURL() portletRenderRequest.getRenderContext().getBackURL()
ポートレットのナビゲーションの場合、ページURLのポートレット・パラメータを追加(または更新)する必要があります。このタスクを実行するには、次のAPIを使用して適切なURLを構築します。
UrlUtils.constructLink( PortletRenderRequest pr, int linkType, -- UrlUtils.PAGE_LINK in this case NameValue[] params, boolean encodeParams, boolean replaceParams)
UrlUtils
は、oracle.portal.provider.v2.url
と呼ばれるパッケージに含まれています。実際には自分自身でページURLをフェッチすることはありません。かわりに、提供されているポートレットURLタイプの1つであるUrlUtils.PAGE_LINK
を使用します。
params
引数のパラメータ名は完全に修飾されている必要があります。また、パラメータが正しく修飾されていることを前提に、適切なlinkType
を持つUrlUtils.constructLink
が、ポートレットに属さないURLパラメータを妨害していない必要があります。
UrlUtils.contructLink
の代替バージョンは、URLを受け入れて、それを、戻されるURLのベースとします。HTMLリンクが必要な場合、UrlUtils.constructHTMLLink
を使用して完全なアンカー要素を作成できます。
次のポートレット例であるThesaurusLink.jsp
では、パラメータq
を使用して、シソーラスで検索する単語を識別します。次に、見つかった関連単語についてのリンクが作成されます。ユーザーはこのリンクをたどり、この新しい単語に影響するシソーラスを取得します。値q
を設定する初期の実行フォームの詳細は、7.2.3.3.3項「ポートレットのURLタイプを使用したフォームの構築」の例を参照してください。
注意: SimpleResult (モバイル・ポートレット用)の属性をレンダリングする場合、属性値に無効なXML文字が含まれる可能性があるときはこの属性値をエスケープする必要があります。ほとんどのURLには、URLのパラメータ間を区切るために& が含まれます。このため、通常、次を使用してURLが含まれる属性をエスケープする必要があります。
oracle.portal.utils.xml.v2.XMLUtil.escapeXMLAttribute |
<% String paramNameQ = "q"; String qualParamNameQ = HttpPortletRendererUtil.portletParameter(paramNameQ); PortletRenderRequest pRequest = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); String paramValueQ = pRequest.getQualifiedParameter(paramNameQ); %> <!-- Output the HTML content --> <center> Words similar to <%= paramValueQ %> <br> Click on the link to search for words related to that word. <br> <ul> <% String[] relatedWords = Thesaurus.getRelatedWords(paramValueQ); NameValue[] linkParams = new NameValue[1]; for (int i=0; i<=relatedWords.length; i++) { linkParams[0] = new NameValue( qualParamNameQ, relatedWords[i]); %> <li> <b> <%= relatedWords[i] %> </b> <%= UrlUtils.constructHTMLLink( pRequest, UrlUtils.PAGE_LINK, "(words related to " + relatedWords[i] + ")", "", linkParams, true, true)%> </li> <% } %> </ul> </center>
フォームでポートレット・パラメータを使用する方法は、リンクで使用する方法とほとんど違いはありません。次の2つの基本的ルールが同様に適用されます。
ポートレットのパラメータ名を修飾します。
受信URLのその他のパラメータは操作したり削除しません。
マークアップおよび動作の点では、フォームとリンクはかなり異なります。ただし、リンクの場合と同様、PDK-Javaにはこれら2つの基本ルールに準拠するためのユーティリティが含まれています。
ポートレットのパラメータ名を正しく修飾するためのコードは、7.2.3.3.2項「ポートレットのURLタイプを使用したリンクの構築」に記載されているコードと同じです。つまり、ページ上のリンクにしてもフォーム要素の名前にしても、パラメータ名は単なる文字列です。
フォームは、URLのその他のパラメータは変更しないままにする必要があるという点でリンクとは異なります。マークアップでフォームを開いた後、次のAPIの1つを使用できます。
UrlUtils.htmlFormHiddenFields(pRequest,UrlUtils.PAGE_LINK, formName); UrlUtils.htmlFormHiddenFields(someURL);
この場合、formName = UrlUtils.htmlFormName(pRequest,null)
です。
注意: ページに複数のフォームがある可能性があるため、フォーム名は完全に修飾する必要があります。これは、ページ上のその他のポートレットと競合するのを避けるために、URLのパラメータとフォームの要素名に修飾が必要であるのと同様です。 |
htmlFormHiddenFields
ユーティリティは、HTMLの非表示フォーム要素をフォームに書き込みます。この場合、指定したURLの、ポートレットに属さないパラメータごとに1つのフォーム要素を書き込みます。
<INPUT TYPE="hidden" name="paramName" value="paramValue">
このため、開発者は、ポートレットのパラメータをフォームに追加するのみでよいのです。
もう1つ注意が必要なのは、フォームの送信ターゲットを導出する方法です。多くの場合、送信ターゲットは現行のページです。
formTarget = UrlUtils.htmlFormActionLink(pRequest,UrlUtils.PAGE_LINK)
formTarget
の値には、HTMLフォームのアクション属性やSimpleForm
のターゲット属性を使用できます。メソッド名にHTMLが含まれている場合でも、実際にはURLを戻すのみであるため、これはモバイル・ポートレットでも使用できます。
次の例のフォームは、シソーラス・ポートレットの送信フォームをレンダリングします。このフォームの送信結果であるポートレットの詳細は、7.2.3.3.2項「ポートレットのURLタイプを使用したリンクの構築」の例を参照してください。
<% String paramNameSubmit = "submit"; String paramNameQ = "q"; String qualParamNameQ = HttpPortletRendererUtil.portletParameter(paramNameQ); String qualParamNameSubmit = HttpPortletRendererUtil.portletParameter(paramNameSubmit); PortletRenderRequest pRequest = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); String formName = UrlUtils.htmlFormName(pRequest,"query_form"); %> <!-- Output the HTML content --> <center> <b>Thesaurus</b> Enter the word you wish to search for <form name="<%= formName %>" method="POST" action="<%= UrlUtils.htmlFormActionLink(pRequest,UrlUtils.PAGE_LINK) %>"> <%= UrlUtils.htmlFormHiddenFields(pRequest,UrlUtils.PAGE_LINK, formName)%> <table><tr><td> Word of interest: </td><td> <input type="text" size="20" name="<%= qualParamNameQ %>" value=""> </td></tr></table> <input type=submit name="<%= qualParamNameSubmit %>" Value="Search"> </form> </center>
ポートレット内でナビゲーションを実装する方法には、次の3つがあります。
明示的なポートレット・パラメータを使用して、レンダリングされるURLにナビゲーション情報を渡します。このURLに基づいて、ポートレット・コード内のブランチ・ロジックは、どのポートレットのセクションをレンダリングするのかを確認できます。このオプションは、7.2.3.3.2項「ポートレットのURLタイプを使用したリンクの構築」および7.2.3.3.3項「ポートレットのURLタイプを使用したフォームの構築」に示されているシソーラス例を少し拡張したものです。基本的に、このポートレットは、パラメータ値q
を使用してシソーラスの検索動作を実行するのでなく、パラメータ値に基づいて分岐し、これに応じて様々なコンテンツをレンダリングします。
前の項目と同じようにナビゲーション情報を渡します。ただし、PDK-Javaを使用してパラメータを解釈し、その値に基づいて分岐してください。この方法の場合、シソーラスの例をいくらか変更する必要があるため、後でその詳細を説明します。
セッション記憶域を使用してポートレットの状態を記録し、URLパラメータを使用して明示的なナビゲーションではなくアクションを示します。この方法は、ポートレットが含まれるページからユーザーが移動したときにポートレットを前の状態にリストアする唯一の方法です。ユーザーがこのページから移動すると、すべてのポートレット・パラメータは失われ、セッション記憶域にある状態のみをリストアできます。ただし、その状態がセッション記憶域に保管されていることが前提です。このオプションを使用するには、セッション記憶域について理解し、これを実装する必要があります。セッション記憶域の実装の詳細は、7.2.6.2項「セッション記憶域の実装」を参照してください。
次のポートレット・コードは、PDK-Javaのサンプル・プロバイダのマルチページ例の一部です。
<portlet>
<id>11</id>
<name>Multipage</name>
<title>MultiPage Sample</title>
<shortTitle>MultiPage</shortTitle>
<description>
This portlet depicts switching between two screens all
in the context of a Portal page.
</description>
<timeout>40</timeout>
<timeoutMessage>MultiPage Sample timed out</timeoutMessage>
<renderer class="oracle.portal.provider.v2.render.RenderManager">
<contentType>text/html</contentType>
<showPage>/htdocs/multipage/first.jsp</showPage>
<pageParameterName>next_page</pageParameterName>
</renderer>
</portlet>
pageParameterName
の値はポートレット・パラメータnext_page
の名前です。この値は、PDKフレームワークがshowPage
パラメータ値の上書きとして取得および解釈するポートレット・パラメータの名前です。PDKフレームワークは、マルチページ・ポートレットのリクエスト時にパラメータの修飾バージョンを検出すると、first.jsp
ではなくnext_page
によって示されたリソースをレンダリングします。ポートレット内のパラメータは、ポートレットによってレンダリングされるため、PDKではレンダリングされません。
シソーラスの例をこのパラメータで動作するように変更できます。特に、フォーム送信ポートレットをシソーラスの入力用(ポートレットの先頭ページ)として使用し、シソーラス内をさらにドリルダウンしていくためのリンクが含まれる結果ページにユーザーをナビゲートできます。次の例は、これらの変更内容を示します。
注意: 次の例は、このシソーラスの例のように、比較的簡単なケースの場合に最も役に立ちます。ウィザードの使用経験を積む必要があるなど、より込み入った必要性がある場合は、StrutsなどのMVCフレームワークを使用することを検討してください。Strutsアプリケーションからポートレットを構築する方法の詳細は、7.3項「Oracle JDeveloperを使用したStrutsポートレットの作成」を参照してください。 |
ThesaurusForm.jsp
:
<% PortletRenderRequest pRequest = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); String paramNameSubmit = "submit"; String paramNameQ = "q"; String qualParamNameQ = HttpPortletRendererUtil.portletParameter(pRequest, paramNameQ); String qualParamNameSubmit = HttpPortletRendererUtil.portletParameter(pRequest, paramNameSubmit); String formName = UrlUtils.htmlFormName(pRequest,"query_form"); %> <!-- Output the HTML content --> <center> <b>Thesaurus</b> Enter the word you wish to search for <form name="<%= formName %>" method="POST" action="<%= UrlUtils.htmlFormActionLink(pRequest,UrlUtils.PAGE_LINK) %>"> <%= UrlUtils.htmlFormHiddenFields(pRequest,UrlUtils.PAGE_LINK, formName) %> <%= UrlUtils.emitHiddenField( HttpPortletRendererUtil.portletParameter(request, "next_page"), "htdocs/path/ThesaurusLink.jsp" ) %> <table><tr><td> Word of interest: </td><td> <input type="text" size="20" name="<%= qualParamNameQ %>" value=""> </td></tr></table> <input type=submit name="<%= qualParamNameSubmit %>" Value="Search"> </form> </center>
ThesaurusLink.jsp
を指し示すためにnext_page
を明示的に設定する必要がありますので、その方法に留意してください。この方法でnext_page
を明示的に設定しない場合、このパラメータは、provider.xml
に登録されているリソース(ThesaurusForm.jsp
)にデフォルト設定されます。
ThesaurusLink.jsp
:
<% PortletRenderRequest pRequest = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); String paramNameQ = "q"; String paramNameNextPage = "next_page"; String qualParamNameQ = HttpPortletRendererUtil.portletParameter(pRequest, paramNameQ); String qualParamNameNextPage = HttpPortletRendererUtil.portletParameter(pRequest, paramNameNextPage); String paramValueQ = pRequest.getQualifiedParameter(paramNameQ); %> <!-- Output the HTML content --> <center> Words similar to <%= paramValueQ %> <br> Click on the link to search for words related to that word. <br> <ul> <% Thesaurus t = new Thesaurus(); String[] relatedWords = t.getRelatedWords(paramValueQ); NameValue[] linkParams = new NameValue[2]; linkParams[0] = new NameValue( qualParamNameNextPage, "htdocs/path/ThesaurusLink.jsp"); for (int i=0; i<relatedWords.length; i++) { linkParams[1] = new NameValue( qualParamNameQ, relatedWords[i]); %> <li> <b> <%= relatedWords[i] %> </b> <%= UrlUtils.constructHTMLLink( pRequest, UrlUtils.PAGE_LINK, "(words related to " + relatedWords[i] + ")", "", linkParams, true, true)%> </li> <% } %> </ul> <a href="<%=XMLUtil.escapeXMLAttribute (pRequest.getRenderContext().getPageURL())%>"> Reset Portlet </a> </center>
ページの部分的なリフレッシュ
ページ全体をリフレッシュすることなく、ポートレットはそれ自体をリフレッシュできます。たとえば、マルチページ・ポートレット・サンプルでは、子細に説明すると、firstpage.jsp
はAPIを使用して、ポートレットが次のページにリンクし、ポータル・ページ全体をリフレッシュさせずに次のページを表示できるようにします。次の例の太字のテキストは、これをどのように設定できるのかを示しています。
<%@ page contentType="text/html;charset=Shift_JIS" %>
<%@ page language="java" session="false" %>
<%@ page import="oracle.portal.provider.v2.url.UrlUtils" %>
<%@ page import="oracle.portal.provider.v2.render.http.HttpPortletRendererUtil" %>
<%@ page import="oracle.portal.provider.v2.render.PortletRenderRequest" %>
<%@ page import="oracle.portal.provider.v2.http.HttpCommonConstants" %>
<%@ page import="oracle.portal.utils.NameValue" %>
<%
PortletRenderRequest prr = (PortletRenderRequest)
request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
NameValue[] linkParams = new NameValue[1];
linkParams[0] = new NameValue(HttpPortletRendererUtil.portletParameter(request,
"next_page"), "/htdocs/multipage/second.jsp");
%>
<center>
Hello, this is the first page<p>
<%=UrlUtils.constructHTMLLink(prr, UrlUtils.REFRESH_LINK, "second page", "", linkParams, true, true)%>
</center>
前述の項では、パラメータを受信するポートレットを作成しました。次に、パラメータおよびイベントを、同じページまたは別のページの他のポートレットに渡すポートレットを作成します。OmniPortletのシンプル・パラメータ・フォームのように、パラメータを他のポートレットに渡すシンプル・フォームを作成するための簡単で宣言的なインタフェースを提供するポートレットもあります。ただし、渡されるイベントやポートレットの外観を完全に制御する必要がある場合は、イベントをJavaポートレットに追加できます。
ポートレット・ウィザードでは、パラメータを他のポートレットに渡すために必要なすべてのコードが作成されるわけではありません。ウィザードではprovider.xml
のタグが更新され、開発者は必要なビジネス・ロジックをJSPコードに追加する必要があります。イベントを使用するポートレットを作成するには、次のタスクを実行します。
ポートレット・ウィザードを使用して、新しいポートレットを作成します。
コードをJSPページに追加します。
このポートレットのパラメータを、7.2.3.2項「パブリック・パラメータの追加」で作成したポートレットにマップします。
イベント・ポートレットの作成
イベント・ポートレットを作成する手順は、次のとおりです。
ポートレット・ウィザードを起動して、7.2.3.2項「パブリック・パラメータの追加」でパラメータ・ポートレットに使用したのと同じプロバイダにMyEventsPortlet
という新しいポートレットを作成します(図7-6)。通常どおりにウィザードを進めます。ウィザードのステップ5で、パラメータを作成します。ウィザードのステップ6で、表7-1に示す情報を入力します。
表7-1 イベント
イベント領域 | 名前 | 表示名 | 説明 |
---|---|---|---|
公開されるイベント |
MyEvent |
My Event |
This is my event. |
関連付けられたパラメータ |
MyParam |
My Parameter |
This is my parameter |
ウィザードによって、次のコードがprovider.xml
に生成されます。
注意: 次の例では、入力パラメータとイベント・パラメータの名前がいずれもMyParam になっていることに注意してください。これらは、名前が同じでも異なるパラメータです。 |
<showDetails>false</showDetails> <inputParameter class="oracle.portal.provider.v2. DefaultParameterDefinition"> <name>MyParam</name> <displayName>My Parameter</displayName> </inputParameter> <event class="oracle.portal.provider.v2.DefaultEventDefinition"> <name>MyEvent</name> <displayName>My Event</displayName> <parameter class="oracle.portal.provider.v2.DefaultParameterDefinition"> <name>MyParam</name> <displayName>My Parameter</displayName> </parameter> </event> <renderer class="oracle.portal.provider.v2.render.RenderManager">
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
必要な次のクラスをMyEventsPortlet
にインポートします。
oracle.portal.provider.v2.event.EventUtils
oracle.portal.utils.NameValue
oracle.portal.provider.v2.url.UrlUtils
MyEventsPortlet
に、パラメータ値を別のポートレットに渡すリンクを追加します。次のサンプル・コードに示すように、前のポートレットと同じページ・パラメータを受信しますが、それに加えてイベントを渡すリンクも作成します。
<%@page contentType="text/html; charset=windows-1252" import="oracle.portal.provider.v2.render.PortletRenderRequest" import="oracle.portal.provider.v2.http.HttpCommonConstants" import="oracle.portal.provider.v2.ParameterDefinition" import="oracle.portal.provider.v2.event.EventUtils" import="oracle.portal.utils.NameValue" import="oracle.portal.provider.v2.url.UrlUtils" %> <% PortletRenderRequest pReq = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); %> <% NameValue[] parameters = new NameValue[2]; parameters[0] = new NameValue( EventUtils.eventName("MyEvent"),""); parameters[1] = new NameValue(EventUtils.eventParameter("MyParam"),pReq.getParameter ("MyParam")); %> <span class="portletText1"><br> <a href="<%= UrlUtils.constructLink (pReq, pReq.getRenderContext().getEventURL(), parameters , true, true)%>"> The value of the stock is <%= pReq.getParameter("MyParam") %> </a> <br><br></span>
注意: このサンプル・コードでは、NULL値を処理していません。ポートレットを最初にページに追加する際にエラーが発生する場合がありますが、ポートレットをページ・パラメータにマップすると正常に機能します。 |
ポートレットを、前のポートレット(パラメータ・ポートレット)以外の別のページ(同じページ・グループ内)に追加します。ポートレットを開き、前のポートレットと同じパラメータを受信するようにマップします。
My Parameter = Page Parameter MyParameter
「パラメータ」タブで変更内容を適用し、「イベント」タブに移動します。イベント・ポートレットを開き、イベントを選択します。「ページに移動」を選択し、イベントを渡すページを検索します。パラメータ・ポートレットが存在するページを選択します。図7-7に示すように、イベントをページ・パラメータMyParameter
として渡すように、このポートレットを構成します。
MyParameter = Event Output MyParameter
「OK」をクリックすると、ページが表示されます。イベント・ポートレットには、ページから受信した値を表示するリンクが表示されます(図7-8)。
パラメータ値をURLに追加すると、ポートレットのリンクにその値が表示されます。
&MyParameter=20
リンクをクリックすると、その値がページのパラメータ・ポートレットに渡されます(図7-9)。
Javaポートレットを作成する場合、JNDIサービスを介して、デプロイ固有のプロパティを設定できます。これにより、これらの値がプロバイダ・コードから取得されるようにできます。この方法により、プロバイダ・デプロイに任意のプロパティを指定し、プロバイダ・コード内の任意の場所からこのプロパティに簡単にアクセスできます。PDK-Javaには、J2EEコンテナ内のプロバイダJNDI変数と非プロバイダJNDI変数の両方を取得するためのユーティリティが用意されています。JNDI変数を使用するには、次のタスクを実行する必要があります。
JNDI変数は、プロバイダのweb.xml
ファイルで宣言します。JNDI変数を宣言するための書式は、次のとおりです。
<env-entry> <env-entry-name>variableName</env-entry-name> <env-entry-type>variableType</env-entry-type> <env-entry-value>variableValue</env-entry-value> </env-entry>
env-entry-name
要素にはこの変数を識別する名前が含まれます。env-entry-type
にはこの変数の完全修飾されたJava型が含まれます。env-entry-value
にはこの変数のデフォルト値が含まれます。
env-entry-type
要素では、Javaコードによって予期される、完全に修飾されたJava型変数を指定する必要があります。JNDI変数で使用可能なJava型は、次のとおりです。
java.lang.Boolean
java.lang.String
java.lang.Integer
java.lang.Double
java.lang.Float
J2EEコンテナは、これらの型宣言を使用して、指定された型のオブジェクトを自動的に構成し、コード内で変数を取得するときに、指定された値をオブジェクトに設定します。
PDK-Javaは、個々のプロバイダ・サービス・レベルまたはWebアプリケーション・レベルで設定可能な環境変数をいくつか定義します。同じWebアプリケーションにパッケージ化されている様々なプロバイダ・サービスやアプリケーション・コンポーネントの間で命名が競合しないようにするには、特定の命名規則を策定することをお薦めします。
注意: EnvLookup メソッドを使用する場合、oracle/portal/provider/service/property を使用する必要があります。この場合、独自の会社名またはコンポーネントで代用することはできません。 |
次に例を示します。
プロバイダ・サービス固有名の書式は、次のようにする必要があります。
{company}/{component name}/{provider name}/{variable name}
共有名の書式は、次のようにする必要があります。
{company}/{component name}/{provider name}/global
これらの意味は、次のとおりです。
{company}
: アプリケーションを所有する会社名です。
{component name}
: プロバイダが関連付けられているアプリケーションまたはコンポーネントの名前です。
{provider name}
: プロバイダのサービス名です。
{variable name}
: 変数自体の名前です。
これらの命名規則は、Javaパッケージに使用されている命名規則と似ています。この方法により、アプリケーションまたはアプリケーション・コンポーネントの間で名前が衝突する可能性を最小限に抑えることができます。PDK-Javaには、プロバイダのサービス名をサーブレットまたはJSPにハードコーディングせずにこの書式の変数を取得するためのユーティリティが用意されています。このサービス名は、プロバイダのWARファイルに定義しておくのみでよいのです。JNDI変数の取得方法は、7.2.4.3項「JNDI変数の取得」を参照してください。
プロバイダ・デプロイでは、JNDI変数の一部またはすべてに対して新しい値を設定できます。このタスクは、Oracle WebLogic Serverのデプロイ・プランで以下のように値を手動で設定することで実行できます。
Oracle WebLogic管理コンソールで「プロバイダのデプロイ」に移動し、設定がまだであれば新しいデプロイ・プランを作成します。
デプロイ・プランのXMLファイルを編集します。設定するデプロイのプロパティごとに、次の変数定義を<deployment-plan>タグの直下に追加します。
<variable-definition> <variable> <name>jndi_var_def</name> <value>false</value> </variable> </variable-definition>
この変数定義を設定する実際のJNDI変数に結びつけるには、WEB-INF/web.xmlモジュール記述子(oracle/portal/sample/rootDirectoryを例として使用します)の下の各プロパティで以下を実行します。
<module-descriptor external="false"> <root-element>web-app</root-element> <uri>WEB-INF/web.xml</uri> <variable-assignment> <name>jndi_var_def</name> <xpath>/web-app/env-entry/[env-entry-name="oracle/portal/sample/rootDirectory"]/env-entry-value</xpath> </variable-assignment> </module-descriptor>
ファイルを保存します。
プロバイダのデプロイで「更新」を選択し、新しい設定のデプロイ・プランを有効にします。
JNDIは、標準的なJ2EEテクノロジです。このため、JNDI変数にはJ2EE APIを介してアクセスできます。次に例を示します。
String myVarName = "oracle/portal/myProvider/myVar"
String myVar = null;
try
{
InitialContext ic = new InitialContext();
myVar = (String)ic.lookup("java:env/" + myVarName);
}
catch(NamingException ne)
{
exception handling logic
}
基本的なJ2EE API以外にも、PDK-Javaには、PDK自体によって定義および使用される変数値を取得するための簡素なユーティリティ・クラスが用意されています。これらの変数はすべて、7.2.4.1.2項「変数の命名規則」で説明されている命名規則に準拠しており、その書式は次のとおりです。
oracle/portal/provider_service_name/variable_name oracle/portal/variable_name
これらのAPIを使用するには、provider_service_name
およびvariable_name
を指定するのみでよいのです。このユーティリティは、指定された情報に基づいて完全なJNDI変数名を構成し、前に示したものと類似のコードを使用して変数を参照し、変数値を戻します。
EnvLookup
クラス(oracle.portal.utils.EnvLookup
)には、2つのlookup()
メソッドがあります。1つはプロバイダ変数を取得し、もう1つは非プロバイダ変数を取得します。どちらのメソッドもjava.lang.Object
を戻します。これは、目的のJava型にキャストできます。
次のコード例では、プロバイダ変数を取得しています。
EnvLookup el = new EnvLookup(); String s = (String)el.lookup(myProviderName, myVariableName);
変数名のうち、myProviderName
は、プロバイダのサービス名を示す部分です。変数名のうち、このプロバイダのサービス名の後ろに続く部分がmyVariableName
です。この例では、取得される変数の型がjava.lang.String
であると想定しています。
非プロバイダ変数を取得するには、同じコードを使用し、1つのパラメータ、変数名のみをlookup()
に渡します。また、この場合、接頭辞oracle/portal
は除きます。
EnvLookup el = new EnvLookup();Object o = el.lookup(myVariableName);
表7-2は、デフォルトでPDK-Javaに用意されているJNDI変数を示します。これらの変数を宣言しない場合、PDK-Javaは、元の場所(web.xml
およびデプロイ・プロパティ・ファイル)でこれらの値を検索します。
表7-2 PDK-JavaのJNDI変数
変数 | 説明 |
---|---|
oracle/portal/provider/provider_name/autoReload
|
ブール型の自動リロード・フラグ。デフォルト値はtrue。 |
oracle/portal/provider/provider_name/definition
|
プロバイダの定義ファイルの場所。 |
oracle/portal/provider/global/log/logLevel |
ログ設定(0〜8)。0はロギングなし、8は最大限のロギング。 |
oracle/portal/provider/provider_name/maxTimeDifference
|
プロバイダのHMAC時間差。 |
oracle/portal/provider/<service_name>/resourceUrlKey |
Parallel Page Engineによるリソースのプロキシ化の認証キー。詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。 |
oracle/portal/provider/provider_name/rootDirectory
|
プロバイダのパーソナライズの場所。デフォルト値はなし。 |
oracle/portal/provider/provider_name/sharedKey
|
HMAC共有キー。デフォルト値はなし。 |
oracle/portal/provider/provider_name/showTestPage
|
(非プロバイダ)プロバイダのテスト・ページにアクセス可能どうかを決定するブール型フラグ。デフォルト値はtrue。 |
oracle/portal/provider/global/transportEnabled |
「デフォルトの編集」のパーソナライズをエクスポートおよびインポート可能かを決定するブール型フラグ。詳細は、7.2.8.3.2項「パーソナライズのエクスポート/インポートの無効化」を参照してください。 |
トランザクションとレンダリングを同時に実行するのではなく、トランザクションを完了してからそのトランザクションがあるページをレンダリングする方が、ポートレットにとって都合がよい場合があります。たとえば、ポートレットにデータ値を更新するリンクがあり、その更新はページ上の他のポートレットに影響を与える可能性があるとします。ページのリフレッシュによって同時にトランザクションも実行されると、そのデータ値に依存する他のポートレットは最新の値でリフレッシュされる場合と、されない場合があります。さらに、トランザクションとレンダリングがこのように結び付けられると、ブラウザでユーザーが「戻る」を押すなどの操作によって、トランザクションが繰り返され、レコードが重複して作成されるなどの可能性があります。
JSPポートレットでは、processAction
メソッドを使用してこの問題を解決できます。このメソッドを使用すると個々のポートレットは、ページのレンダリングが行われる前に、値の更新などのトランザクションを完了できます。PDK-JavaにはprocessAction
がありませんが、別のメカニズムを使用してサーブレットにデータを送信することにより、同じ結果を得ることができます。ページ・フローおよびポートレットの制御にStrutsを使用している場合は、form
タグおよびトランザクション・トークンを使用して、同じパラメータが2回送信されないようにすることができます。Strutsポートレットの詳細は、7.3項「Oracle JDeveloperを使用したStrutsポートレットの作成」を参照してください。
別の方法として、共有画面モードではなく、編集モードでデータを送信することもできます。編集モードなど、フル・ページ表示モードに基づくリクエストは、リンクを生成したポートレットにのみ送信されます。同じポータル・ページの他のポートレットはレンダリング・リクエストに気付くこともありません。このため、このようなフル・ページ表示モードを使用すると、ページおよびその他のポートレットと切り離してポートレットのトランザクションを実行できます。
ポートレットの送信を実行した後は、戻りURLを使用してフル・ページ表示モードからページにリダイレクトします。この操作により、次の2つの効果を得ることができます。
ユーザーは元のページに戻ります。
フォーム送信のすべてのトレースをブラウザから消去します。
この結果、データ送信処理の後にすべてのページ・リフレッシュが行われることが保証されます。ページ・リフレッシュは送信後に行われるので、ページ上のすべてのポートレットは更新後のデータにアクセスし、送信の重複は発生しないことになります。
この手法は、プライベート・イベント送信ポートレットというPDK内のサンプル・ポートレットで説明されています。これは、ポートレットに単純なフォームを送信し、フォームのコンテンツのログを記録する処理を示します。プライベート・イベント送信ポートレットでは、データ送信とパーソナライズのためのポートレット・レンダリングの両方を扱うように、編集モードをオーバーロードします。どのフル・ページ表示モード(編集、ヘルプ、情報およびデフォルトの編集)でもこの目的に関して同じ効果が得られます。
このポートレットの編集モードには、最初に特定のパラメータを探す追加コードが含まれています。このパラメータが存在する場合は、リクエストはプライベート・イベントを表すことになります。パラメータを識別するために様々な値を使用して、同じモードで多数の様々なプライベート・イベントを扱うことができます。識別パラメータが存在しない場合は、編集モードは標準のポートレット・パーソナライズ・ロジックになります。
プライベート・イベントを処理した後は、このモードはユーザーが「OK」をクリックしたときに編集モードが使用するものとまったく同じロジックを使用して、ページにリダイレクトされます。この手法を示す完全なソース・コードは、サンプル・ファイルのEditServlet.java
を参照してください。
注意: この手法を使用するときは、イベントの詳細情報が永続化されている必要があります。ポートレット・レンダリングはイベント・プロセスと同じリクエスト・サイクルで起こらないので、ポートレットをレンダリングするために必要なイベントのすべてのデータは、ストレージから入手できる必要があります。そうしないと、次にレンダリングするときに、必要なデータがポートレットまたはページにない場合があります。データを永続化する必要がある場合は、(ユーザー・リファレンスおよびポートレット・リファレンスで)修飾した形式で格納します。修飾されていないと、あるユーザー/ポートレットからのイベントが、誤って別のページで別のユーザーの同じポートレットのレンダリングと関連付けられたり、同じユーザー/同じポートレットが同じページ上の別のポートレット・リファレンスと関連付けられたりする可能性があります。 |
ユーザーがポータル・ページにアクセスすると、Oracle Portalは、パブリックな未認証のセッションを起動してCookieを保持し、そのセッションに関する情報を複数のリクエストにわたって追跡します。ユーザーがOracle Portalにログインすると、このセッションはログイン・ユーザーの認証済セッションとなります。このポータル・セッションは、次の場合に終了します。
ブラウザ・セッションが終了したとき(つまり、ユーザーがすべてのブラウザ・ウィンドウを閉じたとき)
ユーザーが明示的にログアウトしたとき
ユーザーのアイドル時間が設定時間を超えたためにセッションがタイムアウトしたとき
そのポートレットをページに提供したプロバイダが、自分がなんらかの特別な処理のためにコールされるように登録時に指定している場合、Oracle Portalはメタデータ生成の一環として、プロバイダすべてに連絡します。このコールにより、プロバイダは、ユーザー・セッションに基づいて処理を行い、必要に応じてプロバイダのアプリケーションのユーザーをログに記録し、Oracle Portalでプロバイダ・セッションを確立できるようになります。データベース・プロバイダの場合、このコールの名前はdo_login
であり、Webプロバイダの場合はinitSession
です。Web対応型アプリケーションの大部分はCookieを使用してセッションを追跡するため、アプリケーションのプロバイダはCookieを戻すのにこのAPIコールを利用できます。
セッション・ストアを使用すると、ポータル・セッションの間存続する情報を保存および取得できます。この情報が有効で使用可能なのは、そのセッションの存続期間中のみです。セッション・ストアに格納するのは、一時情報のみです。アプリケーション開発者はこのセッション・ストアを使用して、現行のユーザー・セッションに関する情報を格納できます。セッション・ストアのデータは複数のポートレット間で共有できます。
格納する情報を複数のセッションにわたって存続させる必要がある場合は、セッション・ストアのかわりにプリファレンス・ストアに格納できます。一般的なセッション・ストアの適用例を次に示します。
ロードや演算にコストがかかるデータ(たとえば、検索結果)をキャッシュする場合。
ポートレットの現在の状態(たとえば、ポートレットに表示された検索結果の現在の範囲(ページ)やユーザーが実行したイベントの順序)をキャッシュする場合。
セッション記憶域を実装する前には、パフォーマンス・コストを慎重に検討する必要があります。ポートレットとプロバイダはリモートであるため、セッション・ストアに情報を作成して保持する操作は、少ない情報量であっても比較的コストがかかる可能性があります。このため、多数のユーザーが頻繁にアクセスするパブリック・ページについては、セッション記憶域の実装を避けた方がよい場合があります。
スケーラビリティに重要な関心がある場合、ステートフルなアプリケーションは問題発生の原因となる可能性があります。ステートフルなアプリケーションは、使用しているOracle Portal構成のロード・バランシングとフェイルオーバー・メカニズムに影響を与えることがあります。これは、同じOracle Portalインスタンスにアクセスする複数の中間層をデプロイしても、状態を追跡するためには面倒なルーティング(同じノードが後続のリクエストを同じセッションで処理する)を実装する必要があるためです。このルーティングによって、ノードがクラッシュした場合に不均衡なロード・バランスやセッション・データの消失が発生し、フェイルオーバーに影響を与えることがあります。多くの開発者がステートレスなアプリケーションの構築を選ぶ理由の1つはここにあります。ただし、スケーラビリティが問題でない場合、ステートフルなアプリケーションによる問題は発生しません。
この項の例では、共有画面モードでポートレットをレンダリングした回数をカウントするために、セッション記憶域を使用します。
この項のタスクを実行するには、次の前提が必要です。
6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」を読んで理解していること。
ウィザードで作成したポートレットがページに正常に追加されていること。
PDKフレームワークでは、セッションをProviderSession
オブジェクトを使用して表します。このオブジェクトはプロバイダ・インスタンスのinitSession
メソッドへのコールの際に確立されます。このオブジェクトは、ProviderUser
と関連付けられています。Oracle Portalからのリクエスト間でデータを永続的に保持するには、ProviderSession
オブジェクト上のsetAttribute
メソッドを使用してセッション・オブジェクトにデータを書き込む必要があります。このメソッドはjava.lang.Object
をjava.lang.String
にマップし、そのマッピングをセッション・オブジェクト内に格納します。String
は、その後、セッションがまだ有効である場合、後続のリクエスト中にObject
を取得するために使用できます。
次のような場合は、プロバイダ・セッションが無効になることがあります。
セッションがタイムアウトした場合
ProviderSession
上のinvalidate
メソッドがコールされた場合
サーブレット・コンテナを実行中のJVMプロセスが終了した場合
同じProviderInstance
に含まれるすべてのポートレットは、特定のProviderUser
に対して同じセッションを共有します。したがって、特定のポートレット・インスタンスに対して一意のデータは、セッション内の一意のString
にマップする必要があります。これは、PortletRendererUtil
クラス内のportletParameter
メソッドを使用して行います。このメソッドは、そのインスタンス用に生成された識別子を先頭に付けることで、提供されたString
パラメータまたは属性名をPortletInstance
に対して一意にします。戻されたインスタンス固有の名前を使用すると、セッションにポートレット・インスタンス・データを書き込むことができます。
PDKフレームワーク・クラスの詳細は、次の「Portlet Development」ページの「Java Doc API」をクリックして、OTNのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/portlet_development_10g1014.html
セッション記憶域を実装するには、次のタスクを実行する必要があります。
ProviderSession
、PortletRendererUtil
およびHttpPortletRendererUtil
をインポートします。
プロバイダ・セッションを取得します。
Javaポートレット内からセッションにアクセスして、セッションの読取りと書込みを行います。
provider.xml
でsessionをtrueに設定します。
セッション記憶域のプロバイダを登録し、「ログイン頻度」を設定します。
次に、現行セッションでポートレットがレンダリングされた回数を表示するセッション・カウントをポートレットに追加する手順を説明します。
ウィザードを使用してポートレットを作成した後は、Oracle JDeveloperの「表示」ページのJSPを編集できます。次のクラスをインポートする必要があります。
<%@page contentType="text/html; charset=windows-1252" import="oracle.portal.provider.v2.render.PortletRenderRequest" import="oracle.portal.provider.v2.http.HttpCommonConstants" import="oracle.portal.provider.v2.ProviderSession" import="oracle.portal.provider.v2.render.PortletRendererUtil" import="oracle.portal.provider.v2.render.http.HttpPortletRendererUtil" %>
最初に有効なセッションをチェックし、次にカウントを増分して表示するコードを挿入します。セッションが有効で、以前に格納した値が存在する場合は、その値を表示し、カウントを増分して新しい値を格納します。セッションは有効だが以前に格納した値がない場合は、カウントを1に初期化し、その値を表示して格納します。また、このポートレットの一意の文字列キーを取得し、その文字列キーを配列で使用してセッションをカウントできます。セッション情報を受信していない場合は、ユーザーに対して、再度ログインが必要であることを示す情報を提供できます。
<% PortletRenderRequest pReq = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); ProviderSession pSession = pReq.getSession(); if (pSession != null) { String key = PortletRendererUtil.portletParameter(pReq, "count"); Integer i = (Integer)pSession.getAttribute(key); if (i == null) { i = new Integer(0); } i = new Integer(i.intValue()+1); pSession.setAttribute(key, i); %> <p>Render count in this session: <%=i%> </p> <% } else { %> <p>The session has become invalid</p> <br> Please log out and log in again. <% } %>
デフォルトでは、ウィザードでprovider.xml
のsessionをtrueに設定することはありません。プロバイダがポータルからセッション情報を受信するためには、このフラグを更新する必要があります。このタグをtrueに設定する必要があるのは、プロバイダまたはポートレットでセッション情報を使用する場合のみです。このフラグをtrueに設定すると、プロバイダ・コールに余分なロードが追加されます。
<provider class="oracle.portal.provider.v2.DefaultProviderDefinition">
<session>true</session>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
Oracle Portalでプロバイダを登録します。ウィザードの「接続の定義」ページで、「ユーザー」ラジオ・ボタンを選択し、「ログイン頻度」として「セッションごとに1回」を選択します。ポートレットの登録方法に関する注意は、6.5.5項「Oracle PDK-Javaポートレットの登録と表示」を参照してください。
この項では、Javaポートレットで使用できるセキュリティ・サービスについて説明します。
この項で参照されているPDKクラスの詳細は、次の「Portlet Development」ページの「Java Doc API」をクリックして、OTNのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/portlet_development_10g1014.html
この項のタスクを実行するには、次の前提が必要です。
6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」を読んで理解していること。
ウィザードで作成したポートレットがページに正常に追加されていること。
この項では、ポートレット・プロバイダの保護に使用できる主な機能について説明します。
ユーザーが初めてOracle Portalインスタンスにログインするときは、IDを確認してアクセス権限を取得するためにパスワードを入力する必要があります。この認証は、OracleAS Single Sign-On Serverで実行されます。詳細は、7.2.7.3項「シングル・サインオン」を参照してください。
ユーザーのIDが示されたリクエストでプロバイダに渡されると、プロバイダのコードは、HttpServletRequest
オブジェクトから入手可能なPortletRenderRequest
からの認証済みユーザーIDにアクセスできます。
PortletRenderRequest pr = (PortletRenderRequest)request.getAttribute (HttpCommonConstants.PORTLET_RENDER_REQUEST); String userName = pr.getUser().getName();
詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
認可によって、特定のユーザーがポートレットの表示または対話を行えるかどうかが判断されます。Oracle Portalには、次の3種類の認可チェックが用意されています。
Portalアクセス制御リスト(ACL): OracleAS Single Sign-On Serverによって認証されると、Oracle PortalではACLを使用して、フォルダやポートレットなどのポータル・オブジェクトに対して操作を実行するユーザー権限を決定します。ユーザーの操作の範囲は、単なるオブジェクトの表示から、そのオブジェクトに対する管理機能の実行にまで及びます。特定の権限が付与されているグループに属していない場合、Oracle Portalでは、その権限に関連付けられている操作を実行できません。詳細は、7.2.7.4項「Oracle Portalアクセス制御リスト(ACL)」を参照してください。
プログラムによるポートレットのセキュリティ: プログラムによって独自のセキュリティ・マネージャを実装することも可能です。詳細は、7.2.7.5項「ポートレットのセキュリティ・マネージャ」を参照してください。
これまでに説明したユーザー認証と認可では、プロバイダが受信したメッセージの信頼性までは確認されません。以下の方法を使用して、ポータルとWebプロバイダ間の通信を適切に保護できます。
Oracle Portalサーバー認証では、プロバイダへのアクセスを少数の認証されているマシンに制限します。この方法では、受信したHTTPメッセージのIPアドレスまたはホスト名をトラステッド・ホストのリストと比較します。リストにIPアドレスまたはホスト名がある場合、メッセージはプロバイダに渡されます。リストにないと、そのメッセージはプロバイダに達する前に拒否されます。詳細は、7.2.7.6項「Oracle Portalのサーバー・セキュリティ」を参照してください。
メッセージ認証では、共有キーを使用してPortalクライアントのIDをアサートし、メッセージの改ざんを防止します。詳細は、7.2.7.7項「メッセージ認証」を参照してください。
メッセージの暗号化は、メッセージの内容を暗号化します。詳細は、7.2.7.8項「HTTPS通信」を参照してください。
ユーザー入力のエスケープでは、Oracle PortalはXSS攻撃から保護するために、ユーザーが入力した任意の文字列をエスケープし、テキストのみとして処理します。XSS攻撃では、攻撃者はユーザー入力フォームを介して悪意のあるスクリプトで渡そうとします。詳細は、7.2.7.10項「ユーザー入力のエスケープ」を参照してください。
通信セキュリティの詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
ポートレットは、アプリケーションへのウィンドウの役目を果します。ポートレットにはサマリー情報が表示され、アプリケーションのすべての機能にアクセスする方法が提供されます。ポートレットは、アプリケーションの機能をポータルで直接公開したり、タスクを実行するためにアプリケーション自体にアクセスできる深いリンクを提供します。
アプリケーションでは、ポートレットを介してアプリケーションにアクセスするユーザーを認証する必要があります。次のアプリケーション認証方法があります。
7.2.7.3.1項「パートナ・アプリケーション」。この認証方法では、アプリケーションのユーザーは、Oracle Portalの認証ユーザーと同じです。
7.2.7.3.2項「外部アプリケーション」。この認証方法では、Oracle Portalユーザーとアプリケーションのユーザーは異なりますが、アプリケーションのユーザー名とパスワードはOracle Portalユーザーが管理します。
7.2.7.3.3項「アプリケーションによる認証がない場合」。この場合、プロバイダとOracle Portal間の通信はまったく保護されません。
シングル・サインオンの詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
パートナ・アプリケーションは、認証のためにOracle Portalと同じOracleAS Single Sign-On Serverを共有するアプリケーションです。したがって、ユーザーがOracle Portalにすでにログインしているときは、再度ログインしなくてもそのIDがパートナ・アプリケーションにアサートされます。
パートナ・アプリケーションは、OracleAS Single Sign-On Serverと密接に統合されています。ユーザーがパートナ・アプリケーションへのアクセスを試みると、パートナ・アプリケーションはそのユーザーの認証をOracleAS Single Sign-On Serverに委任します。あるパートナ・アプリケーションに対してユーザーが認証される(有効なユーザー名とパスワードを入力する)と、そのユーザーは、同じOracleAS Single Sign-On Serverインスタンスを共有している他のパートナ・アプリケーションにアクセスするときにユーザー名やパスワードを入力する必要がありません。OracleAS Single Sign-On Serverでは、ユーザーが正常に認証されたと確認し、認証が成功したことを他のパートナ・アプリケーションに示します。
パートナ・アプリケーションの利点は次のとおりです。
Oracle PortalとOracleAS Single Sign-On Serverを最も密接に統合できます。
ユーザーはシングル・サインオンを最も有効に利用できます。
Oracle Portalとプロバイダ間ではユーザー名やパスワードが転送されないため、最もセキュアな形式で統合できます。
パートナ・アプリケーションの不利な点は次のとおりです。
アプリケーションのユーザー・コミュニティがOracle Portalのユーザー・コミュニティの一部である可能性があっても、アプリケーションはOracle Portalと同じユーザー・リポジトリを共有する必要があります。この点は考慮する必要がありますが、そのアプリケーションを公開するポータル・ページへのアクセスをアプリケーションのユーザー・コミュニティに簡単に制限できるため、この問題は重大ではありません。
アプリケーションを1つ以上のOracleAS Single Sign-On Serverインスタンスと密接に統合できるのは、それらのインスタンスが同じユーザー・リポジトリを共有している場合のみです。
アプリケーションは、認証をOracleAS Single Sign-On Serverに委任するように作成する必要があります。
アプリケーションのソース・コードへのアクセス権限が必要です。
外部アプリケーションでは、Oracle Portalとは異なる認証サーバーを使用します。このアプリケーションでは、Oracle Portalが使用するのとは別のOracleAS Single Sign-On Serverインスタンスまたは他の認証方法を使用できます。ただし、OracleAS Single Sign-On Serverでは、そのユーザーについて、外部アプリケーションのユーザー名とパスワードが格納されます。これは、ユーザーがOracle Portalにすでにログインしている場合、そのユーザーはユーザー名やパスワードを入力しなくても外部アプリケーションにログインできることを意味します。
ユーザーの認証を管理しているアプリケーションは、管理者がそのアプリケーションを外部アプリケーションとして登録している場合、OracleAS Single Sign-On Serverと柔軟に統合できます。以前にOracleAS Single Sign-On Serverによって認証されたユーザーが初めて外部アプリケーションにアクセスすると、OracleAS Single Sign-On Serverでは、その外部アプリケーションを使用してユーザーの認証を試みます。認証プロセスでは、そのアプリケーションの登録情報と、ユーザーのユーザー名とパスワードとを結合するHTTPリクエストが送信されます。ユーザーがまだその外部アプリケーションのユーザー名とパスワードを登録していない場合、OracleAS Single Sign-On Serverでは、認証リクエストを行う前に、必要な情報の入力をユーザーに要求します。ユーザーが外部アプリケーションのユーザー名とパスワードを入力すると、OracleAS Single Sign-On Serverでは新しいユーザー名とパスワードがユーザーのOracle Portalのユーザー名にマップされ、格納されます。格納された情報は、次回ユーザーが外部アプリケーションによる認証が必要なときに使用されます。
外部アプリケーションの利点は次のとおりです。
多数のポータルとの統合が可能です。ただし、優先するポータルがある場合は、アプリケーションをその優先ポータルのパートナ・アプリケーションとして統合し、他のポータルの外部アプリケーションとして統合できます。
ユーザーはシングル・サインオンを利用できます。ただし、ユーザーは異なるユーザー名やパスワードを保持する必要があります。さらに、外部アプリケーションのユーザー名のマッピングも保持する必要があります。
ユーザー・リポジトリおよびOracleAS Single Sign-On Serverに依存せずに、複数のポータルと統合できます。
アプリケーションのソース・コードへのアクセス権限が不要です。
外部アプリケーションの不利な点は次のとおりです。
ポータルと同じユーザー・リポジトリを共有しません。このため、エンド・ユーザーによるユーザー情報の管理が必要です。
ユーザー名とパスワードは、SSLを実装しないかぎり、プレーン・テキストでプロバイダに送信されます。
Oracle Portalインスタンスにログインすると、OracleAS Single Sign-On Serverインスタンスによって認証が行われます。IDを確認した後、Oracle Portalは、ACLを使用して、特定のポートレットへのアクセスが認可されているかどうかを確認し、そのポートレットをポートレット・リポジトリからページに追加します。
Oracle Portal ACLは、次のセキュリティ特性に従って使用されます。
権限は、権限が付与されているオブジェクトに対して実行できる操作を定義します。権限には、管理や実行などの操作が含まれます。
Oracle Portalのユーザーとその権限は、ビルダーの「管理」タブで付与されます。
Oracle Portalのユーザー・グループは、Oracle Portalビルダーの「管理」タブで管理されます。グループ内のメンバーシップとそのグループに付与されている権限は、すべてこのタブで定義および保持されます。ユーザー・グループに付与された権限は、そのグループのすべてのユーザーによって継承されます。
プロバイダの権限は、プロバイダとそのすべてのポートレットに適用されます。プロバイダのACLは、Oracle Portalナビゲータの「プロバイダ」タブで管理されます。
ポートレットの権限によって、ポートレットのプロバイダに設定された権限を上書きできます。ポートレットのACLは、Oracle Portalナビゲータの「プロバイダ」タブで管理されます。プロバイダについて「開く」をクリックすると、そのプロバイダのポートレットを管理するページが表示されます。
Oracle Portalのオブジェクト、ユーザーおよびユーザー・グループに使用できる権限の詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
ACLの利点は次のとおりです。
ACLは、Oracle Portalオブジェクトを保護するための簡単かつ強力なメカニズムを備えています。
ユーザー・グループのメンバーシップを集中管理することによって、各オブジェクトに関連付けられているACLの変更が不要になるため、ACLの管理が簡略化されます。
ACLの不利な点は次のとおりです。
ACLは、プロバイダまたはポートレットのレベルで適用されます。ポートレットを配置するページに応じてポートレットのセキュリティ・ルールを変更することはできません。
ポートレットのセキュリティ・マネージャはプロバイダ内部に実装され、特定のユーザーがポートレットのインスタンスを表示できることを確認します。ユーザーがポートレット・インスタンスを含むページを表示すると、セキュリティ・マネージャによって、そのユーザーにポートレットを表示する適切な権限があるかどうかが判断されます。プロバイダでアクセス制御メソッドを実装することで、適切な権限のないユーザーはポートレットからコンテンツを取得できない(つまり、ポートレットを表示しない)ように制限します。ユーザーの詳細や設定項目など指定の特性が認可ロジックを通過した場合のみ、そのユーザーはコンテンツを取得できます。プロバイダでポートレットのセキュリティ・メソッドを実装しない場合は、偽名や認証されていない名前であっても、すべてのユーザー名が通過する可能性があります。
プロバイダでは、次の2つのポートレットのセキュリティ・メソッドを実装できます。
ポートレットのリストの取得
ポートレットのアクセス可能性の確認
ポートレットは、Oracle Portalのユーザー権限、およびユーザーがメンバーとして属しているグループにアクセスできます。セキュリティ・メソッドで使用できる情報は次のとおりです。
ユーザーのデフォルト・グループ
ユーザーまたはグループの権限
すべてのグループで利用できる最高のユーザー権限
ユーザーがアクセスできるオブジェクト(データベース・プロバイダのみ)
AuthLevelSecurityManager
は、認可レベルに関する次の情報にアクセスできます。
強い認証
ユーザーは、現行のOracle PortalセッションでOracleAS Single Sign-On Serverによって認証されています。つまり、ユーザーは有効なユーザー名とパスワードを使用してログインし、そのセッションのコンテキスト内でポートレットをリクエストしました。
弱い認証
以前に強い認証を受けているユーザーは、Oracle Portalセッションがアクティブではないページに戻り、そのページを表示します。永続的なCookie(ユーザーのブラウザで保持)には、以前のセッションでユーザーが有効なユーザー名とパスワードでログインしたことが示されます。
パブリックまたは認証なし
ユーザーは現行のOracle Portalセッションのコンテキスト内でログインしたことがなく、以前にログインしたことを示す永続的なCookieもありません。
これらのセキュリティ・サービスをJavaポートレットに組み込むには、provider.xml
を更新して、セキュリティ・レベルをstrong、weakまたはpublicに設定します。次のXMLをprovider.xml
の</portlet>
タグの直前に挿入してください。
<securityManager class="oracle.portal.provider.v2.security.AuthLevelSecurityManager"> <securityLevel>strong</securityLevel> </securityManager>
provider.xml
を変更した後は、プロバイダをリフレッシュします。
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
セキュリティ・メソッドの利点は次のとおりです。
ポートレットでは、認可レベルに従って異なる出力を作成できます。
セキュリティ・メソッドの不利な点は次のとおりです。
セキュリティ・マネージャのほとんどの実装では、認可レベルや受信メッセージにあるユーザー固有の他の要素が使用されます。このような確認は、Oracle Portalインスタンスを装ったエンティティによって無視されることがあります。
セキュリティ・マネージャをポートレットに追加した後、次の手順に従ってこれを検証できます。
ページ作成とページへのポートレット追加を実行できる権限でOracle Portalインスタンスにログインしていることを確認します。
PUBLICに対して表示可能な新しいポータル・ページを作成します。
Javaポートレットをページに追加します。
新しいポータル・ページへの直接URLを書き留めておきます。
「ログアウト」リンクをクリックして、ポータル・インスタンスからログアウトします。
ブラウザのアドレス・バーに手順4で書き留めたURLを入力して、ポータル・ページに直接アクセスします。
手順2で作成したページが表示されますが、手順3で作成したポートレットは表示されません。ページにポートレットを追加したときはログインしていたため、強い認証を受けています。PDKランタイムはこれを検出し、ポートレットの追加を許可しました。ログアウトしてページを表示したときには、強い認証がすでに失われていたため、PDKフレームワークはポートレットのコンテンツのレンダリングを許可しませんでした。
再度ログインしてページを表示すると、ポートレットの存在を確認できます。
PDKに付属の実装では提供されない特別なセキュリティ対策がポートレットに必要な場合は、独自のカスタムのPortletSecurityManager
コントローラ・クラスを用意する必要があります。そのためには、oracle.portal.provider.v2.security.
PortletSecurityManager
クラスを拡張し、インタフェースで指定されている2つのメソッドに対して実装を提供します。次に、XMLプロバイダ定義でsecurityManager
コントローラ要素のクラス属性を新しいクラス名に置き換え、子要素を適切に構成します。
プロバイダへの認可されていないアクセスを回避する1つの方法は、プロバイダへのアクセスを既知のクライアント・マシンに、サーバー・レベルで制限することです。プロバイダにアクセスできるのは識別されたクライアントのみであるため、この方法により、DoS攻撃を防御できます。
このため、Oracle Fusion Middlewareでは、ホスト名またはIPアドレスに基づいてhttpd.conf
ファイルのディレクティブを許可または拒否することで、クライアント・マシンへのアクセスを制御します。識別子としてホスト名が使用されている場合、サーバーはドメイン・ネーム・サーバー(DNS)でホスト名を検索する必要があり、各リクエストの処理で余分なオーバーヘッドが発生します。この問題はIPアドレスを使用することで回避できますが、リモート・クライアントのIPアドレスが警告なしに変更される可能性があります。
サーバー・セキュリティの利点は次のとおりです。
プロバイダへのアクセスをトラステッド・ホストのみに制限できます。
構成を簡略化できます。
サーバー・セキュリティの不利な点は次のとおりです。
Oracle Web CacheにはIPアドレスのチェック機能がありません。プロバイダの前にOracle Web Cacheがある場合は、すべてのホストのクライアントがOracle Web Cacheに表示リクエストを送信することを防止できません。
アクセスを特定のIPアドレスとホスト名に制限しても、偽のIPアドレスとホスト名が含まれたプロバイダにメッセージを送信することで回避される可能性があります。この方法の場合、リターン・メッセージはIPアドレスがコピーされたマシンに送信されますが、その後も問題が発生する可能性があるため、効果的に実行するのは困難です。
このトピックの詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
既知のクライアントへのアクセスを制限するために、メッセージ認証にはクライアント(Portalインスタンス)とプロバイダに認識されている共有キーが使用されます。これはSSL通信で、クライアント証明書のかわりにプロバイダと使用できます。
Oracle Portalでは、Hashed Message Authentication Code(HMAC)アルゴリズムを使用して計算されたデジタル署名が各メッセージとともにプロバイダに送信されます。プロバイダは、そのプロバイダ独自の共有キーのコピーを使用して署名を確認し、メッセージを認証できます。この手法は、プロバイダとのSecure Socket Layer(SSL)通信で、クライアント証明書のかわりに使用できます。
セキュリティや管理上の問題が発生する可能性があるため、1つのプロバイダ・インスタンスで複数の共有キーはサポートできません。たとえば、共有キーのコピーの1つがなんらかの方法で侵害された場合、プロバイダの管理者は新しいキーを作成してすべてのOracle Portalクライアントに配布し、クライアントはそのプロバイダ定義を更新する必要があります。この問題を回避するには、異なるプロバイダ・サービスをデプロイして、サービスごとに一意の共有キーを指定します。各プロバイダ・サービスには独自のデプロイ・プロパティ・ファイルがあるため、各サービスは他のサービスとは無関係に構成されます。同じプロバイダ・アダプタ内に複数のプロバイダ・サービスをデプロイすることによるオーバーヘッドは比較的小さいものです。
プロバイダの前にOracle Web Cacheがない場合、プロバイダ・セッションの存続期間中に同じ署名Cookieを使用するこの方法は、パフォーマンスと、リクエストを認証することによるセキュリティの間のトレードオフを意味します。署名Cookieの値が計算されるのは、最初のSOAPリクエストによってプロバイダとのセッションが確立された後の1回のみです。プロバイダ・セッションのタイムアウトが短いほど、署名の計算頻度が高くなり、不正に再送信される表示リクエストに対するセキュリティが高まります。ただし、セッションの確立に必要なSOAPリクエストでは時間がかかります。
Oracle Web Cacheを使用して表示リクエストのレスポンスをキャッシュするプロバイダでも、同様のトレードオフが必要です。キャッシュされたコンテンツは、それを取得するための署名Cookieが受信リクエストに含まれているという点で安全ですが、長期間にわたってコンテンツをキャッシュすると、プロバイダは不正にトラップされてプロバイダに再送信される表示リクエストに対して無防備になります。
署名要素は、メッセージの傍受や再送信に対する保護を提供しますが、メッセージ・コンテンツの傍受や読取りを防ぐための処理は何も行いません。しかも、メッセージはプレーン・テキストで送信されます。メッセージの内容が認可されていない者に読み取られるのが心配な場合は、メッセージ認証をSSLと組み合せて使用する必要があります。
メッセージ認証の利点は次のとおりです。
プロバイダによって受信されたメッセージが正当なOracle Portalインスタンスから送信されたものであることが保証されます。
メッセージ認証の不利な点は次のとおりです。
プロバイダが複数のポータルを処理する場合は、管理上の問題が発生します。セッションのタイムアウトを短くすることによってセキュリティを非常に高くした場合は、パフォーマンス上の影響があります。
このトピックの詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
資格証明ストア共有キー
プロデューサの共有キーは、資格証明ストアに格納されます。共有キーを資格証明ストアに格納するには、以下を実行します。
資格証明を作成
資格証明を作成するには、次のWLSTコマンドを実行します。
createCred(map='PDK', key='pdk.omniPortlet.sharedKey', user='sharedKey', password='1234567890abc')
資格証明ストアにPDK Javaコード・アクセスを付与
pdk javaコード・アクセスを資格証明ストア権限に付与するには、以下を実行します。
grantPermission(appStripe=None,principalClass=None,principalName=None,codeBaseURL='file:${domain.home}/servers/WLS_Portal/tmp/_WL_user/-',permClass='oracle.security.jps.service.credstore.CredentialAccessPermission',permTarget='context=SYSTEM,mapName=PDK,keyName=*',permActions='read')
Oracle Portalとプロバイダとの間の通常の通信には、TCPをトランスポート・レイヤーとして使用してデータをプレーン・テキストで送信する、HTTPというネットワーク・プロトコルが使用されます。HTTPSは、TCPの上位にある保護された追加のレイヤー(SSL)を使用して、クライアントとサーバー間の通信を保護し、メッセージの傍受や読取りを困難にします。
SSLを使用して通信を受信する各エンティティ(たとえば、Oracle Web Cacheインスタンス)には、自由に利用できる公開鍵と、そのエンティティのみが知っている秘密鍵があります。エンティティに送信されるメッセージは、そのエンティティの公開鍵で暗号化されます。公開鍵で暗号化されたメッセージは秘密鍵によってのみ復号化できるため、悪意のある第三者がメッセージを傍受しても復号化はできません。
通信の署名に使用される証明書によって、公開鍵が実際に正しいエントリに属していることが保証されます。このような証明書は、認証局(CA)として知られる信頼できるサード・パーティによって発行されます。この証明書には、エンティティの名前、公開鍵およびその他のセキュリティ資格証明が記述されており、サーバーのIDを確認するためにSSL通信のサーバー側にインストールされます。クライアントの証明書は、クライアントのIDを確認するためにクライアントにインストールすることもできます。
Oracle Wallet Managerは、公開鍵のセキュリティ資格証明を管理します。また、公開鍵と秘密鍵のペアの生成、CAに対する証明書リクエストの作成、およびサーバーでの証明書のインストールを行います。
このトピックの詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
SSLの構成
プロバイダをOracle Portalインスタンスから登録するときは、URLを1つのみ入力します。これは、HTTPまたはHTTPSのいずれかを使用できますが、両方は使用できないことを意味します。
SSLメッセージの受信に使用される各サーバーの各ポートには、サーバー側の証明書がインストールされている必要があります。つまり、Webプロバイダとプロバイダをホスティングするサーバーの前には、OracleAS Web Cacheインスタンスが必要です。サーバー・ポートにインストールされている証明書によって、2地点間の通信が暗号化されることが保証されますが、メッセージのソースは認証されません。信頼できるOracle Portalインスタンスとプロバイダとの間の通信を完全に保護するには、メッセージ認証もあわせて使用する必要があります。
Oracle Portal用のSSL構成の詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
PDK-Javaでは、LDAP(Oracle Internet Directory)セキュリティにポートレットのセキュリティ・マネージャを使用します。また、PDK-Javaでは、ユーザー、グループおよび権限のリポジトリとしてOracle Internet Directoryを使用します。ログイン・ユーザーに関する情報が取得され、そのユーザーにポートレットとポートレット内のデータの表示に必要な権限があるかどうかが判断されます。Oracle Internet Directoryセキュリティを有効にすると、プロバイダで次の処理が実行されます。
グループに基づいてポートレットを保護できます。
(独自のセキュリティ・マネージャを使用して)ポートレットの管理機能へのアクセスを制限します。
姓、名前、タイトル、電子メール、電話番号、グループ、写真など、Oracle Internet Directoryに格納されているユーザー・プロパティ情報をすべて取得できます。
Oracle Portalのユーザーおよびグループを作成できます。
デフォルトでは、Oracle Internet Directoryセキュリティは無効になっています。有効にするには、特定のプロバイダのデプロイ・プロパティ・ファイルを変更する必要があります。ポートレットを保護するために、迅速かつ簡単にOracle Internet Directoryを有効にして使用できます。そのための手順は、次のとおりです。
デプロイ・プロパティ・ファイル(provider_name
.properties
)でOracle Internet Directoryマネージャを有効にします。
oidManager=true
oidAdminClass=class_that_extends_oracle.portal.provider.v2.oid.OidInfo
OidInfo
という単純なクラスを拡張して、Oracle Internet Directoryの接続情報を指定します。
プロバイダ定義ファイルに、ポートレットを表示できるグループのリストを指定します。
<group>cn=group1,cn=groups,dc=us,dc=oracle,dc=com</group>
プロバイダは、OidInfo
クラスに指定した情報を使用してOracle Internet Directoryに接続します。ポートレットは、指定の資格証明(たとえば、ユーザー名とパスワード)を使用してOracle Internet Directoryにアクセスし、指定されたタスクを実行します。特にプロバイダ接続用として、ポートレットでリクエストされるタスクの実行に必要な最低限の権限を持つOracle Internet Directoryユーザーを作成することをお薦めします。たとえば、ポートレットでグループ情報のチェックのみを行う場合は、管理者としてOracle Internet Directoryに接続しないでください。
PDK-Javaには、特にOracle Internet Directoryとの統合用に一連のデフォルト・クラスが用意されています。これらのクラスは、ポートレットからOracle Internet Directoryへの接続を処理し、Oracle Portalグループに基づいてポートレットを保護し、さらにOracle Internet Directory内からユーザー・プロパティ情報にアクセスすることを可能にします。Oracle Internet Directoryとの統合用にWebプロバイダで使用するクラスは、次のとおりです。
oracle.portal.provider.v2.oid.OidInfo
は、開発者が指定したOracle Internet Directory接続情報を受信して、Oracle Internet Directoryに接続します。独自のポートレットを作成するときは、このクラスを拡張して、プロバイダからOracle Internet Directoryにセキュアな接続詳細を送信する必要があります。
oracle.portal.sample.v2.devguide.oid.UnsafeOidInfo
はOidInfo
の拡張機能で、ポートレットのセキュリティをテストする簡単な方法を提供します。このクラスは、PDK-JavaのOracle Internet Directoryサンプルで使用され、Oracle Internet Directory接続情報(後の説明を参照)についてデプロイ・プロパティ・ファイルを解析します。このクラスは、テストおよび開発の目的でのみ使用してください。本稼働用に使用するのは安全ではありません。
oidManager
は、デフォルトではfalseに設定されています。Oracle Internet Directoryを有効にするには、provider_name
.properties
でこのクラスをtrueに設定する必要があります。(Webアプリケーションに存在するプロバイダが1つのみの場合は、provider_name
.properties
が_default.properties
と同じであることを確認してください)。次に例を示します。
serviceClass=oracle.webdb.provider.v2.adapter.soapV1.ProviderAdapter loaderClass=oracle.portal.provider.v2.http.DefaultProviderLoader showTestPage=true definition=providers/lab_provider/provider.xml autoReload=true oidManager=true oidAdminClass=oracle.portal.sample.v2.devguide.oid.UnsafeOidInfo oidHost=myhost.mydomain.com oidPort=oidPort oidUser=oidUser oidPasswd=oidPassword
oidAdminClass
は、OidInfo
を拡張するクラスに設定されます。PDK-Javaでは、デフォルトでUnsafeOidInfo
を使用しますが、その名前に示すように、このクラスは本稼働用に使用しないでください。
oidHost
は、Oracle Internet Directoryがホスティングされているマシンです。
oidPort
は、Oracle Internet Directoryで使用するポートです。
oidUser
は、Oracle Internet Directoryのアカウントです。
oidPasswd
は、Oracle Internet Directoryのパスワードです。
次に例を示します。
serviceClass=oracle.webdb.provider.v2.adapter.soapV1.ProviderAdapter loaderClass=oracle.portal.provider.v2.http.DefaultProviderLoader showTestPage=true definition=providers/lab_provider/provider.xml autoReload=true oidManager=true oidAdminClass=oracle.portal.sample.v2.devguide.oid.UnsafeOidInfo oidHost=myhost.mydomain.com oidPort=oidPort oidUser=oidUser oidPasswd=oidPassword
oracle.portal.provider.v2.security.GroupSecurityManager
は、プロバイダとそのポートレットへのアクセス権限を持つグループを管理します。このクラスはポートレット固有で、プロバイダ定義ファイルから情報を取得します。プロバイダのポートレットごとに、異なるグループ設定を指定することもできます。このタグを使用して設定できるグループの数に制限はありませんが、Webプロバイダは各グループを解析して検証するため、グループ数が多いとパフォーマンスが低下する場合があります。
<group>
はprovider.xml
内のタグで、グループ管理を行います。このタグは、ポートレットにアクセス可能なグループのリストを表示します。このグループ情報の大/小文字の区別は、Oracle Internet Directoryと同じです。
注意: 次の例で参照しているportal_instance_id は、使用しているインストールに固有な内容です。インスタンス識別子を検索する場合は、『Oracle Fusion Middleware Oracle Internet Directory管理者ガイド』を参照してください。 |
<securityManager class="oracle.portal.provider.v2.security.
GroupSecurityManager">
<group>cn=DBA,cn=portal_instance_id,cn=groups,
dc=us,dc=oracle,dc=com</group>
</securityManager>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
Oracle Internet Directoryセキュリティの利点は次のとおりです。
ポートレットを保護する簡単で強力な方法を提供します。
ユーザーのグループ・メンバーシップに基づいてポートレット内のデータを保護します。
Webプロバイダとして公開されているポートレットから直接ユーザーとグループを作成します。
Oracle Internet Directoryセキュリティの不利な点は次のとおりです。
Oracle Internet Directoryを介してポートレットを認可するときに、パフォーマンスがわずかに低下します。LDAPサーバーからグループ情報を取得するときにコストがかかりますが、このコストが発生するのは、ユーザーがセッション内のポートレットに初めてアクセスするときのみです。
プロバイダはOracle Internet Directoryにアクセスする必要があります。
プロバイダで使用するすべてのOracle Portalインスタンスは、同じOracle Internet Directoryインスタンスを使用することが前提です。
Oracle Internet Directoryを使用してプロバイダを保護する方法、またはOracle Internet Directoryを使用して保護されたサンプル・ポートレットを設定する方法は、OTNでテクニカル・ノート『Installing the Oracle Internet Directory Portlets』を参照してください。
Oracle Internet Directoryを使用してプロバイダを保護した後、次の手順に従ってこれを検証できます。
provider.xml
の<group>
タグに指定されているグループのメンバーであるユーザーとして、Oracle Portalインスタンスにログインしていることを確認します。
PUBLICに対して表示可能な既存のページを使用するか、新しいページを作成します。
Javaポートレットをページに追加します。
新しいページへの直接URLを書き留めておきます。
「ログアウト」をクリックします。
手順4で書き留めたURLをブラウザのアドレス・バーに入力してページに直接アクセスするか、provider.xml
にリストされているグループに属さないユーザーを使用してOracle Portalにログインします。
図7-10のように、手順2で作成したページが表示されますが、手順3で追加したポートレットは表示されません。ページにポートレットを追加したときは、ポートレット表示の認可を受けたユーザーとしてログインしています。PDKランタイムはこれを検出し、ポートレットの追加を許可しました。ログアウトしてページを表示したときは、ポートレット表示を許可されたグループにはすでに属していなかったため、PDKフレームワークはポートレットのコンテンツのレンダリングを許可しませんでした。
再度ログインしてページを表示すると、ポートレットの存在を確認できます(図7-11)。
テキストにエスケープせずにユーザー入力を受け入れると、攻撃者がユーザー入力フォームを介して悪意のあるスクリプトで渡そうとするXSS攻撃の危険があります。たとえば、ポートレット・タイトルがカスタマイズ可能な場合、攻撃者はタイトル文字列を使用して、ポートレットにスクリプトまたはコマンドを渡そうとすることができます。OracleAS Porletでは、そのような攻撃からポートレットを保護できるように、次の機能が提供されています。
ポートレット・タイトル内のスクリプトが実行されないように、フレームワーク・デフォルト・コンテナ・レンダラ・クラスはすべてのスクリプト文字をエンコードします。このデフォルトの動作は、JNDI変数escapeStrings
で制御されます。true
に設定すると、ポートレット・タイトル内のマークアップ・タグが表示タグ文字としてレンダリングされます。たとえば、<i>title</i>
というタイトルのカスタマイズは、titleではなく<i>title</i>
としてレンダリングされます。このモードは安全ですが、そのようにしたくない場合は、そのプロバイダのescapeStrings
をfalse
に設定できます。
escapeStrings
はWebプロバイダ内のすべての論理プロバイダに適用されます。escapeStrings
の値は、WebLogic Server管理コンソールから、他のJNDI変数と同じように設定できます。詳細は、7.2.4.2項「JNDI変数値の設定」を参照してください。
カスタマイズされた値をレンダリングするコードがある場合、XSS攻撃を避けるためにそれらの入力値を適切にエスケープする必要があります。これは、どのモードでページをレンダリングするコードでも同様です。Oracle Portalではこのための2つの新しい静的なメソッドが提供されています。Javaクラスoracle.portal.provider.v2.url.UrlUtils
にある次のようなメソッドです。
public static escapeString(
string_text
)
は、与えられた文字列内の任意のスクリプト文字をエスケープします。たとえば、より小さい(<)は<
となります。このメソッドはescapeStrings
JNDI変数による影響を受けず、安全であり、使用を推奨されています。
public static escapeStringByFlag(
string_text
)
は、与えられた文字列内の任意のスクリプト文字をエスケープします。このメソッドはescapeStrings
JNDI変数によって制御されるので、安全性が低く、使用を推奨されていません。
次に例を示します。
title = UrlUtils.escapeString(data.getPortletTitle());
Oracle Portalのエクスポート/インポート機能は、ポートレットなどのポータル・オブジェクトをOracle Portalインスタンス間で移動するための多目的ツールです。たとえば、エクスポート/インポートを使用して、オブジェクトを開発環境からステージング環境に、さらに最終的には本番環境に移動できます。また、Oracle Portalインスタンス間でページおよびページ・グループを移動したり、Webプロバイダをマシン間で移動するのに、エクスポート/インポートを使用することもできます。一般的なエクスポート/インポートの詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』を参照してください。
ポートレットのデフォルト設定は、管理者が設定した後、ユーザーが変更できるため、開発者はデフォルト設定をインポートおよびエクスポートする際に、いくつかの特別な配慮をする必要があります。トランスポート・プロセスを簡略化するために、Oracle Portalには開発者のために、管理者のパーソナライズ・データ(つまり、デフォルトの編集モードで作成されたデータ)を処理するデフォルト機能が用意されています。ポートレットがエクスポートされるとき、デフォルトでは、PDK-JavaのPreferenceStore
メカニズムを使用して格納されたデフォルトのパーソナライズ・データがポートレットとともにエクスポートされます。したがって、ポートレットがターゲットのOracle Portalインスタンスにインポートされるとき、このデータはポートレットとともにインポートされます。その結果、ポートレットがポートレット・インスタンス間で移動されるとき、ポートレット・インスタンスのデフォルト設定は保持されます。脚注1
前述の動作は、開発者が便利なように提供されており、利用するためになんらかの操作を実行する必要はありません。ただし、パーソナライズ・データのエクスポートに対して、デフォルト機能より精度の高い制御を行うことが必要な場合があります。エクスポート/インポートについて独自の要件を実装するために、開発者はプログラミング・インタフェースを使用してパーソナライズのデフォルト処理を強化または上書きできます。
PDK-Javaのプリファレンス・ストア・メカニズムを使用する場合、デフォルトの編集をパーソナライズした内容のエクスポート/インポートが組み込まれるため、開発者側でなんらかの操作を実行する必要はありません。デフォルトで行われる、管理者のパーソナライズのこのエクスポート/インポートは、PDK-Javaのプリファレンス・ストアに基づいて行われます。独自のプリファレンス・ストア・メカニズム(ファイルまたはデータベースのプリファレンス・ストレージ・システムなど)を作成した場合、次の機能を実行する独自のエクスポート/インポート・サポートを実装する必要があります。
パーソナライズのエクスポート。この機能は少なくとも管理者のパーソナライズをエクスポートする必要がありますが、必要に応じてユーザーのパーソナライズを含めることもできます。
パーソナライズのインポート。この機能は、エクスポートに対して実装したすべての機能に対応している必要があります。たとえば、管理者とユーザーの両方のパーソナライズのエクスポートを実装した場合、これらの両方がインポートできる必要があります。
パーソナライズに対するエクスポート/インポート機能では、Oracle Portalインスタンスおよびプロバイダがリリース10.1.2上に存在する必要があります。パーソナライズのエクスポート/インポートの動作は、プロバイダの位置に関係なく同じです。次のいずれかの場合があります。
Oracle Fusion MiddlewareのデフォルトのOracle Containers for Java EE(Oracle Portalインスタンスは異なります)。
別のOracle Containers for Java EE(Oracle Portalインスタンスは異なることがあり、プロバイダは同じでもターゲットのOracle Portalインスタンスに登録されていません)。
PDK-Javaのプリファレンス・ストア・メカニズムは、多数のアプリケーション・エンティティによるデータの永続化を可能にします。次の3つのエンティティは、エクスポート/インポートのためにデータを永続化するエンティティです。
ポートレット・インスタンスは、管理者によってデフォルトのパーソナライズが行われたページ上のポートレットです。ポートレット・インスタンスのAPIは、次のとおりです。
ポートレット定義は、パーソナライズがまったく適用されていない基本ポートレットです。ポートレット定義は、特定のページで使用するために配置される前の、ポートレット・リポジトリに存在するポートレットのバージョンと考えることができます。ポートレット定義のAPIは、次のとおりです。
プロバイダ・インスタンスは、一連のポートレットを含み、これらのポートレットと通信するエンティティです。プロバイダ・インスタンスのAPIは、次のとおりです。
デフォルトでは、これらの各エンティティは、oracle.portal.provider.v2.transport.PrefStoreTransporter
のインスタンスを使用して、トランスポート用にデータをoracle.portal.provider.v2.preference.PreferenceStore
からバイト配列に変換します。ただし、エクスポート/インポートのデフォルト動作では、ポートレット・インスタンス・エンティティのパーソナライズ・データのみがエクスポートおよびインポートされます。ポートレット定義またはプロバイダ・インスタンスのレベルで永続化されたデータがある場合、そのデータもエクスポートすることがあります。たとえば、ProviderInstance
レベルで永続化した請求ハンドルはエクスポートする必要があります。
PrefStoreTransporter
の動作を変更するために、デフォルト実装を上書きできます。PrefStoreTransporter
のオーバーライド方法は、7.2.8.3.7項「参照によるエクスポートの例」の例を参照してください。
ロギング・インタフェース
エクスポート/インポート・トランザクションのトラブルシューティングを簡略化するために、メッセージをコール元のOracle PortalインスタンスとWebプロバイダ・ログの両方に送信できます。PDK-Javaでは、トランスポート・ロギング・クラスを提供しています。このクラスを使用すると、エクスポートおよびインポートの操作中にイベントをログに追加できます。この方法により、ポートレットのパーソナライズのトランスポート中に発生するイベントをより適切に管理できます。ログは、トランスポート中またはトランスポート後にポートレットで予期しない動作が発生した場合に、有益なトラブルシューティング・ツールになります。たとえば、PDK-Javaのバージョン間で不一致が見つかった場合に、イベントをログに記録できます。
イベントをログに記録するには、ログ出力オブジェクト、すなわち前述の各メソッドに提供されるoracle.portal.provider.v2.transport.TransportLogger
クラスのインスタンスを使用します。コール元のポータルでは、各メソッドに提供されるこのインスタンスを介してイベントをログに記録します。Webプロバイダ・ログには、標準的なロギング・メカニズムのoracle.portal.log.LogManager
を使用してイベントを記録します。エクスポート/インポートのログ・レベルは次のとおりです。
TransportLogger.SEVERITY_INFO
TransportLogger.SEVERITY_WARNING
TransportLogger.SEVERITY_ERROR
この例では、ポートレットを構築し、パーソナライズのエクスポートについてデフォルト動作を受け入れる最も基本的なケースを示します。7.2.8.3.6項「パーソナライズ・データの暗号化の例」および7.2.8.3.7項「参照によるエクスポートの例」の例では、エクスポートおよびインポート時にパーソナライズのセキュリティを強化する方法を示します。最も基本的な形式のパーソナライズのエクスポートを実装する手順は、次のとおりです。
株式ポートレットを作成し、次のクラスMyStockPortletShowRenderer.java
を使用して表示モードを実装します。このクラスには、エクスポート/インポートを有効にする特別なコードが組み込まれていないことに注意してください。
package oracle.portal.sample.v2.devguide.tx; import java.util.StringTokenizer; import oracle.portal.provider.v2.PortletException; import oracle.portal.provider.v2.personalize.NameValuePersonalizationObject; import oracle.portal.provider.v2.render.PortletRenderRequest; import oracle.portal.provider.v2.render.PortletRendererUtil; import oracle.portal.provider.v2.render.http.BaseManagedRenderer; import java.io.PrintWriter; import oracle.portal.sample.v2.devguide.webservices. NetXmethodsServicesStockquoteStockQuoteServiceStub; public class MyStockPortletShowRenderer extends BaseManagedRenderer { private String pid = null; private String userdata; private String stockList; private String stockCode; public void renderBody(PortletRenderRequest request) throws PortletException { // Use the PrintWriter from the PortletRenderRequest PrintWriter out = null; NetXmethodsServicesStockquoteStockQuoteServiceStub ns = new NetXmethodsServicesStockquoteStockQuoteServiceStub(); try { out = request.getWriter(); NameValuePersonalizationObject data = null; data = (NameValuePersonalizationObject)PortletRendererUtil. getEditDefaultData(request); stockList= data.getString("stock"); if(stockList!=null) { StringTokenizer st = new StringTokenizer(stockList,","); out.println("<table border='0'>"); out.println("<thead>"); out.println("<tr>"); out.println("<th width='20%'>"); out.println("<p align='left'> Stock Code</p></th><th width='20%'>"); out.println("<p align='left'> Quote</p>"); out.println("</th>"); out.println("</tr>"); out.println("<thead>"); while(st.hasMoreElements()) { stockCode= st.nextElement().toString(); out.println("<tr>"); out.println("<td width='20%'>"); out.println("<p align='left'>"+ stockCode + "</p></td><td width='20%'>"); out.println(ns.getQuote(stockCode)); out.println("</td>"); out.println("</tr>"); } out.println("</table>"); } else { out.println("<br> Click <b>Edit Defaults</b> to define stock codes."); } } catch(Exception ioe) { throw new PortletException(ioe); } } }
次のクラスMyStockPortletEditDefaultsRenderer.java
を使用して、株式ポートレットにデフォルト編集モードを実装します。このクラスにより、管理者はデフォルトのパーソナライズを実行し、格納できます。その後、そのパーソナライズは、デフォルト動作に従ってエクスポートされます。
package oracle.portal.sample.v2.devguide.tx; import oracle.portal.provider.v2.PortletException; import oracle.portal.provider.v2.http.HttpCommonConstants; import oracle.portal.provider.v2.render.PortletRenderRequest; import oracle.portal.provider.v2.render.http.BaseManagedRenderer; import oracle.portal.provider.v2.render.PortletRendererUtil; import oracle.portal.provider.v2.personalize.NameValuePersonalizationObject; import java.io.PrintWriter; import java.io.IOException; import oracle.portal.provider.v2.render.http.HttpPortletRendererUtil; public class MyStockPortletEditDefaultsRenderer extends BaseManagedRenderer { public void renderBody(PortletRenderRequest request) throws PortletException { PrintWriter out = null; try { out = request.getWriter(); } catch(IOException ioe) { throw new PortletException(ioe); } // Personalize the portlet title and stock String actionParam = PortletRendererUtil.getEditFormParameter(request); PortletRenderRequest prr = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); String action = request.getParameter(actionParam); String title = prr.getQualifiedParameter("myportlet_title"); String stock = prr.getQualifiedParameter("myportlet_stock"); NameValuePersonalizationObject data = null; try { data = (NameValuePersonalizationObject) PortletRendererUtil.getEditDefaultData(request); } catch(IOException io) { throw new PortletException(io); } // Cancel automatically redirects to the page, so // will only recieve OK or APPLY if (action != null) { data.setPortletTitle(title); data.putString("stock",stock); try { PortletRendererUtil.submitEditData(request, data); } catch(IOException ioe) { throw new PortletException(ioe); } return; } // Otherwise just render the form title = data.getPortletTitle(); stock = data.getString("stock"); out.print("<table border='0'> <tr> "); out.println("<td width='20%'> <p align='right'>Title:</p></td> <td width='80%'>"); out.print("<input type='TEXT' name='" + HttpPortletRendererUtil.portletParameter(prr, "myportlet_title") + "' value='" + title + "'>"); out.println("</td> </tr>"); out.print("<tr> <td width='20%'> <p align='right'>Stock Codes:</p></td> <td width='80%'>"); out.print("<input type='TEXT' name='" + HttpPortletRendererUtil.portletParameter(prr, "myportlet_stock") + "' value='" + stock + "'>"); out.println("<br> For example use US Stock Codes separated by comma: <i> SUNW,IBM,ORCL</i>"); out.print("</td> </tr>"); out.println("</table>"); } }
株式ポートレット用に、次のクラスNetXmethodsServicesStockquoteStockQuoteServiceStub.java
を作成します。
package oracle.portal.sample.v2.devguide.webservices; import oracle.soap.transport.http.OracleSOAPHTTPConnection; import org.apache.soap.encoding.SOAPMappingRegistry; import java.net.URL; import org.apache.soap.rpc.Call; import org.apache.soap.Constants; import java.util.Vector; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Response; import org.apache.soap.Fault; import org.apache.soap.SOAPException; import java.util.Properties; public class NetXmethodsServicesStockquoteStockQuoteServiceStub { public NetXmethodsServicesStockquoteStockQuoteServiceStub() { m_httpConnection = new OracleSOAPHTTPConnection(); m_smr = new SOAPMappingRegistry(); } private String _endpoint = "http://64.124.140.30:9090/soap"; public String getEndpoint() { return _endpoint; } public void setEndpoint(String endpoint) { _endpoint = endpoint; } private OracleSOAPHTTPConnection m_httpConnection = null; private SOAPMappingRegistry m_smr = null; public Float getQuote(String symbol) throws Exception { Float returnVal = null; URL endpointURL = new URL(_endpoint); Call call = new Call(); call.setSOAPTransport(m_httpConnection); call.setTargetObjectURI("urn:xmethods-delayed-quotes"); call.setMethodName("getQuote"); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); Vector params = new Vector(); params.addElement(new Parameter("symbol", String.class, symbol, null)); call.setParams(params); call.setSOAPMappingRegistry(m_smr); Response response = call.invoke(endpointURL, "urn:xmethods-delayed-quotes#getQuote"); if (!response.generatedFault()) { Parameter result = response.getReturnValue(); returnVal = (Float)result.getValue(); } else { Fault fault = response.getFault(); throw new SOAPException(fault.getFaultCode(), fault.getFaultString()); } return returnVal; } public void setMaintainSession(boolean maintainSession) { m_httpConnection.setMaintainSession(maintainSession); } public boolean getMaintainSession() { return m_httpConnection.getMaintainSession(); } public void setTransportProperties(Properties props) { m_httpConnection.setProperties(props); } public Properties getTransportProperties() { return m_httpConnection.getProperties(); } }
このポートレットのprovider.xml
を使用してWebプロバイダを作成します。パーソナライズの格納を可能にする<preferenceStore>
要素の使用に注意してください。
<provider class="oracle.portal.provider.v2.DefaultProviderDefinition"> <session>false</session> <passAllUrlParams>false</passAllUrlParams> <preferenceStore class="oracle.portal.provider. v2.preference.FilePreferenceStore"> <name>prefStore1</name> <useHashing>true</useHashing> </preferenceStore> <portlet class="oracle.portal.provider.v2.DefaultPortletDefinition"> <id>1</id> <name>MyStockPortlet</name> <title>My Stock Portlet</title> <description>Simple Stock Portlet to show Export and Import feature of web providers</description> <timeout>80</timeout> <showEditToPublic>false</showEditToPublic> <hasAbout>false</hasAbout> <showEdit>false</showEdit> <hasHelp>false</hasHelp> <showEditDefault>true</showEditDefault> <showDetails>false</showDetails> <renderer class="oracle.portal.provider.v2.render.RenderManager"> <renderContainer>true</renderContainer> <renderCustomize>true</renderCustomize> <autoRedirect>true</autoRedirect> <contentType>text/html</contentType> <showPage class="oracle.portal.sample.v2. devguide.tx.MyStockPortletShowRenderer"/> <editDefaultsPage class="oracle.portal.sample.v2.devguide.tx. MyStockPortletEditDefaultsRenderer"/> </renderer> <personalizationManager class="oracle.portal.provider.v2.personalize. PrefStorePersonalizationManager"> <dataClass>oracle.portal.provider.v2.personalize. NameValuePersonalizationObject </dataClass> </personalizationManager> </portlet> </provider>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
このエクスポート対応のプロバイダをソースのOracle Portalインスタンスに登録します。Webプロバイダの登録方法は、6.5.5項「Oracle PDK-Javaポートレットの登録と表示」を参照してください。
注意: Webプロバイダが保護された環境で実行されている場合、Oracle WebLogic Serverの起動時にプロキシ・ホストおよびポートを必ず指定してください。次に例を示します。JAVA_OPTIONS=“-Dhttp.proxyHost=www-proxy.us.oracle.com -Dhttp.proxyPort=80 |
サンプル・ページにリージョンを2つ作成し、My Stock Portletを1つ目のリージョンに追加します。リージョンおよびページの作成方法は、『Oracle Fusion Middleware Oracle Portalユーザーズ・ガイド』を参照してください。
ページを編集し、My Stock Portletの「デフォルトの編集」アイコンを選択します。株式コードSUNW、IBM、ORCL
を選択します。ページ上のポータルのデフォルトを編集する方法は、『Oracle Fusion Middleware Oracle Portalユーザーズ・ガイド』を参照してください。
My Stock Portletを2つ目のリージョンに追加し、デフォルトを再編集します。今度は、別の株式コードMSFT
を使用します。
このページを含むページ・グループをエクスポートします。ページ・グループのエクスポート方法は、『Oracle Fusion Middleware Oracle Portal管理者ガイド 』の第10章「コンテンツのエクスポートおよびインポート」を参照してください。
このページ・グループをターゲットのOracle Portalインスタンスにインポートします。ページ・グループのインポート方法は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』の第10章「コンテンツのエクスポートおよびインポート」を参照してください。
ターゲットのOracle PortalインスタンスでMy Stock Portletをページに表示し、パーソナライズが保持されていることを確認します。
パーソナライズのトランスポートは、ポートレットが機密データを格納し、保護された環境で機能していない場合、セキュリティ上の問題を示すことがあります。Oracle Portalには、プロバイダおよびポートレットのレベルで、ポートレットのパーソナライズのエクスポートとそれに続くインポートを保護するための方法がいくつか用意されています。エクスポート/インポートについてポートレットおよびプロバイダをより厳しく保護するために、次の処置を行うことができます。
7.2.8.3.1項「プロバイダ通信の保護」。Oracle Portalの構成オプションを使用して、プロバイダとOracle Portal間の通信を保護できます。これにより、ポートレットのエクスポートとインポートがよりセキュアになります。
7.2.8.3.2項「パーソナライズのエクスポート/インポートの無効化」。各Webアプリケーションに対して、すべてのポートレットのパーソナライズ・データのエクスポートを無効化できます。この方法は、最も高いセキュリティを提供しますが、ポートレットの移動時に管理者は自分のデフォルトのパーソナライズを保持できないため、機能性を著しく犠牲にします。
7.2.8.3.3項「トランスポート用データの不明瞭化(自動)」。デフォルトでは、Oracle Portalはトランスポートする前にパーソナライズ・データを不明瞭化しますが、暗号化はしません。
7.2.8.3.4項「トランスポート用パーソナライズ・データの暗号化」。次のいずれかに該当する場合、トランスポート用にパーソナライズ・データを暗号化することができます。
Webプロバイダ接続がHTTPSを使用して保護されていない場合。
転送時のデータ保護を確保する場合。
Oracle Portalインスタンスに格納されている間、データを保護されたままにする場合。
7.2.8.3.5項「参照によるエクスポート」。ポートレットのパーソナライズ・データは、トランスポート・セットに直接含めるかわりに、参照を使用してトランスポート・セットに含めることができます。データ自体はトランスポート・セットに存在しないため、参照によるエクスポートは最もセキュアなパーソナライズのトランスポート方法です。
ポートレットのエクスポート/インポートのセキュリティが重要な問題である場合、ポートレット・プロバイダとの通信を保護するようにOracle Portalを構成する必要があります。Oracle Portalでのプロバイダ通信の保護に対する主要なメカニズムは次のとおりです。
Hashed Message Authentication Code(HMAC)アルゴリズムを使用したメッセージ認証。プロバイダに対するメッセージ認証の詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド 』の6.1.7.8項「メッセージ認証」を参照してください。
プロバイダとOracle Portal間のHTTPS。プロバイダ通信に対するHTTPSの詳細は、『Oracle Fusion Middleware Oracle Portal管理者ガイド』の6.1.7.9項「HTTPS通信」を参照してください。
注意: 証明書は、プロバイダとのHTTPS通信に使用できません。 |
JNDI変数oracle/portal/provider/global/transportEnabled
により、パーソナライズのエクスポートおよびインポートを許可するかどうかが制御されます。この変数をtrueに設定すると、パーソナライズはエクスポートとインポートの一環としてトランスポートされます。falseに設定すると、トランスポートされません。Oracle WebLogic ServerのPDK-Java Webアプリケーションに設定されたデプロイ・プランを通して、PDK-JavaにJNDI変数を設定できます。これは、WebLogic Server管理コンソールを使用して行えます。デプロイ・プランは、パッケージ化されたデプロイ記述子ファイルを変更する手間を省き、アプリケーションの構成変更が簡単になります。デプロイ・プランの設定が終わったら、既存のWEB-INF/web.xmlモジュール記述子内のJNDI変数に対して、それを次のように手動で変更できます。
<module-descriptor external="false"> <root-element>web-app</root-element> <uri>WEB-INF/web.xml</uri> <variable-assignment> <name>provider_transportEnabled</name> <xpath>/web-app/env-entry/[env-entry-name="oracle/portal/provider/global/transportEnabled"]/env-entry-value</xpath> </variable-assignment> </module-descriptor>
この変数割当の変数定義は<deployment-plan>タグの直下で行われ、次のようになります。
<variable-definition> <variable> <name>provider_transportEnabled</name> <value>false</value> </variable> </variable-definition>
これによって、oracle/portal/provider/global/transportEnabled
はfalseに設定されます。
参照: Oracle Fusion Middleware Oracle WebLogic Serverへのアプリケーションのデプロイ |
デフォルトでは、パーソナライズ・データはエンコード(BASE64)されます。このエンコーディングにより、トランスポート時のデータは不明瞭化されます。BASE64エンコーディングは、デフォルトで提供されるため、利用するためになんらかの操作を実行する必要はありません。ただし、より高いセキュリティが必要な場合は、データを暗号化できます。7.2.8.3.4項「トランスポート用パーソナライズ・データの暗号化」を参照してください。
oracle.portal.provider.v2.security.CipherManager
クラスをプロバイダに実装することで、エクスポートする前にパーソナライズ・データを暗号化できます。インポート時には、暗号マネージャが再起動され、データが復号化されます。7.2.8.3.6項「パーソナライズ・データの暗号化の例」を参照してください。
注意: 暗号マネージャを使用して、エクスポート用にWebプロバイダを暗号化する場合、暗号化アルゴリズムに対する鍵の管理方法を独自に考案する必要もあります。 |
前述のとおり、ポートレットのエクスポートのデフォルト動作では、実際のパーソナライズ・データがトランスポート・セットに含まれます。よりセキュアなトランスポートのために、実際のプリファレンス・データを含めるのではなく、ポインタを使用してパーソナライズがエクスポートされるように、ポートレットをコーディングできます。トランスポート・セットのインポート時に、ターゲットのOracle PortalインスタンスはポインタをWebプロバイダに戻します。その後、Webプロバイダで、実際のデータは新しいポートレット・インスタンスと再度関連付けられます。7.2.8.3.7項「参照によるエクスポートの例」を参照してください。
注意: セキュリティ・ゾーンを越えてエクスポートする場合、参照によるエクスポートは事実上機能しないことがあります。一般に、参照によるエクスポートを採用するのは、同じ一般的なセキュリティ環境内でトランスポートを実行する場合のみです。 |
Webプロバイダのパーソナライズ・データを暗号化するには、独自の暗号マネージャを作成し、ポートレット・プロバイダに関連付ける必要があります。この例では、説明専用の、単純でセキュアではない暗号マネージャを示します。セキュアな暗号マネージャを本番システムに実装するには、この例を大幅に拡張する必要があります。本番システムへの実装で考慮する必要がある問題を次に示します。
鍵オブジェクトをメモリー内に保持しないでください。必要に応じて、永続ストアから読み取ります。
クラスタ化されたケースで機能させるには、DBPreferenceStore
でサポートされるプロバイダのPreferenceStore
APIを使用します。
インポート時に、provider.xml
から取得された暗号マネージャのインスタンスがSOAPメッセージで戻されたクラス名と一致する場合、復号化の実行にそのCipherManager
インスタンスが使用されます。したがって、ポートレット/プロバイダ定義に保持されるインスタンスが、適切な方法(たとえば、provider.xml
のタグやJNDI変数)を使用して構成されると、その構成がインポート時に再利用されます。
Webプロバイダのパーソナライズ・データを暗号化する手順は、次のとおりです。
注意: 次のサンプルは説明専用のものです。本番環境で使用するには、大幅に拡張する必要があります。 |
暗号マネージャ・クラスInsecureCipherManager
を作成します。このクラスは、Webプロバイダに対してエクスポートまたはインポートされるパーソナライズ・データの暗号化および復号化に使用されます。BASE64でエンコードされ、ハードコーディングされた秘密鍵が、基礎となるJava Runtime Environmentのデフォルトのjavax.crypto
プロバイダにより提供されるDESアルゴリズムで使用されます。その結果、エンコードされた鍵は、バイト・コードを逆コンパイルするのみで悪意を持ったユーザーに奪取されるため、この特別サンプルはセキュアではありません。
注意: このサンプルではjavax.crypto パッケージを使用します。このパッケージは、Java1.3のオプションで、手動でインストールする必要があります。ただし、Java1.4では、このパッケージをデフォルトで提供しています。 |
package oracle.portal.sample.v2.devguide.tx; import java.io.IOException; import java.security.GeneralSecurityException; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import oracle.portal.provider.v2.ProviderException; import oracle.portal.provider.v2.security.CipherManager; import sun.misc.BASE64Decoder; public final class InsecureCipherManager implements CipherManager { /** * Base64 encoded external form of a javax.crypto.SecretKey which was * generated for the DES algorithm. This is completely insecure! Anyone * can decompile the bytecode and recostitue the key. A more secure * implementation would implement a key management policy in a * java.security.KeyStore. */ private static final String sEncodedKey = "UTJds807Arw="; /** * Generated from the (insecure) encoded form in sEncodedKey. */ private SecretKey mKey; /** * Transforms the input data to a more secure form, in a single operation, * using the DES cryptographic algorithm along with a statically defined * secret key. * @param toEncode the input data. * @return an encoded form of the input data. * @throws ProviderException if an error occurs during transform. */ public final byte[] encode(byte[] toEncode) throws ProviderException { try { Cipher c = Cipher.getInstance("DES"); c.init(Cipher.ENCRYPT_MODE, getSecretKey()); return c.doFinal(toEncode); } catch (GeneralSecurityException gse) { throw new ProviderException(gse); } catch (IOException ioe) { throw new ProviderException(ioe); } } /** * Transforms the input data to its original form, in a single operation, * using the DES cryptographic algorithm along with a statically defined * secret key. * @param toDecode the input data. * @return a decoded form of the input data. * @throws ProviderException if an error occurs during transform. */ public final byte[] decode(byte[] toDecode) throws ProviderException { try { Cipher c = Cipher.getInstance("DES"); c.init(Cipher.DECRYPT_MODE, getSecretKey()); return c.doFinal(toDecode); } catch (GeneralSecurityException gse) { throw new ProviderException(gse); } catch (IOException ioe) { throw new ProviderException(ioe); } } /** * Returns a <code>javax.crypto.SecretKey</code> deserialized from the * obuscated form in sEncodedKey. Note, this is highly insecure!! */ private SecretKey getSecretKey() throws GeneralSecurityException, IOException { if (mKey == null) { DESKeySpec ks = new DESKeySpec((new BASE64Decoder()).decodeBuffer( sEncodedKey)); SecretKeyFactory skf = SecretKeyFactory.getInstance("DES"); mKey = skf.generateSecret(ks); } return mKey; } }
暗号マネージャを参照するように、provider.xml
を変更します。
<?xml version = '1.0' encoding = 'UTF-8'?> <?providerDefinition version="3.1"?> <provider class="oracle.portal.provider.v2.DefaultProviderDefinition"> <providerInstanceClass>net.mzyg.tx.TxProviderInstance</providerInstanceClass> <session>false</session> <passAllUrlParams>false</passAllUrlParams> <preferenceStore class="oracle.portal.provider.v2. preference.DBPreferenceStore"> <name>prefStore1</name> <connection>java:comp/env/jdbc/PortletPrefs</connection> </preferenceStore> <cipherManager class="oracle.portal.sample.v2.devguide.tx. InsecureCipherManager"/>
実際のパーソナライズをエクスポートするのではなく、参照によりエクスポートする手順は、次のとおりです。
DefaultPortletInstance
を次のExportByRefDefaultPortletInstance
でオーバーライドします。
package oracle.portal.sample.v2.devguide.tx;
import oracle.portal.provider.v2.DefaultPortletInstance;
import oracle.portal.provider.v2.preference.PreferenceStore;
import oracle.portal.provider.v2.transport.PrefStoreTransporter;
public class ExportByRefDefaultPortletInstance extends DefaultPortletInstance
{
/**
* Returns a {@link oracle.portal.provider.v2.transport.PrefStoreTransporter}
* capable of carrying out transport operations such as export/import on
* data applicable to {@link oracle.portal.provider.v2.PortletInstance}
* persisted in {@link oracle.portal.provider.v2.preference.PreferenceStore}.
* This implementation returns an {@link ExportByRefPrefStoreTransporter}.
* @param ps the {@link oracle.portal.provider.v2.preference.PreferenceStore}
* containing the data to be transported.
* @return a {@link oracle.portal.provider.v2.transport.PrefStoreTransporter}
*/
protected PrefStoreTransporter getPrefStoreTransporter(PreferenceStore ps)
{
return new ExportByRefPrefStoreTransporter(ps);
}
}
ExportByRefDefaultPortletInstance
で参照されるExportByRefPrefStoreTransporter
クラスを作成します。このクラスは、エクスポート操作時にプリファレンス・データを送信しない代替プリファレンス・ストア・トランスポータを実装します。かわりに、ソース・プリファレンスのコンテキスト・パスをストリームに書き出します。エクスポート時に、コンテキスト・パスを読み取り、そのパスを使用してプリファレンス・データを検索し、新しいインスタンスにコピーします。この参照によるエクスポート方法は、ソースとターゲットのプロバイダが同じプリファレンス・ストアにアクセスすることを前提にしています。つまり、この例の最も適した例は、ソースとターゲットのプロバイダが同じ場合です。
package oracle.portal.sample.v2.devguide.tx; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import oracle.portal.provider.v2.transport.PrefStoreTransporter; import oracle.portal.provider.v2.transport.TransportLogger; import oracle.portal.provider.v2.preference.Preference; import oracle.portal.provider.v2.preference.PreferenceStore; import oracle.portal.provider.v2.preference.PreferenceStoreException; public class ExportByRefPrefStoreTransporter extends PrefStoreTransporter { public ExportByRefPrefStoreTransporter(PreferenceStore prefStore) { super(prefStore); } /** * Exports the context path of the supplied {@link * oracle.portal.provider.v2.preference.Preference} from the {@link * oracle.portal.provider.v2.preference.PreferenceStore}. * @param pref the source {@link * oracle.portal.provider.v2.preference.Preference} * @param out the <code>java.io.OutputStream</out> to which data will be * written. * @param logger */ protected void exportPreference(Preference pref, OutputStream out, TransportLogger logger) throws PreferenceStoreException, IOException { // Get the context path of the preference we are exporting. String contextPath = pref.getContextPath(); DataOutputStream dos = new DataOutputStream(out); // Write the context path in the export data. The import process // will use this context path to lookup this preference in the // preference store and copy it to the new context dos.writeUTF(contextPath); } /** * Reads a context path from the stream and copies preference data * from that location into the {@link * oracle.portal.provider.v2.preference.PreferenceStore}. * @param pref the target {@link * oracle.portal.provider.v2.preference.Preference} * @param in the <code>java.io.InputStream</code> from which to read data. * @param logger */ protected void importPreference(Preference pref, InputStream in, TransportLogger logger) throws PreferenceStoreException, IOException { // Read the context path to copy the value for this // preference from. DataInputStream dis = new DataInputStream(in); String contextPath = dis.readUTF(); // Create preference object to copy from (identical to the // target preference but with a different context path) Preference sourcePref = new Preference(contextPath, pref.getName(), pref.getType(), (String)null); // Copy across the preference getPrefStore().copy(sourcePref, pref, true); } }
ポートレットに次の要素が含まれるように、provider.xml
を更新します。
<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition"> ... <portletInstanceClass>oracle.portal.sample.v2.devguide.tx. ExportByRefDefaultPortletInstance</portletInstanceClass> </portlet>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
この章の前述の各項では、完全に機能するJavaポートレットをPDKフレームワークを使用して作成する方法を説明しました。ポートレットの基本機能の設定が完了した後は、ポートレットのパフォーマンスに注目する必要があります。
キャッシュは、高度な動的コンテンツを含むWebサイトのパフォーマンスの向上に使用される一般的な手法です。この手法では、キャッシュと呼ばれる待機時間の短い大きなデータ・ストアを備えたローカル・エージェントを使用してリクエストをプロキシ化することで、動的コンテンツのデータの取得と出力の生成に伴うオーバーヘッドを大幅に削減できます。キャッシュ・エージェントは、リクエストに対して次のいずれかの方法で応答します。
リクエストされたコンテンツの有効なバージョンがキャッシュ内に存在する場合、エージェントはキャッシュされた既存のコピーをそのまま戻します。これによって、コンテンツの取得と生成というコストがかかるプロセスを省くことができます。この状況はキャッシュ・ヒットと呼ばれます。
リクエストされたコンテンツの有効なバージョンがキャッシュ内に存在しない場合、エージェントはリクエストをその宛先に転送し、コンテンツが戻されるのを待機します。エージェントはコンテンツをリクエスト元に戻し、そのキャッシュ内にローカル・コピーを格納して、同じコンテンツに対するリクエストが後で発生した場合に再利用します。この状況はキャッシュ・ミスと呼ばれます。
Webプロバイダは、動的コンテンツ(つまり、ポートレット)の生成元であり、多くの場合、デプロイされているOracle Portalインスタンスから離れた場所にあります。このため、キャッシュによるパフォーマンス向上が可能となります。Oracle Portalのアーキテクチャは、それ自体がキャッシュに適しています。これは、すべてのレンダリング・リクエストが、ポータルの中間層に存在するParallel Page Engine(PPE)という単一のページ作成エージェントから発生するためです。WebプロバイダでレンダリングされたポートレットをPPEでキャッシュし、キャッシュされたコピーを再利用して後続のリクエストを処理することによって、Webプロバイダがページ作成にもたらすオーバーヘッドを最小限にできます。
Webプロバイダでは、どれがアプリケーションに最も適しているかによって、次の3種類のキャッシュ方法のいずれも使用できます。これらのキャッシュ方法の主な違いは、コンテンツが有効かどうかを判断する方法にあります。3種類のキャッシュ方法を次に示します。
有効期限ベースのキャッシュ: プロバイダはレンダリング・リクエストを受信すると、そのレスポンスに有効期限のスタンプを付けます。レンダリングされたレスポンスはキャッシュに格納され、同じコンテンツに対する後続のすべてのリクエストは、有効期限が経過するまで、このキャッシュを使用して処理されます。このキャッシュ・スキームは最も簡単でパフォーマンスが優れていると考えられます。それは、キャッシュの有効性をテストするためのオーバーヘッドがほとんどなく、ネットワークのラウンドトリップを伴わないためです。有効期限ベースのキャッシュは、コンテンツの使用期間が効率よく定義されているアプリケーションに適しています。コンテンツの使用期間が確実ではない場合、有効期限ベースのキャッシュは効果的ではありません。詳細は、7.2.9.2項「キャッシュのアクティブ化」および7.2.9.3項「有効期限ベースのキャッシュの追加」を参照してください。
無効化ベースのキャッシュ: 無効化ベースのキャッシュは、基本的には有効期限ベースのキャッシュと同様に機能しますが、任意の時点でキャッシュのコンテンツを期限切れ、つまり無効化できる点が異なります。キャッシュのコンテンツの無効化は、通常、イベントによってトリガーされます。
たとえば、当日の予定を表示するカレンダ・ポートレットの場合、ポートレットのコンテンツが生成されるのは、初めてその日のカレンダを表示したときの1回のみです。予定の追加や取消し、予定時間の変更などその日の予定に変更が発生するまで、コンテンツはキャッシュされたままです。各変更イベントは、カレンダ・アプリケーションでアクションをトリガーできます。変更イベントが発生すると、カレンダ・アプリケーションは、その変更の影響を受けるキャッシュされたポートレット・コンテンツに対して無効化リクエストを生成できます。カレンダ・ポートレットを含むページを次回に表示すると、キャッシュにはエントリが含まれていません。Webプロバイダは、変更後の予定で新しいコンテンツを再生成するように連絡を受けます。
この方法は、非常に効率的にコンテンツをキャッシュできます。これは、コンテンツの生成元(つまり、Webプロバイダ)が連絡を受けるのは新しいコンテンツの生成が必要なときのみで、固定した再生成スケジュールに拘束されないためです。詳細は、7.2.9.2項「キャッシュのアクティブ化」および7.2.9.4項「無効化ベースのキャッシュの追加」を参照してください。
有効化ベースのキャッシュ: レンダリング・リクエストを受信したプロバイダは、そのレスポンスにバージョン識別子(または「E」タグ)のスタンプを付けます。この方法でもレスポンスはキャッシュされますが、キャッシュされたレスポンスをPPEが再利用する前に、キャッシュされたバージョンがまだ有効かどうかを判断する必要があります。そのために、キャシュされたコンテンツのバージョン識別子を含めたレンダリング・リクエストをプロバイダに送信します。プロバイダは、このバージョン識別子が有効であるかどうかを判断します。バージョン識別子が有効である場合、プロバイダはコンテンツを含まない軽量のレスポンスをPPEに即座に送信し、キャッシュされたバージョンを再利用できることを通知します。バージョン識別子が無効な場合、プロバイダは新しいバージョン識別子を含む新しいコンテンツを生成し、以前にキャッシュされたバージョンを置き換えます。このキャッシュ方法では、PPEは、常にプロバイダに対してコンテンツが最新かどうかを確認する必要があります。キャッシュされたコピーの有効性は、プロバイダのロジックによって判断されます。この方法では、固定期間に依存するのではなく、キャッシュされたコンテンツの使用をプロバイダが管理できるという利点があります。詳細は、7.2.9.2項「キャッシュのアクティブ化」および7.2.9.5項「有効化ベースのキャッシュの追加」を参照してください。
これらの項のタスクを実行するには、次の前提が必要です。
6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」を読んで理解していること。
ウィザードで作成したポートレットがページに正常に追加されていること。
Oracle Portalのキャッシュ機能をWebプロバイダで使用するには、最初に、中間層キャッシュをアクティブにする必要があります。このキャッシュは、mod_plsql(データベース・プロシージャおよびデータベース・プロバイダをHTTPでコールするOracle HTTP Serverプラグイン)で使用されるキャッシュと同じであるため、PL/SQLキャッシュと呼ばれます。
通常、キャッシュに関する構成詳細の責任は、OracleAS Portal管理者にあります。
無効化ベースのキャッシュの場合は、Webプロバイダの前にOracle Web Cacheを構成する必要があります。リモートのWebプロバイダにはOracle Web Cacheがインストールされていない場合が多いことに注意してください。Oracle Web Cacheの詳細は、『Oracle Fusion Middleware Oracle Web Cache管理者ガイド』を参照してください。
Oracle Web Cacheをインストールして構成した後は、Oracle Web Cache Managerについて次の点を確認してください。
Webプロバイダのホスト名とポートを指していること。
キャッシュ・ルールによってプロバイダのコンテンツのキャッシュが発生しないこと。コンテンツは、プロバイダがそのレスポンスで生成するSurrogate-Controlヘッダーに従ってキャッシュされる必要があります。
有効期限ベースのキャッシュは、実装が最も簡単なキャッシュ・スキームの1つで、XMLプロバイダ定義内で宣言によってアクティブにできます。利用するManagedRenderer
の出力には、出力のキャッシュ時間(分)をそのpageExpires
プロパティに設定することによって、有効期限を設定できます。たとえば、ポートレット出力を1分間キャッシュすると仮定します。有効期限ベースのキャッシュを追加する手順は、次のとおりです。
6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」の説明に従って、ポートレット・ウィザードを使用してポートレットを作成した後、provider.xml
ファイルを編集し、showPageのpageExpires
プロパティ・タグを1に設定します。これによって、ポートレットの1分間の期限切れエントリが設定されます。
デフォルトでは、ウィザードによって、showPage
の圧縮された標準的なタグが生成されます。pageExpires
のサブタグを含めるには、このタグを拡張する必要があります。
<showPage class="oracle.portal.provider.v2.render.http.ResourceRenderer">
<resourcePath>/htdocs/mycacheportlet/MyCachePortletShowPage.jsp
</resourcePath>
<pageExpires>1</pageExpires>
</showPage>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
JSPコードを表示ページに追加して、ポートレットが1分間キャッシュされることをテストします。ここでは、現在の時刻をJSPに追加します。
<%@page contentType="text/html; charset=windows-1252" import="oracle.portal.provider.v2.render.PortletRenderRequest" import="oracle.portal.provider.v2.http.HttpCommonConstants" import="java.util.Date" import="java.text.DateFormat" %> <% PortletRenderRequest pReq = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG,pReq.getLocale()); String time = df.format(new Date()); %> <P>Hello <%=pReq.getUser().getName() %>.</P> <P>This is the <b><i>Edit</i></b> render mode!</P> <P>This information is correct as of <%=time%>.</P>
ポートレットを表示して、時間(秒を含む)が1分間で一定していることを確認します。時間が経過すると、ポートレットは最新の時刻を表示し、新しいキャッシュが設定されます。
Oracle Web Cacheを使用すると、コンテンツに対するリクエストはHTTPを使用して送信され、コンテンツがキャッシュから戻されるか、またはHTTPリクエストがコンテンツの生成元に転送されます。Oracle Web Cacheに戻されたコンテンツは、リクエスト元に戻される前にキャッシュに追加されます。キャッシュのコンテンツは、無効化リクエストをOracle Web Cacheに直接送信することで無効化されます。PDK-Javaでは、Java API for Web Cache(JAWC)を使用して無効化リクエストを生成します。この項では、Oracle Web Cacheの構成方法、およびPDK-Javaに付属する無効化ベースのキャッシュのサンプルの使用方法を説明します。
Oracle Web Cacheに送信されたすべてのリクエストがキャッシュされるわけではありません。コンテンツをキャッシュするには、Oracle Web Cacheに対してコンテンツのキャッシュを指示するディレクティブがコンテンツに含まれている必要があります。通常、Oracle Web Cacheでは、リクエストに関連付けられたURLをキャッシュ・キーとして使用しますが、Surrogate-Controlヘッダーと呼ばれる特別なHTTPヘッダーをレスポンスに設定すると追加のキーを指定できます。
Javaポートレットを構成して無効化ベースのキャッシュを使用するには、次の処理を実行する必要があります。
Oracle Web Cacheを構成します。詳細は、『Oracle Fusion Middleware Oracle Web Cache管理者ガイド』を参照してください。
無効化ベースのキャッシュを有効にするには、そのキャッシュをプロバイダ・サーブレット・レベルでオンにします。PDK-JavaのWebアプリケーション・デプロイメント・ディスクリプタであるweb.xml
内にある初期化パラメータにフラグが設定されます。次に例を示します。
<servlet> ... <servlet-class>oracle.webdb.provider.v2.adapter.SOAPServlet</servlet-class> <init-param> <param-name>invalidation_caching</param-name> <param-value>true</param-value> </init-param> </servlet>
ここにフラグが定義されていないと、無効化ベースのキャッシュはオフになります。フラグの状態は、プロバイダのテスト・ページを表示してチェックできます。testPageURI
プロパティがsample.properties
ファイルで設定されていない場合は、プロバイダ・コードによりテスト・ページが古いデフォルト形式で表示されます。古い形式のテスト・ページは、無効化ベースのキャッシュのフラグをweb.xml
ファイルから正しく取得します。テスト・ページURLの形式は、次のとおりです。
http://provider_hostname:port/jpdk/providers/sample
PDK-Javaが自動的に事前インストールされているOracle Fusion Middlewareインストール・タイプ(たとえば、Oracle Portal and Wirelessタイプのインストール)を使用する場合は、Oracle Web Cacheの無効化設定がすでにMID_TIER_ORACLE_HOME/portal/conf/cache.xml
に事前構成されていることを確認する必要があります。事前構成されている場合、この項の説明は無視して7.2.9.4.3項「XMLプロバイダ定義の構成」に進んでください。そうでない場合は、Oracle Web Cacheの無効化ポートレットを構成する必要があります。
最初に必要なのは、アプリケーション・サーバーに関連付けられたOracle Web Cacheインスタンスの無効化ポートのユーザー名とパスワードです。これらを取得した後は、提供されているoracle.webdb.provider.v2.cache.Obfuscate
Javaユーティリティを使用して、このユーザー名とパスワードを、JAWC APIに必要な書式の不明瞭化された文字列に変換します。デフォルトのOracle Fusion Middlewareインストールでは、通常、無効化ポートのユーザー名はinvalidator
で、パスワードはアプリケーション・サーバー管理者のパスワードと同じです。たとえば、無効化ポートのユーザー名にinvalidator
を、パスワードにwelcome
を指定して、Oracle Fusion MiddlewareをD:\as904
にインストールするとします。次のコマンドを実行します。
注意: 次に示すコマンドは、PDK-Javaのインストレーション・ガイドで指示されているように、pdkjava.jar およびjawc.jar がORACLE_HOME /j2ee/home/shared-lib/oracle.jpdk/1.0 に存在することを前提にしています。
スタンドアロンのOracle Containers for Java EEインストールを使用している場合は、Java実行可能ファイルへのパスを外部のJava 2 SDKインストールに置き換える必要があります。 |
D:\as904\jdk\bin\java -classpath D:\as904\j2ee\home\shared-lib\oracle.jpdk\1.0\pdkjava.jar oracle.webdb.provider.v2.cache.Obfuscate invalidator:welcome
このコマンドが正常に実行されると、次に示すような16進文字列が出力されます。
0510198d5df8efd5779406342be2528aa0cccb179ea6b77baf49f019f5075a3a11
この情報を使用してJAWC構成ファイルcache.xml
を作成します。この構成ファイルは、1つ以上のOracle Web Cacheインスタンスとその無効化ポートを指定します。次に例を示します。
<?xml version="1.0"?> <webcache> <invalidation host="cache.mycompany.com" port="4001" authorization="0510198d5df8efd5779406342be2528aa0cccb179ea6b77baf49f019f5075a3a11"/> </webcache>
JAWCではシステム・プロパティ・ファイルを使用して、この構成ファイルを検索します。このシステム・プロパティをOracle WebLogic Serverに設定するには、PDK-Javaがインストールされている特定のインスタンス(たとえば、MW_HOME/wlserver_10.3/.product.properties
)について、.product.properties
ファイルに適切な1行を追加して、そのインスタンスを再起動します。
注意: キャッシュ構成ファイルの場所はシステム・プロパティとして定義されるため、サーバー・インスタンスごとに定義できるキャッシュは1つのみです。各Oracle Web Cache構成の背後に、2つの異なるWebプロバイダ・インスタンスを指定することはできません。 |
provider.xml
でタグの組合せを使用すると、ポートレット全体またはそのページの一部に対して自動無効化ベースのキャッシュをアクティブ化できます。自動無効化ベースのキャッシュをオンにするには、それを、次に示すように各ページまたはレンダラのレベルで宣言して、無効化ベースのキャッシュがすべてのページに対してアクティブ化されていることを示す必要があります。
<useInvalidationCaching>true</useInvalidationCaching>
ポートレットで(編集モードまたはデフォルト編集モードでの)パーソナライズをサポートしている場合は、レンダラに対しても<autoInvalidate>true</autoInvalidate>
を宣言できます。編集モードで「OK」または「適用」をクリックすると、この宣言によって、キャッシュされたポートレット・コンテンツがすべて無効化されます。したがって、パーソナライズされた設定に基づいて、新しいマークアップが生成されます。
ページをキャッシュに保持する最大時間は、次の時間についての最小時間となります。
「グローバル設定」ページの「キャッシュ」タブに定義されているOracle Portalの有効期間の最大値
Oracle Portalで有効期間の最大値が指定されていない場合は、Webプロバイダのデフォルト(24時間)
<pageExpires>
タグがある場合はその時間(分)。
provider.xml
の次の抜粋部分では、このポートレットは最大5分間キャッシュされ、パーソナライズ時には自動的に無効化されるように指定されています。
<renderer class="oracle.portal.provider.v2.render.RenderManager"> <contentType>text/html</contentType> <renderContainer>true</renderContainer> <autoRedirect>true</autoRedirect> <autoInvalidate>true</autoInvalidate> <showPage class="oracle.portal.provider.v2.render.http.ResourceRenderer"> <resourcePath>/htdocs/invalidation/invalidation1.jsp</resourcePath> <useInvalidationCaching>true</useInvalidationCaching> <pageExpires>5</pageExpires> </showPage> <editPage class="oracle.portal.sample.v2.devguide.invalidation. InvalidationEditRenderer"/></renderer>
注意: pageExpires タグは、通常の有効期限ベースのキャッシュでも使用します。これら2つの形式のキャッシュは、相互に排他的です。無効化ベースのキャッシュは、Webプロバイダと同じ場所にあるOracle Web Cacheインスタンスで発生します。有効期限ベースのキャッシュを使用して格納されたページは、Oracle Portalの中間層にキャッシュされます。 |
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
リクエストの処理、またはなんらかの情報の更新が行われたときに、ポートレットのキャッシュされたバージョンを無効化する必要が生じる場合があります。このような場合は、手動でキャッシュを無効化できます。
PDK-Javaに付属する無効化ベースのキャッシュのポートレット・サンプルには、コンテンツがキャッシュされた時刻、および無効化リクエストをトリガーするためのリンクを表示する単一のポートレットが含まれています。Webプロバイダに対するページ・リクエストがキャッシュを介して初めて行われたときは、そのレスポンスがキャッシュされます。ポートレットのコンテンツに対する後続のリクエストは、Oracle Web Cacheからコンテンツを戻すことによって実行されます。ポートレット下部にあるリンクをクリックすると、キャッシュからポートレットを削除する無効化リクエストがプロバイダで生成されます。ポートレットに対する次のリクエストはプロバイダに転送され、プロバイダは現在の時刻で新しいポートレットを生成します。
Oracle Web Cacheに対する無効化コールを実行するには、最初に、ServletInvalidationContext
オブジェクトへのハンドルを用意する必要があります。このハンドルは、ServletInvalidationContextFactory
クラスのstatic getServletInvalidationContext()
メソッドをコールすると取得できます。
ハンドルを取得した後は、キャッシュ・キーを指定する必要があります。キャッシュ・キーでは、無効化する対象が、特定のポートレット・インスタンスか、あるポートレットのすべてのインスタンスか、またはあるプロバイダが管理するすべてのポートレットかを指定する必要があります。このタスクを実行するには、ServletInvalidationContext
クラスのメソッド、またはそのスーパー・クラスInvalidationContext
のメソッドを使用します。ここでは、特定のユーザー(ユーザー・レベル)についてポートレットをキャッシュするかどうかを指定できます。キャッシュ・キーにユーザーが指定されていない場合、キャッシュされたコンテンツはすべてのユーザーに戻されます。これは、システム・レベルのキャッシュを使用していることを意味します。
次の例は、ポートレット・インスタンスを無効化し、setFullProviderPath()
およびsetPortletReference()
メソッドをコールします。キャッシュ・キーが設定されている場合は、InvalidationContext
オブジェクトのinvalidate()
メソッドをコールします。このメソッドは、無効化メッセージをOracle Web Cacheに送信します。
ServletInvalidationContext inv = ServletInvalidationContextFactory.getServletInvalidationContext(); inv.setFullProviderPath ((ServletPortletRenderRequest)pReq); inv.setPortletReference (pReq.getPortletReference()); int num = inv.invalidate();
詳細は、Web Cacheのサンプル・プロバイダを参照してください。
有効化ベースのキャッシュの追加は多少複雑ですが、プロバイダに対するどのリクエストがキャッシュ・ヒットであるかを厳密に制御できます。ここでは、ポートレット内のデータが変更された場合のみキャッシュを更新する例を説明します。このアルゴリズムを実装するには、prepareResponse
メソッドを上書きする必要があります。BaseManagedRenderer.prepareResponse
メソッドの署名は次のとおりです。
public boolean prepareResponse(PortletRenderRequest pr) throws PortletException, PortletNotFoundException
使用しているバージョンのprepareResponse()
で、次の処理を実行する必要があります。
キャッシュされたバージョン識別子を取得します。この識別子は、HttpPortletRendererUtil.getCachedVersion()
メソッドをコールすることで、PPEによってレンダリング・リクエストに設定されます。
public static java.lang.String getCachedVersion (PortletRenderRequest request)
以前にキャッシュされたバージョンが有効であることをポートレットが検出した場合は、HttpPortletRendererUtil.useCachedVersion()
メソッドをコールして適切なヘッダーを設定する必要があります。また、RenderManager
に対しては、ポートレット本体をレンダリングするためにrenderBody()
をコールする必要がないことが指示されます。
public static void useCachedVersion(PortletRenderRequest request)
これ以外の場合は、HttpPortletRendererUtil.setCachedVersion()
を使用して、新しいバージョンのポートレットを生成します。このポートレットがキャッシュされます。また、PPEに対しては、renderBody()
メソッドをコールして、ポートレットのコンテンツを再生成する必要があることが指示されます。
public static void setCachedVersion(PortletRenderRequest request, java.lang.String version, int level) throws java.lang.IllegalArgumentException
有効化ベースのキャッシュの場合、provider.xml
を更新する必要はありません。ポートレットを表示するには、ページをリフレッシュするか、ポートレットをページに追加してコンテンツを更新します。コンテンツが変更されている場合、ポートレットは新しいコンテンツを表示します。コンテンツが変更されていない場合は、キャッシュされたバージョンのポートレットが表示されます。
この項では、モバイル機器のPDK-Javaポートレットを拡張する方法について説明します。この項に進む前に、モバイル対応型のポートレットの構築ガイドライン(6.1.4項「モバイル・ポートレットのガイドライン」、およびPDK-Javaを使用したポートレットの構築方法(7.2項「PDK-Javaポートレットの拡張」について確認しておく必要があります。
モバイル機器のポートレットを正しく構築する手順は、次のとおりです。
ポートレットの表示リクエストに応じてOracleAS Wireless XMLを生成するJSPを作成します。ポートレットのJSPは、組込みレンダラであるoracle.portal.provider.v2.render.http.ResourceRenderer
によって管理および制御されます。
このレンダラを使用して、表示モードごとに個別のリソース(JSP)を定義することや、表示モードごとにコールするJSPを定義することが可能です。このため、表示モードを処理するためのJSPを、リクエストされるコンテンツがHTMLかOracleAS Wireless XMLかに応じて複数個定義できます。たとえば、この機能を使用して、宝くじポートレットのモバイル機器へのレンダリングを別のJSPに行わせることができます。このサンプルでは、mlotto.jsp
がモバイル・レンダリングを生成します。
contentType
宣言は、ソース・コードの先頭行にあります。JSPレスポンスのコンテンツ・タイプは、text/vnd.oracle.mobilexml
に設定されています。これは、OracleAS Wireless XMLのMIMEタイプ名です。すべてのモバイル・レスポンスが正常に動作するには、そのコンテンツ・タイプをこの値に設定する必要があります。
<%@ page session="false" contentType="text/vnd.oracle.mobilexml" %>
<%@ page import="oracle.portal.sample.v2.devguide.lottery.LottoPicker" %>
<% LottoPicker picker = new LottoPicker();
picker.setIdentity(request.getRemoteAddr() ); %>
<SimpleText>
<SimpleTextItem />
<SimpleTextItem>Your numbers:</SimpleTextItem>
<SimpleTextItem />
<SimpleTextItem HALIGN="CENTER" >
<%
int [] picks = picker.getPicks();
for (int i = 0; i < picks.length; i++) {
out.print(picks[i] + " ");
}
out.println("");
%>
</SimpleTextItem>
</SimpleText>
ポートレットがOracleAS Wireless XMLレスポンスを生成できるように、provider.xml
を変更してポートレット定義にacceptContentType
タグを追加します。各acceptContentType
タグは、ポートレットがレンダリング可能な個別のコンテンツ・タイプを定義します。この値は、コンテンツのMIMEタイプです。この場合、宝くじポートレットは、HTML(text/html
)およびOracleAS Wireless XML(text/vnd.oracle.mobilexml
)を生成可能であることを宣言します。
<acceptContentType>text/html</acceptContentType>
<acceptContentType>text/vnd.oracle.mobilexml</acceptContentType>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
provider.xml
で表示モードに対するJSPレンダラのマッピングを宣言します。
コンテンツ・タイプ別に関連表示モードのレンダリング・ハンドラを定義する必要があります。1つのshowPage
宣言では、HTMLレスポンスをレンダリングするJSPを識別します。別の宣言では、OracleAS Wireless XMLレスポンスをレンダリングするJSPを識別します。ここではクラス属性が必要ですが、より簡単な場合は、クラスはデフォルトのままでかまいません。showPage
宣言内の次のようなresourcePath
およびcontentType
タグを使用して、特定のJSPと特定のコンテンツ・タイプの関連付けを表現します。
resourcePath
は、このモードをレンダリングするためのJSPを定義します。
contentType
は、このJSPのレスポンス・タイプを定義します。
ResourceRenderer
は、宝くじポートレットの表示リクエストを受信すると、HTMLレスポンスをレンダリングする場合はlotto.jsp
を起動し、OracleAS Wireless XMLをレンダリングする場合はmlotto.jsp
を起動します。次のコードは、provider.xml
でこの関係を表現する方法を示します。
<renderer class="oracle.portal.provider.v2.render.RenderManager"> <contentType>text/html</contentType> <renderContainer>true</renderContainer> <showPage class="oracle.portal.provider.v2.render.http.ResourceRenderer"> <resourcePath>/htdocs/lottery/lotto.jsp</resourcePath> <contentType>text/html</contentType> </showPage> <showPage class="oracle.portal.provider.v2.render.http.ResourceRenderer"> <resourcePath>/htdocs/lottery/mlotto.jsp</resourcePath> <contentType>text/vnd.oracle.mobilexml</contentType> </showPage> ... </renderer>
注意: ResourceRenderer (および任意のポートレット)は、リクエストのAcceptヘッダーによって受信したリクエストのタイプを判定します。Acceptヘッダーは、特定のリクエストについて受信可能なレスポンス・タイプを定義する標準のHTTPヘッダーです。複数のコンテンツ・タイプを受信可能である場合は、HTTPヘッダーは複数の値からなるリストになります。複数の値がある場合、これらは優先順位の高い値から低い順に並べられます。Oracle Portalは、Acceptヘッダーでポートレットに渡される値を制御します。HTMLリクエストの場合、Acceptヘッダーは次のようになります。
text/html, text/xml, text/vnd.oracle.mobilexml これらの値は、Oracle PortalはHTMLレスポンスを優先するがXMLおよびOracleAS Wireless XMLも受信することを示します。 モバイル・リクエストの場合、Acceptヘッダーは次のようになります。 text/vnd.oracle.mobilexml, text/xml これらの値は、Oracle PortalはOracleAS Wireless XMLを優先するが、OracleAS Wireless XMLに変換されるスタイルシート参照が含まれる一般的なXMLも受信することを示します。
|
短いタイトルを宣言します。短いタイトルは、ポートレット名の短い書式であり、表示領域が制限されているときに使用されます。特に、Oracle Portalは、モバイル・リクエストに応じて生成されたページ・メニューでポートレットをメニュー・アイテムとしてレンダリングするときに、短いタイトルを使用します。ポートレットによって短いタイトルが登録された場合、Oracle Portalはこれをメニュー・アイテムのラベルとして使用します。それ以外の場合は、ポートレットの標準タイトルを使用します。短いタイトルを宣言するには、provider.xml
のポートレットのメタデータ・セクションにshortTitle
タグを含めます。
<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
<id>2</id>
<name>Lottery</name>
<title>Lottery Portlet</title>
<shortTitle>Lottery</shortTitle>
...
</portlet>
短いタイトルのパーソナライズをサポートします。ポートレットの短いタイトルは、ページ上のポートレット・インスタンスを参照するメニュー・アイテムのラベルとしてユーザーに表示されるため、すべてのポートレットでユーザーが短いタイトルをパーソナライズできるようにすることをお薦めします。PDK-Javaには、短いタイトルと標準タイトルの両方を管理する基本データ・クラスが用意されています。
oracle.portal.provider.v2.personalize.NameValuePersonalizationObject
NameValuePersonalizationObject
は、標準タイトルと短いタイトルの両方を管理します。これには、値を取得および設定するためのメソッドが含まれます。パーソナライズ・コードは、フォーム表示とフォーム送信という2つの部分に分割されます。このロジックは、最初に現在のデータ・パーソナライズ・オブジェクトを取得します。次に、これがフォーム送信であるかどうかを確認します。フォーム送信である場合、データ・パーソナライズ・オブジェクトの値を更新し、これらの値をリポジトリに書き戻し、制御を戻します。その後、PDK-Javaは、このフォームにリダイレクトしますが、その際、これが新しい値を使用してフォームを再表示するフォーム送信であることを示すパラメータは使用しません。この場合、JSPは、現在のパーソナライズ値が含まれるパーソナライズ・ページを使用して応答します。
ポートレットではこのクラスまたはサブクラスを使用してこの基本サポートを継承するようにすることをお薦めします。宝くじの例でサポートされているパーソナライズは、これら2つのタイトルのみです。このため、custom.jsp
でNameValuePersonalizationObject
クラスを直接使用しています。
<%@ page session="false" import="oracle.portal.provider.v2.*" %> <%@ page import="oracle.portal.provider.v2.http.*" %> <%@ page import="oracle.portal.provider.v2.render.*" %> <%@ page import="oracle.portal.provider.v2.personalize.NameValuePersonalizationObject" %> <%-- This page both displays the personalization form and processes it. We display the form if there isn't a submitted title parameter, else we apply the changes --%> <% PortletRenderRequest portletRequest = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); String title = request.getParameter("lotto_title"); String sTitle = request.getParameter("lotto_short_title"); String actionParam = PortletRendererUtil.getEditFormParameter(portletRequest); String action = request.getParameter(actionParam); NameValuePersonalizationObject data = (NameValuePersonalizationObject) PortletRendererUtil.getEditData(portletRequest); // Cancel automatically redirects to the page // -- so will only receive 'OK' or 'APPLY' if (action != null) { data.setPortletTitle(title); data.setPortletShortTitle(sTitle); PortletRendererUtil.submitEditData(portletRequest, data); return; } // otherwise just render the form title = data.getPortletTitle(); sTitle = data.getPortletShortTitle(); %> <TABLE BORDER="0"> <TR> <TD WIDTH="20%"> <P ALIGN="RIGHT">Title: </TD> <TD WIDTH="80%"> <INPUT TYPE="TEXT" NAME="lotto_title" VALUE="<%= title %>" SIZE="20"> </TD> </TR> <TR> <TD WIDTH="20%"> <P ALIGN="RIGHT">Short Title: </TD> <TD WIDTH="80%"> <INPUT TYPE="TEXT" NAME="lotto_short_title" VALUE="<%= sTitle %>" SIZE="20" MAXLENGTH="20"> </TD> </TR> </TABLE>
パーソナライズされた短いタイトルのレンダリングをサポートします。短いタイトルのパーソナライズを追加した場合は以後、モバイル・ページのレスポンスではポートレット側で自分自身をメニュー・アイテムとしてレンダリングする必要があります。モバイル機器では表示される画面が小さいため、ポートレットは同時にレンダリングされることはありません。ユーザーには、特定のページで、ポートレットへのリンクのメニューが表示されます。ユーザーは、このメニューから各ポートレットにナビゲートしてコンテンツを表示します。このモデルをより効率的にサポートするために、Oracle Portalにはリンク・モードが用意されています。このモードでは、ポートレットがそれ自体に対するリンク参照を生成します。
HTMLリクエストの場合、リンク・モードではアンカー・タグhref
が生成されます。モバイル・リクエストの場合、リンク・モードではsimpleHref
タグが生成されます。現在、Oracle Portalは、モバイル・ページのレスポンスを組み立てるときにリンク・モードのリクエストのみを送信します。このため、リンク・モードについては、text/vnd.oracle.mobilexml
コンテンツ・タイプのレンダリングをサポートするのみでよいのです。ポートレットでHTMLレンダリングも行う場合は、HTMLリンク・モードもサポートすることをお薦めします。
宝くじポートレットの例では、次のように個々のJSPで各リンク・レンダリングを実装しています。
milotto.jsp
には、text/vnd.oracle.mobilexml
リンク・レスポンスを生成するコードが含まれています。
anchorlotto.jsp
には、text/html
リンク・レスポンスを生成するコードが含まれています。
それぞれのコードはほぼ同じです。リンク・モードをサポートする目的は、パーソナライズされた短いタイトルをレンダリングすることにあるため、コードはリポジトリから最初に短いタイトルを取得します。次に、リクエストされたマークアップに適したリンク・タグを生成します。取得された短いタイトルは、リンクのラベルとしてレンダリングされます。Oracle Portalは、ページ上のポートレットの特定の使用方法を参照するURLを作成する必要があるため、リンクで使用されるURLを作成し、これをポートレットに渡します。ポートレットは、このURLを使用してリンクを作成します。このリンクのURLは、リクエストのPageURL
パラメータから取得されます。milotto.jsp
のコードは、次のとおりです。
<%@ page session="false" contentType="text/vnd.oracle.mobilexml" %> <%@ page import="oracle.portal.provider.v2.http.HttpCommonConstants" %> <%@ page import="oracle.portal.provider.v2.render.*" %> <%@ page import="oracle.portal.provider.v2.personalize.NameValuePersonalizationObject" %> <%@ page import="oracle.portal.utils.xml.v2.XMLUtil" %> <% PortletRenderRequest portletRequest = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); NameValuePersonalizationObject data = (NameValuePersonalizationObject) PortletRendererUtil.getEditData(portletRequest); String title = data.getPortletShortTitle(); // if short title is empty then use the title if (title == null || title.length() == 0) title = data.getPortletTitle(); %> <SimpleHref target="<%= XMLUtil.escapeXMLAttribute( portletRequest.getRenderContext().getPageURL()) %>"> <%= XMLUtil.escapeXMLText(title) %> </SimpleHref>
注意: URLおよび短いタイトル・ラベルとして出力されるテキストは、特別なXMLエスケープ・ユーティリティを介して渡されます。text/vnd.oracle.mobilexml はXMLコンテンツ・タイプであるため、生成されるレスポンスは、特定の文字のエスケープを必要とするXMLルールに準拠する必要があります。静的テキストを生成する場合を除き、テキストはすべて、提供されている2つのユーティリティを使用してエスケープすることをお薦めします。2つのユーティリティ・メソッドを使用するのは、テキストがタグ属性値とタグ値のどちらであるかによって、エスケープを必要とするキャラクタ・セットが異なるためです。 |
リンク・モードのサポートを宣言します。リンク・モードを実装した後は、provider.xml
を更新してリンク・モードの存在を示す必要があります。リンク・モードを宣言するには、次のようなコードをprovider.xml
に追加します。
<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
<id>2</id>
<name>Lottery</name>
...
<showLink>true</showLink>
<showEdit>true</showEdit>
<showEditToPublic>false</showEditToPublic>
...
</portlet>
JSPをリンク・モードにバインドします。ポートレットは、表示モードとJSPレンダラ間のマッピングを宣言する必要があります。リンク・モードの構文は、表示モードの構文と同じです。
<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition"> <id>2</id> <name>Lottery</name> ... <renderer class="oracle.portal.provider.v2.render.RenderManager"> <contentType>text/html</contentType> <renderContainer>true</renderContainer> <linkPage class="oracle.portal.provider.v2.render.http.ResourceRenderer" > <resourcePath>/htdocs/lottery/anchorlotto.jsp</resourcePath> <contentType>text/html</contentType> </linkPage> <linkPage class="oracle.portal.provider.v2.render.http.ResourceRenderer" > <resourcePath>/htdocs/lottery/milotto.jsp</resourcePath> <contentType>text/vnd.oracle.mobilexml</contentType> </linkPage> ... </renderer> ... </portlet>
モバイル機器をより効率的にサポートするために、Oracle Portalは、レスポンスを生成するための追加情報をポートレットに渡します。この情報は、次のように3つの大きなカテゴリに分けられます。
Oracle Portalは、ポートレットによるパーソナライズのレンダリングまたはページの編集をリクエストするときにモバイル機能を有効化するかどうかを示すフラグを送信します。ポートレットは、この情報を使用して、必要に応じてモバイル固有の属性をパーソナライズ・ページで含めるか除外するかを指定します。
ポートレットは、PortletRenderRequest
オブジェクトを使用してこの情報にアクセスします。
...
if (portletRequest.getPortalConfig().isMobileEnabled()) {
...
}
...
OracleAS Wirelessは、レスポンス用としてOracle Portalに転送するリクエストにユーザーの位置を追加します。このユーザーの位置情報は、ユーザーの実際の位置(ユーザーのデバイスがこの機能をサポートしている場合)またはプロファイルされている位置によって決まります。ユーザーの位置は、ProviderUser
オブジェクトによって公開されます。このオブジェクトには、PortletRenderRequest
オブジェクトからアクセスできます。位置対応型のポートレットは、この情報を使用して生成対象のコンテンツを調整できます。
... UserLocation location = portletRequest.getUser().getLocation(); if (location != null) { ... } ...
Oracle Portalはリクエストごとに、リクエスト側のデバイスに関する特性をポートレットに送信します。この情報は、モバイル・リクエストのみではなくすべてのポートレット・リクエストについて送信されます。この情報は、リクエストを行うデバイスのタイプ、そのレイアウト方向、デバイスが処理可能な最大レスポンス・サイズ、デバイスとの接続がセキュアかどうかを分類するものです。表7-3は、使用可能なデバイスのタイプを示します。
表7-3 デバイスのクラス
Class | 説明 |
---|---|
voice |
音声アクセス番号をコールする通常の電話など、音声専用デバイスを示します。 |
micromessenger |
SMS電話またはポケットベルなど、テキスト・メッセージ・デバイスを示します。 |
messenger |
電子メールなどの一般的なメッセージのデバイスを示します。 |
microbrowser |
WAP電話など、マークアップ・ブラウザをサポートする小型サイズの表示デバイスを示します。 |
pdabrowser |
PalmまたはPocketPCなど、中型サイズの表示デバイスを示します。 |
pcbrowser |
デスクトップ・ブラウザを使用する大型サイズの表示デバイスを示します。 |
ポートレットは、リクエストを行うデバイスのタイプに基づいてレスポンスのコンテンツのレイアウトまたは表現を変更できます。たとえば、ポートレットは、幅の広い表を、画面の小さなデバイス用に列グループがまとめてリンクされた一連の画面に分割できます。
最大レスポンス・サイズは、ポートレットが戻すデータ量を制限するためのヒントとなります。このサイズはバイト単位で示されます。最大レスポンス・サイズが0である場合、このサイズが不明であることを示します。
ポートレットは、PortletRenderRequest
オブジェクトを使用してこの情報にアクセスします。
... DeviceInfo deviceInfo = portletRequest.getDeviceInfo(); switch (deviceInfo.getDeviceClass()) { case DeviceInfo.DeviceClass.MICROBROWSER: renderMicroBrowser(portletRequest); break; default: renderDefault(portletRequest); break; } ...
7.2.3.3.4項「ポートレット内でのナビゲーションの実装」のほとんどの情報は、モバイル・ポートレットの開発にも関連しています。ただし、記載されている一部のユーティリティは、HTMLをレンダリングするポートレットに固有のものです。SimpleResult
をレンダリングするポートレットについては、表7-4に示されているものと同等のユーティリティが用意されています。
表7-4 同等のHTMLおよびSimpleResultユーティリティ
HTMLユーティリティ | SimpleResultユーティリティ |
---|---|
UrlUtils.constructHTMLLink |
UrlUtils.constructMXMLLink |
UrlUtils.htmlFormHiddenFields |
UrlUtils.mxmlFormHiddenFields |
UrlUtils.emitHiddenField |
UrlUtils.emitMxmlHiddenField |
次の例は、シソーラス・サンプルをモバイル対応型のポートレットに対応させる方法を示します。モバイル・ポートレットとしてデプロイする場合、JSPのどちらのセット(HTMLとSimpleResult
)もデプロイされます。これらのJSPは、そのHTMLの対応ユーティリティを補完するものであり、これらを置き換えるものではありません。また、これらのJSPはSimpleResult
をそのマークアップとして使用します。ナビゲーション・パラメータの値は、次のデスクトップJSPではなく次のモバイルJSPを指し示すように変更されています。
mThesaurusForm.jsp
:
<% PortletRenderRequest pRequest = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); String paramNameQ = "q"; String qualParamNameQ = HttpPortletRendererUtil.portletParameter(pRequest, paramNameQ); %> <!-- Output the MXML content --> <SimpleText> <SimpleTitle>Thesaurus</SimpleTitle> <SimpleTextItem>Enter the word you wish to search for:</SimpleTextItem> <SimpleForm method="POST" target="<%= UrlUtils.htmlFormActionLink(pRequest,UrlUtils.PAGE_LINK) %>"> <%=UrlUtils.mxmlFormHiddenFields (pRequest.getRenderContext().getPageURL()) %> <%= UrlUtils.emitMxmlHiddenField( HttpPortletRendererUtil.portletParameter(request, "next_page"), "htdocs/path/mThesaurusLink.jsp" ) %> <SimpleFormItem type="text" size="20" name="<%= qualParamNameQ %>" value="" /> </SimpleForm> </SimpleText>
mThesaurusLink.jsp
:
<% PortletRenderRequest pRequest = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); String paramNameQ = "q"; String paramNameNextPage = "next_page"; String qualParamNameQ = HttpPortletRendererUtil.portletParameter(pRequest, paramNameQ); String qualParamNameNextPage = HttpPortletRendererUtil.portletParameter(pRequest, paramNameNextPage); String paramValueQ = pRequest.getQualifiedParameter(paramNameQ); %> <!-- Output the MXML content --> <SimpleText> <SimpleTitle>Words similar to <%= paramValueQ %></SimpleTitle> <% Thesaurus t = new Thesaurus(); String[] relatedWords = t.getRelatedWords(paramValueQ); NameValue[] linkParams = new NameValue[2]; linkParams[0] = new NameValue( qualParamNameNextPage, "htdocs/path/mThesaurusLink.jsp"); for (int i=0; i<relatedWords.length; i++) { linkParams[1] = new NameValue( qualParamNameQ, relatedWords[i]); %> <SimpleTextItem> <%= relatedWords[i] %> <SimpleBreak/> <%= UrlUtils.constructMXMLLink( pRequest, pRequest.getRenderContext().getPageURL(), "(words related to " + relatedWords[i] + ")", "", linkParams, true, true)%> </SimpleTextItem> <% } %> <SimpleTextItem> <SimpleHref target="<%=XMLUtil.escapeXMLAttribute( pRequest.getRenderContext().getPageURL())%>"> Reset Portlet </SimpleHref> </SimpleTextItem> </SimpleText>
この項では、異なる言語でレンダリングできるJavaポートレットの作成方法を説明します。ポートレットで使用する言語は、そのポートレットを表示しているポータルの言語設定によって決まります。
この項を終了すると、必要な数の言語をサポートするポートレットを作成できるようになります。また、既存のポートレットを多言語をサポートするように変換することもできます。ポートレットが複数の言語をサポートするように作成されていると、新しい言語をプラグ・インするのが簡単になります。多言語のJavaポートレットの基本モデルは、標準のJava国際化モデルと似ています。Javaの国際化に関する知識がある場合は、容易にこのプロセスを習得できます。
この項のタスクを実行するには、次の前提が必要です。
6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」を読んで理解していること。
ウィザードで作成したポートレットがページに正常に追加されていること。
これは、次の2つのタスクから構成されます。
6.5項「Oracle JDeveloperを使用したOracle PDK-Javaポートレットの構築」では、Javaポートレット・ウィザードを使用してポートレットを作成しました。ウィザードで作成した基本的なメッセージは1つの言語でのみ利用でき、表示するテキストはポートレットのレンダラ・クラスにハードコーディングされています。ポートレットを複数の言語で利用できるようにするには、このような言語依存要素を、リソース・バンドルと呼ばれる独自のクラスに格納する必要があります。
リソース・バンドルの作成
リソース・バンドルは、ポートレットで利用する言語ごとに必要です。また、ポータルで選択された言語設定に対応するリソース・バンドルがない場合に使用するリソース・バンドルも作成する必要があります。次のタスクを実行します。
デフォルト・リソース・バンドルの作成
次の手順を実行します。
Oracle JDeveloperで、java.util.package
のListResourceBundle
を拡張するMyProviderBundle
というJavaクラスを作成します。このクラスには、オブジェクトの多次元配列が含まれており、この配列には、JSPの表示ページにある各言語依存要素を表すキー値のペアが保持されます。この実装は次のコードで示されます。
package mypackage2; import java.util.ListResourceBundle; public class MyProviderBundle extends ListResourceBundle { public static String HELLO_MSG = "MyPortletHelloMessage"; public static String INFO_MSG = "MyPortletInfoMessage"; public Object[][] getContents() { return contents; } static private final Object[][] contents = { {HELLO_MSG, "Hello"}, {INFO_MSG, "This is the show page of the portlet and it is being generated in the default language!"} }; }
MyProviderBundle
を保存します。
サポートする他の言語のためのリソース・バンドルの作成
ここで、ポートレットでサポートする各言語について、リソース・バンドル・クラスを作成する必要があります。それぞれのクラスの名前は、デフォルトのリソース・バンドル・クラスと同じである必要がありますが、末尾に言語コードを付加します。たとえば、フランス語をサポートする場合は、MyProviderBundle_fr
というJavaクラスを作成します。言語コードfr
は、言語設定がフランス語に設定されている場合にポータルのロケール・オブジェクトによって使用されるコードと同じです。
ロケールの詳細は、Javadocでjava.util.Locale
を参照してください。次の「Portlet Development」ページの「Java Doc API」をクリックして、OTNのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/portlet_development_10g1014.html
Oracle Portalで言語設定を変更する場合は、現行のロケール・オブジェクトの値、つまりロケール・オブジェクトの言語コードを変更します。言語コードは、言語の呼称に関するISO:639コードに準拠しています。サポートされている他の言語のリソース・バンドルを作成する手順は、次のとおりです。
フランス語のリソース・バンドルを作成するには、前述したように、MyProviderBundle_fr
というJavaクラスを作成します。
デフォルトのリソース・バンドルをテンプレートとして使用し、英語文字列を対応するフランス語に置き換えます。例を次に示します。
package mypackage2; import java.util.ListResourceBundle; public class MyProviderBundle_fr extends ListResourceBundle { public Object[][] getContents() { return contents; } static private final Object[][] contents = { {MyProviderBundle.HELLO_MSG, "Bonjour"}, {MyProviderBundle.INFO_MSG, "Cette page est le 'show mode' de la portlet et est generee dans la langue par defaut."} }; }
MyProviderBundle_fr
を保存します。
リソース・バンドルを作成する各言語について、手順1〜3を繰り返します。その際、クラス名を適切な言語コードを持つ名前に変更し、メッセージ文字列を適切な言語の同等のメッセージに変更します。
レンダラの更新
ここで作成したリソース・バンドルを使用するには、JSPの表示ページを編集し、ハードコーディングされたメッセージを、実行時にポータルのロケール・オブジェクトと最も密接に対応するリソース・バンドルからメッセージを取り出す参照に置き換えます。レンダラを更新する手順は、次のとおりです。
表示ページを表すJSPを開き、次のように変更します。
<%@page contentType="text/html; charset=windows-1252" import="oracle.portal.provider.v2.render.PortletRenderRequest" import="oracle.portal.provider.v2.http.HttpCommonConstants" import="java.util.ResourceBundle" %> <% PortletRenderRequest pReq = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); <!-- Get a resource bundle object for the current language. --> ResourceBundle b = ResourceBundle.getBundle("mypackage2.MyProviderBundle",pReq.getLocale()); %> <!-- Pull the message from the appropriate resource bundle. --> <P> <%= b.getString(mypackage2.MyProviderBundle.HELLO_MSG) %> <%= pReq.getUser().getName() %>.</P> <P> <%= b.getString(mypackage2.MyProviderBundle.INFO_MSG) %></P>
JSPページを変更します。
これで、ポートレットをリフレッシュして変更を表示できます(図7-12)。
フランス語のメッセージを表示するには、「言語の設定」ポートレットで言語を英語からフランス語に設定します(図7-13)。
ポートレット内のテキストは変更されますが、ポートレット・タイトルはデフォルト言語の英語のままであることに注意してください。また、次の項で説明しているように、provider.xml
からリソース・バンドルを指し示すことによって、ポートレットで適切なポートレット属性(ポートレット名、ポートレット・タイトル、ポートレットの説明など)を設定できます。
プロバイダの定義ファイルprovider.xml
には、ポートレット名や説明などポートレットを記述する多数の属性が定義されています。これらの属性は、表示モードでポートレットのタイトル・バーなどで使用されるため、翻訳する必要があります。翻訳を提供する方法は2通りあり、いずれかを選択します。両方の方法について、次の項で概略を説明します。
方法1: プロバイダ・レベルでリソース・バンドルを使用
リソース・バンドルでポートレット属性に関する翻訳を提供し、リソース・バンドルで使用したキーを指定すると、provider.xml
でこれらのリソース・バンドルを使用するように指定できます。この方法では、任意のキーを使用できるため、プロバイダの各種ポートレットで対応する各属性に対して異なるキーを使用することによって、プロバイダのすべてのポートレットが使用できるリソース・バンドルのセットを1つのみにできます。この項では、次のタスクを説明します。
リソース・バンドルの更新
次の手順を実行します。
デフォルトのリソース・バンドルMyProviderBundle.java
を開きます。
ポートレット属性を表すリソース・バンドルに文字列を追加し、その文字列のテキストを追加します。
package mypackage2; import java.util.ListResourceBundle; public class MyProviderBundle extends ListResourceBundle { public static String HELLO_MSG = "MyPortletHelloMessage"; public static String INFO_MSG = "MyPortletInfoMessage"; public static String PORTLET_NAME = "FirstPortletName"; public static String PORTLET_TITLE = "FirstPortletTitle"; public static String PORTLET_SHORT_TITLE = "FirstPortletShortTitle"; public static String PORTLET_DESCRIPTION = "FirstPortletDescription"; public static String TIMEOUT_MESSAGE = "FirstPortletTimeoutMessage"; public Object[][] getContents() { return contents; } static private final Object[][] contents = { {HELLO_MSG, "Hi"}, {INFO_MSG, "This is the show page of the portlet and it is being generated in the default language!"}, {PORTLET_NAME, "MyNLSPortlet"}, {PORTLET_TITLE, "My NLS Portlet"}, {PORTLET_SHORT_TITLE, "MyNLSPortlet"}, {PORTLET_DESCRIPTION, "My first ever NLS portlet, using my MyPortletShowPage.jsp"}, {TIMEOUT_MESSAGE, "Timed out waiting for MyNLSPortlet"} }; }
MyProviderBundle.java
を保存します。
MyProviderBundle_fr.java
を開きます。MyProviderBundle
で宣言した文字列と一致するフランス語文字列を含むように変更します。
package mypackage2; import java.util.ListResourceBundle; public class MyProviderBundle_fr extends ListResourceBundle { public Object[][] getContents() { return contents; } static private final Object[][] contents = { {MyProviderBundle.HELLO_MSG, "Bonjour"}, {MyProviderBundle.INFO_MSG, "Cette page est le 'show mode' de la portlet et est generee en francais!"}, {MyProviderBundle.PORTLET_NAME, "MaPremierePortlet"}, {MyProviderBundle.PORTLET_TITLE, "Ma Portlet Multi-Langue"}, {MyProviderBundle.PORTLET_SHORT_TITLE, "Ma NLS Portlet"}, {MyProviderBundle.PORTLET_DESCRIPTION, "Ma premiere portlet multi-langue, utilisant mon renderer"}, {MyProviderBundle.TIMEOUT_MESSAGE, "Temps d'acces a la portlet demandee expire"} }; }
MyProviderBundle_fr.java
を保存します。
provider.xmlの更新
次の手順を実行します。
XMLプロバイダ定義ファイルを開き、ハードコーディングしたポートレット属性値を使用するかわりにリソース・バンドルを指すように変更します。
<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
<id>3</id>
<resource>mypackage2.MyProviderBundle</resource>
<nameKey>FirstPortletName</nameKey>
<titleKey>FirstPortletTitle</titleKey>
<ShortTitleKey>FirstPortletShortTitle</ShortTitleKey>
<descriptionKey>FirstPortletDescription</descriptionKey>
<timeout>10</timeout>
<timeoutMessageKey>FirstPortletTimeoutMessage</timeoutMessageKey>
<showEditToPublic>false</showEditToPublic>
<hasAbout>true</hasAbout>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
方法2: ポートレット・レベルでリソース・バンドルを作成
PDK-Javaでは、ポートレット属性の翻訳を提供するために使用できるリソース・バンドル・キーのセットが定義されます。これらのキーを使用すると、「方法1: プロバイダ・レベルでリソース・バンドルを使用」で実行したようにprovider.xml
ファイルでリソース・バンドル・キーを指定する必要がなくなります。ただし、プロバイダの各ポートレットに対して独立した一連のリソース・バンドルを提供する必要があります。これは、各ポートレットで使用するキーは同じである必要がありますが、その値は異なるためです。次のタスクを実行する必要があります。
リソース・バンドルの更新
次の手順を実行します。
デフォルトのリソース・バンドルMyProviderBundle.java
を開きます。
前述の項で実行した変更を削除し、oracle.portal.provider.v2.PortletConstants
をインポートします。これで、文字列のかわりに次の定数を参照できます。PortletConstants
を使用するときは、静的文字列を宣言する必要はありません。
{PortletConstants.NAME, "MyNLSPortlet"}, {PortletConstants.TITLE, "My NLS portlet"}, {PortletConstants.SHORTTITLE, "MyNLSPortlet"}, {PortletConstants.DESCRIPTION, "My first ever NLS portlet"}, {PortletConstants.TIMEOUTMSG, "Timed out waiting for MyNLSPortlet"}
MyProviderBundle.java
を保存します。
MyProviderBundle_fr.java
を開きます。前述の項で追加したポートレット属性を削除し、oracle.portal.provider.v2.PortletConstants
をインポートして、文字列のかわりに定数を参照します。
{PortletConstants.NAME, "MaPremierePortlet"}, {PortletConstants.TITLE, "Ma Portlet Multi-Langue"}, {PortletConstants.SHORTTITLE, "Ma NLS Portlet"}, {PortletConstants.DESCRIPTION, "Ma premiere portlet multi-langue, utilisant mon renderer"}, {PortletConstants.TIMEOUTMSG, "Temps d'acces a la portlet demandee expire"}
MyProviderBundle_fr.java
を保存します。
provider.xmlの更新
次の手順を実行します。
provider.xml
で、「方法1: プロバイダ・レベルでリソース・バンドルを使用」で実行したように文字列ごとに1つのタグを使用するのではなく、1つのタグのみを使用する必要があります。ファイル内の翻訳された文字列をすべて削除します。たとえば、<nameKey>
、<titleKey>
、<ShortTitleKey>
および<descriptionKey>
などです。次に、ポートレットIDとタイムアウト値の間に次のタグを追加します。
<resource>mypackage2.MyProviderBundle</resource>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
Java国際化の詳細は、Javaチュートリアルの「Internationalization trail」を参照してください。
この項では、Oracle Portalで使用するStrutsポートレットをOracle JDeveloperで作成するフレームワークについて説明します。Strutsタグ・ライブラリをOracle Portal Developer Kit(リリース9.0.4.0.2以上)からOracle JDeveloperに追加して既存のアプリケーションからStrutsポートレットを作成し、次にOracle PDK Javaポートレット・ウィザードを使用してJavaポートレットを作成する方法を説明します。この項では、次のタスクを説明します。
この項では、Apache StrutsをOracle Portalとともに使用する方法を説明します。Strutsは、Model-View-Controller(MVC)設計パターンの実装です。この項では、次のトピックについて説明します。
エンタープライズ・アプリケーションは、次のような複数の異なるタスクを実行します。
データ・アクセス
ビジネス・ロジックの実装
ユーザー・インタフェースの表示
ユーザーの相互作用
アプリケーション(ページ)フロー
MVC(Model-View-Controller)アーキテクチャは、データ表示などのアクティビティはデータ・アクセスから分離する必要があるという前提に基づいて、これらのタスクを区分する方法を提供します。このアーキテクチャによって、データソースをアプリケーションに簡単にプラグインでき、ユーザー・インタフェースをリライトする必要はありません。MVCでは、アプリケーションを論理的にモデル、ビューおよびコントローラの3つのレイヤーに区分できます。
モデル
モデルは、アプリケーション・データとビジネス・ロジック用のリポジトリです。モデルの目的の1つは、データベースからデータを取得し、データをデータベースに保持することです。また、モデルでは、ビューからデータにアクセス可能にするなどの方法でデータの公開を行い、ビューから入力されたデータの検証と消込みを行うためにビジネス・ロジック・レイヤーを実装します。アプリケーション・レベルでは、モデルは、ユーザー・インタフェースと表示されるビジネス・データの間で検証および抽象化のレイヤーとして機能します。データベース・サーバー自体は、モデルの永続的なレイヤーとして機能します。
ビュー
ビューは、JSPを使用して、モデルのデータをレンダリングします。ビューのコードには、ハードコーディングされたアプリケーションやナビゲーション・ロジックは含まれていませんが、ユーザー・ロールに基づいて条件付きデータを表示するなどのタスクを実行するロジックが含まれている場合があります。エンド・ユーザーが、ビューでレンダリングされたHTMLページ内で操作を実行すると、イベントがコントローラに送信されます。これによって、コントローラは次のステップを決定します。
コントローラ
コントローラはMVCパターンの重要な基軸です。ビューで実行されるすべてのユーザー操作は、コントローラを介して送信されます。コントローラは、ブラウザからのリクエストの内容に基づいて、次の操作を実行します。
コントローラを起動する方法はいくつかあります。たとえば、URL引数を使用して、リクエストを適切なコードにルーティングできます。MVCパターンでは、コントローラの機能を決定しますが、その動作は決定しません。
利点
MVCアーキテクチャによって、アプリケーションとその設計をモジュール単位で明確に表示できます。アプリケーション・ロジックの様々なコンポーネントとロールを区分することによって、開発者はアプリケーションを簡単で異なるコンポーネント(モデル、ビューおよびコントローラ)の集まりとして設計できます。このパターンは、保持や拡張が容易なアプリケーションの作成に役立ちます。たとえば、1つのビューを作成すると、同じビジネス・ロジックを使用して別のビューを簡単に作成できます。その使いやすさと再利用性のため、MVCパターンは、Webベースのアプリケーション開発で最も広く使用されているパターンです。
図7-14は、MVCパターンを従来のシン・クライアントのWebアプリケーションに適用する方法を示します。
Apache Strutsフレームワーク(http://struts.apache.org
)は、Webアプリケーション作成用の最も一般的なフレームワークの1つで、MVC設計パラダイムのJSPモデル2に基づくアーキテクチャを提供します。モデル2では、エンド・ユーザーのリクエストは、フローを制御し、JavaBeansまたはEJBなどのコンポーネントを使用してデータにアクセスして操作するサーブレットで管理されます。さらにモデル2では、JSPを使用して、アプリケーションのコンテンツをWebブラウザにレンダリングします。このモデルは、JSPがブラウザ・リクエストとデータ・アクセスを管理するJSPモデル1とは異なります。
Strutsフレームワークは、コントローラ・コンポーネントとして独自のHTTPサーブレットを提供します。Strutsフレームワークは、アプリケーションのページ・フローが含まれるXML構成ファイルによって起動されます。Strutsはモデルを提供しませんが、開発者は、EJB、TopLink、JDBCなどのデータ・アクセス・メカニズムにStrutsを統合できます。ビュー・コンポーネントを作成するための最も一般的なテクノロジはJSPです。Strutsには、ビュー・コンポーネントを作成するための様々なタグ・ライブラリが用意されています。ただし、現在、これらのタグの一部は、Java標準タグ・ライブラリ(JSTL)に取って代わられており、これらも使用される可能性があります。
注意: JSTLおよびJSFの詳細は、Apache Software FoundationのWebサイト(http://struts.apache.org/kickstart.html )で「FAQs」を参照してください。 |
Oracle Portal Developer Kitには、パーソナライズやキャッシュなどOracle Portal APIの使用方法に関する多数の例やドキュメントが含まれています。ポートレットAPIでは、アプリケーション・ロジックとビジネス・ロジックを統合できません。一方、Strutsフレームワークを使用すると、MVCアーキテクチャを利用して、企業ポータル内でアプリケーションを作成および公開できます。
Oracle Strutsポートレット
Strutsフレームワークを使用したポートレットの作成、または既存のStrutsアプリケーションからポートレットの生成を行うには、すべてのコンポーネントをJ2EEコンテナにデプロイする必要があります。Oracle Portalのコンテキストでは、StrutsアプリケーションはPPEによってコールされ、スタンドアロンのStrutsアプリケーションのようにブラウザではコールされません。図7-15に示すように、ポートレットの表示コールが送信されると、ページ・エンジンはStrutsポートレット・レンダラにリクエストを送信し、Strutsポートレット・レンダラはそのリクエストをApache Strutsコントローラ・サーブレットに転送します。
次に示すコードは、プロバイダ定義ファイル(provider.xml
)の一部です。
... <renderContainer>true</renderContainer> <renderCustomize>true</renderCustomize> <autoRedirect>true</autoRedirect> <contentType>text/html</contentType> <showPage class="oracle.portal.provider.v2.render.http.StrutsRenderer"> <defaultAction>showCustomer.do</defaultAction> </showPage> </renderer> ...
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
showPage
タグは、ポートレットの表示モードで実行されるビジネス・ロジックを定義します。StrutsポートレットのshowPage
には、次の2つの重要なコンポーネントが含まれます。
レンダラ・クラス(oracle.portal.provider.v2.render.http.StrutsRenderer
)。PPEからポートレット・リクエストを受信し、プロキシとして機能してリクエストをStrutsアクション・サーブレットに転送します。
defaultAction
タグ。ポートレットが初めてコールされたときにデフォルトで使用するStrutsアクションを定義します。
PDK-Javaを使用すると、Strutsアプリケーションのビュー(Portalビュー)を容易に開発できます。このビューによって、ポータル・スタイルを使用するStrutsポートレットでは整合性のとれたルック・アンド・フィールが維持され、エンド・ユーザーはポータル内でアプリケーションを使用できます。
Strutsポートレットを作成するには、デフォルトのStruts JSPタグの拡張であるOracle Portal JSPタグを使用する必要があります。この開発プロセスは、スタンドアロンのStrutsアプリケーションを作成するプロセスに似ています。Strutsポートレットの作成方法は、7.3.2.1項「Strutsポートレットの作成」を参照してください。また、ポートレットとStrutsアプリケーションは同じサーブレット・コンテキスト内に存在する必要があるため、両方の要素を含む単一のWebアプリケーションを作成する必要があります。Oracle JDeveloperでこのようなWebアプリケーションを簡単に作成する方法は、次の7.3.2.1項「Strutsポートレットの作成」を参照してください。
Apache Strutsは、MVC設計パラダイムの明確で簡単な実装を提供しているため、事実上、MVCベースのJ2EEアプリケーションを開発する際の標準になっています。このフレームワークによって、ポートレット開発者は、アプリケーションの様々なコンポーネントを区分し、Strutsコントローラを利用して既存のStrutsアプリケーションをOracle Portalに容易に公開できるため、既存のビジネス・ロジックをすべて変更する必要はありません。
注意: Oracle Portal Developer Kitの詳細は、Portal Center(http://www.oracle.com/technology/products/ias/portal/pdk.html )を参照してください。 |
Oracle PDKには、Apache Strutsアプリケーションを統合するための新しい拡張機能が含まれています。この項では、既存のStrutsアプリケーションからポートレットを作成する方法を説明します。また、その作成手順に従うと、Model-View-Controllerパラダイムを使用するポートレットも作成できます。Apache Strutsフレームワークの詳細は、7.3.1項「Oracle PortalおよびApache Strutsのフレームワーク」を参照してください。この項で説明するPDK-Javaの拡張機能は、Apache Struts 1.1に準拠しています。
この項では、次の手順を説明します。
既存のStrutsアプリケーションの一部をポートレットとして公開するには、最初に、アプリケーションのPortalビューとして機能する新しいビューを作成することをお薦めします。このビューでは、既存のオブジェクト(Actions
、ActionForm
など)とともに新しいマッピングとJSPを使用します。
注意: アプリケーションのPortalビューを作成することをお薦めしますが、アプリケーションのStrutsタグをPDK-JavaのStrutsタグに置き換えることもできます。この方法を使用すると、アプリケーションをスタンドアロンStrutsとポートレットの両方として実行できます。 |
この例では、新しいエントリをWebロガー(Blog)に追加できるポートレットを作成します。図7-16および図7-17は、Blogを送信してBlogエントリを保存する方法を示しています。
prepareNewBlog
は、リクエストをenterNewBlog.jsp
ページにリダイレクトする単純な空のアクションです。このページには、新しいBlogを送信するためのフォームが表示されます。
struts-config.xml
で対応するエントリは次のとおりです。
<action path="/prepareNewBlog" scope="request" type="view.PrepareNewBlogAction" > <forward name="success" path="/view/enterNewBlog.jsp"/> </action> <action path="/saveNewBlog" name="blogForm" scope="request" type="view.SaveNewBlogAction" input"/view/enterNewBlog.jsp" > <forward name="success" path="/view/newBlogConfirmation.jsp"/> </action>
新しいビューを作成するには、最初に、様々なアクションとリクエストをPortal固有のJSPにリダイレクトするActionMappings
(ページ・フロー)の新しいセットを作成します。
<action path="/portal/prepareNewBlog" scope="request" type="view.PrepareNewBlogAction" > <forward name="success" path="/view/portal/enterNewBlog.jsp"/> </action> <action path="/portal/saveNewBlog" name="blogForm" scope="request" type="view.SaveNewBlogAction" input="/view/enterNewBlog.jsp" > <forward name="success" path="/view/portal/newBlogConfirmation.jsp"/> </action>
変更するのはパス属性のみです。FormBean
アクションは、アプリケーションのビジネス・ロジックが変更されないようにします。
前述の手順で指定したように、アクションによってリクエストが新しいJSPに転送され、JSPでポートレットのコンテンツがレンダリングされます。新しいポートレット・ビューのJSPは、HTMLをスタンドアロン・ビューと共有できますが、ポートレットが次の条件を満たしていることを確認してください。
他のポータル・ページと整合性のとれたルック・アンド・フィールを維持するPortalスタイルが使用されていること。
HTMLの表のセルに格納できるHTMLコードが含まれていること(つまり、<html>
、<body>
および<frame>
タグ以外)。
ポータルで認識できるリンクおよびフォームをレンダリングしていること。これは、Strutsポートレットがコンテンツをインラインでレンダリングするために必要です。これによって、同じポートレット・コンテナ内でリクエストされたコンテンツがレンダリングされ、ユーザーをポータル・ページのコンテキスト内で管理できます。
Strutsポートレット内でインラインのレンダリングを実行するには、Oracle PDKタグを使用する必要があります。
<pdk-struts-html:form action="/portal/saveNewBlog.do"> ... ... </pdk-struts-html:form>
ポートレットのレンダリング中に、いずれかのJSPタグ(たとえば、pdk-struts-html:form
タグ)でフォームをParallel Page Engine(PPE)に送信し、PPEではそのパラメータをStrutsポートレットに送信します。Strutsコントローラは、これらのアクションのロジックを実行し、次のJSPをポータル・ページ内のポートレットに戻します。
PDKにはすべてのStrutsタグが含まれており、URLに関連するすべてのタグを拡張します。次に、PDKによって拡張されるタグを示します。
form
: HTMLフォームを作成し、フォーム内にポータル・ページのコンテキストを埋め込んで、インラインのレンダリングを保証します。
text
: フォーム上のフィールドをレンダリングします。
link
およびrewrite
: ポータル・ページへのリンクを作成します。これらはインラインのレンダリングに必要です。
img
: Webプロバイダを指す絶対リンクを作成します。このタグを、ファイアウォールを備えたインターネットWebサイトのコンテキストで使用する場合は、プロバイダにインターネットから直接アクセスできることを確認する必要があります。これが不可能な場合は、Oracle Portal中間層へイメージをデプロイし、Apache Strutsのイメージ・リンクを使用して関連リンク(アプリケーションではなくポータルに関連付けられたリンク)を生成できます。
注意: Oracle PDKはOracle JDeveloperに登録できるため、Oracle JDeveloperのコンポーネント・パレットからタグを削除できます。詳細は、Oracle JDeveloperのオンライン・ヘルプでJDeveloperでのカスタム・タグ・ライブラリの登録に関する項を参照してください。 |
Strutsポートレットは、手動またはJavaポートレット・ウィザードを使用して作成できます。ウィザードでは明示的にStrutsサポートを提供していませんが、ウィザードを使用してStrutsポートレットを作成できます。
ポートレットを作成する手順は、次のとおりです。
Oracle JDeveloperで、Javaポートレット・ウィザードを開いてOracle PDK Javaポートレットを作成します。
注意: JavaポートレットとOracle PDK Javaポートレットの各オプションは、それぞれ、JPSに準拠したポートレットとPDK-Javaポートレットを作成するのに使用します。「Javaポートレット」または「Oracle PDK Javaポートレット」をクリックすると、Javaポートレット・ウィザードが開きます。ウィザードの起動方法の詳細は、6.5.1項「Oracle PDK-Javaポートレットとプロバイダの作成」を参照してください。 |
「ページを表示」の「実装スタイル」で、「Javaクラス」を選択します。
「パッケージ名」には、oracle.portal.provider.v2.render.http
と入力します。
「クラス名」には、StrutsRenderer
と入力します。これにより、ポートレットのレンダラ・クラスのスケルトンとしてStrutsRenderer
が生成されます。
StrutsRenderer
はPDKに含まれているため、この生成されたファイルは必要ありません。したがって、ウィザードが完了した後は、ウィザードで生成されたファイルを削除する必要があります。これを行うには、システム・ナビゲータ・ウィンドウでファイルをクリックし、Oracle JDeveloperの「ファイル」>「ディスクから削除」を選択します。
provider.xml
を編集して、次のプロパティを変更します。
プロバイダ・レベルで、次のタスクを実行します。
ユーザーがポータル・ページを終了するたびに元のポートレット状態に戻るようにするには、StrutsアクションをStrutsコンテンツに保存するようにStrutsレンダラを構成します。
<actionInSession>true</actionInSession>
ユーザーがポータル・ページの外部から戻ると常にポートレットの先頭から開始するようにするには、Strutsアクションを保存しないでください。
<actionInSession>false</actionInSession>
Strutsアプリケーションがセッションを使用する場合(たとえば、フォーム・シンクロナイザのトークン・メカニズムが使用されているか、または<actionInSession>
がtrueに設定されている場合)、セッション処理を有効化します。
<session>true</session>
ポートレット・レベルで、次のタスクを実行します。
ポートレットがコールされたときに起動する最初のアクションを指定します。次のコードを使用します。
<showPage class="oracle.portal.provider.v2.render.http.StrutsRenderer"> <defaultAction>/portal/prepareNewBlog.do</defaultAction> </showPage>
provider.xml
の構文の詳細は、OTNにあるプロバイダのJavadocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
ポートレットをOracle Portalで使用する準備が完了すると、そのポートレットをOracle Portalに登録してアクセス可能にする必要があります。PDK-Javaポートレットの登録方法の詳細は、6.5.5項「Oracle PDK-Javaポートレットの登録と表示」を参照してください。Strutsアクションをセッション・コンテキストに保存する場合(<actionInSession>true</actionInSession>
)、登録時にプロバイダのログイン頻度を「ユーザー・セッションごとに1回」に指定する必要があります。この方法でログイン頻度を設定すると、セッション情報がStrutsポートレットに渡されます。
Oracle Fusion Middlewareを使用すると、Oracle JDeveloperを使用してStrutsポートレットを容易に作成でき、既存のStrutsアプリケーションをOracle Portalに公開できます。Oracle JDeveloperのJavaポートレット・ウィザードの使用方法は、この章の前半を参照してください。Oracle Portalの使用方法の詳細は、『Oracle Fusion Middleware Oracle Portalユーザーズ・ガイド』およびOracle Portalのオンライン・ヘルプを参照してください。
Strutsの場合と同様、Oracle ADFはMVCの設計パターンに準拠しています。Strutsコントローラを使用するOracle ADFアプリケーションは、Strutsアプリケーションの場合と同じように、ポートレットに変換してOracle Portalにデプロイできます。詳細は、7.3.2項「Strutsポートレットの作成」を参照してください。
注意: Oracle ADFポートレットを作成しても、JSPページが正しく表示されないことがあります。これはParallel Page EngineのリクエストがSOAPリクエスト(oracle.webdb.provider.v2.adapter.SOAPServlet )を介してプロバイダに送信されるためで、ポータルでは、ページが標準の.JSP ページとして扱われなくなります。これを解決するには、ADFBindingFilter フィルタを作成します。 |
ADFBindingFilter
フィルタを作成してマッピングをフィルタするには、web.xml
ファイルに次のコードを記述します。
<filter> <filter-name>ADFBindingFilter</filter-name> <filter-class>oracle.adf.model.servlet.ADFBindingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>windows-1252</param-value> </init-param> </filter> <filter-mapping> <filter-name>ADFBindingFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ADFBindingFilter</filter-name> <url-pattern>*.jspx</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ADFBindingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ADFBindingFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ADFBindingFilter</filter-name> <servlet-name>action</servlet-name> </filter-mapping> <filter-mapping> <filter-name>ADFBindingFilter</filter-name> <servlet-name>jsp</servlet-name> </filter-mapping>
脚注
脚注1: Oracle Portalオブジェクトに対するユーザーのパーソナライズ・データはエクスポートされません。この制限は、ポートレットと同様に、ページなどの他のオブジェクトにも適用されます。