この章では、Oracle JDeveloperポートレット・ウィザードを使用して作成したJavaポートレットを拡張する方法、およびStrutsアプリケーションおよびJSFアプリケーションからポートレットを作成する方法について説明します。この章の内容は、次のとおりです。
この章で参照される多数の例のソース・コードは、Portlet Developer's Kit(PDK)の一部として使用できます。PDKは、次のURLにあるOracle Technology Network(OTN)のPDKのページからダウンロードできます。
http://www.oracle.com/technology/products/ias/portal/pdk.html
PDK-Javaを解凍すると、次の場所に例があります。
../pdk/jpdk/v2/src/oracle/portal/sample/v2/devguide
PDK-Java用の参照JavaDocは次の場所にあります。
../pdk/jpdk/v2/apidoc
18.5項「Oracle JDeveloperを使用したJPS準拠のポートレットの構築」に示すように、ポートレット・ウィザードで初期ポートレットを構築すると、これを拡張できます。JPSポートレットはJava標準に準拠しているため、これの拡張に関する情報は、サード・パーティの書籍やWebページなど様々なソースから多数入手できます。実行が必要になる重要な拡張機能のいくつかは、次のとおりです。
この項では、18.5項「Oracle JDeveloperを使用したJPS準拠のポートレットの構築」で作成したポートレットを拡張します。拡張には、ユーザーがポートレットによるレンダリング対象のフィールドに編集モードまたはデフォルト編集モードでHTMLを貼り付けるために使用できるコードを使用します。また、ポートレットを簡単に再デプロイする方法についても説明します。
次の前提は、この項でのタスクを実行するためのものです。
ウィザードで作成したポートレットが正常にプロデューサに登録され、ページに追加されていること。
ウィザードの「カスタマイズ・プリファレンス」ページで、portletcontent
というプリファレンスが追加されていること。
10.2項「アプリケーションのセキュリティの設定」の手順を実行して、アプリケーションに対してOracle ADFセキュリティを有効にしていること。ユーザーは、パーソナライズ機能へのアクセスを認証されているユーザーとして、アプリケーションにログインしている必要があります。
この項では、コードをMy Java Portletに追加し、ポートレットを再デプロイし、これをテストします。そのための手順は、次のとおりです。
Oracle JDeveloperのアプリケーション・ナビゲータで、JPS標準に準拠したポートレットのview.jsp
ファイルをダブルクリックします。
例19-1のコードをview.jsp
の「ソース」ビューに追加します。
例19-1 view.jspのサンプル・コード
<%@ page contentType="text/html" import="javax.portlet.*,java.util.*,Portlets.Portlet1, Portlets.resource.Portlet1Bundle"%> <%@ taglib uri="http://java.sun.com/portlet" prefix="portlet"%> <portlet:defineObjects/> <% String[] str = {"Portlet Content"}; PortletPreferences prefs = renderRequest.getPreferences(); str = prefs.getValues("portletContent",str); for (int i=0; i<str.length; i++) { %><%=(i<str.length-1)?str[i]+", ":str[i]%><%}%>
「設計」タブをクリックします。ページは、図19-1のように表示されます。
ビジュアル・デザイナでedit.jsp
を開き、「設計」タブをクリックします。JSPは、図19-2で示すように、フォーム・フィールド、フォーム入力フィールドおよび2つのフォーム・ボタン・フィールドで構成されています。
次のコードの中で太字で示された部分を追加し、Contentという名前のフォーム・フィールドを実装します。
例19-2 edit.jspのサンプル・コード
<%@ page contentType="text/html" pageEncoding="windows-1252" import="javax.portlet.*,java.util.*, portlet.Portlet2,portlet.resource.Portlet2Bundle"%> <%@ taglib uri="http://java.sun.com/portlet" prefix="portlet"%> <portlet:defineObjects/> <% PortletPreferences prefs = renderRequest.getPreferences(); ResourceBundle res = portletConfig.getResourceBundle(renderRequest.getLocale()); %> <FORM ACTION="<portlet:actionURL/>" METHOD="POST"> <TABLE BORDER="0"> <TR><TD WIDTH="20%"> <P CLASS="portlet-form-field" ALIGN="right"> <%= res.getString(Portlet2Bundle.PORTLETTITLE) %> </P></TD><TD WIDTH="80%"> <INPUT CLASS="portlet-form-input-field" TYPE="TEXT" NAME="<%= Portlet2.PORTLETTITLE_KEY %>" VALUE="<%= prefs.getValue(Portlet2.PORTLETTITLE_KEY, res.getString("javax.portlet.title")) %>" SIZE="20"> </TD></TR> <% String[] str = {"Portlet Content"}; str = prefs.getValues("portletContent",str); %> <tr><td width="20%"> <p class="portlet-form-field" align="right"> Content </p> </td><td width="80%"> <textarea rows="10" cols="60" class="portlet-form-input-field" name="portletContent"><% for (int i=0; i<str.length; i++) {%><%= (i<str.length-1) ? str[i]+", " : str[i] %><%}%> </textarea> </td></tr> <TR><TD COLSPAN="2" ALIGN="CENTER"> <INPUT CLASS="portlet-form-button" TYPE="SUBMIT" NAME="<%= Portlet2.OK_ACTION %>" VALUE="<%= res.getString(Portlet2Bundle.OK_LABEL) %>"> <INPUT CLASS="portlet-form-button" TYPE="SUBMIT" NAME="<%= Portlet2.APPLY ACTION %>" VALUE="<%= res.getString(Portlet2Bundle.APPLY_LABEL) %>"> </TD></TR> </TABLE> </FORM>
「設計」タブをクリックします。ページは、図19-3のように表示されます。
ビジュアル・エディタで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によりコードが自動的に保存およびコンパイルされた上で、ポートレットがデプロイされます。この手順の実行方法に関する注意は、18.9項「アプリケーション・サーバーへのポートレットのデプロイ」を参照してください。
ポートレットが含まれるページをリロードします。ポートレットには、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はポートレットでレンダリングされます。
JSR 168およびWSRP 1.0ではパブリック・ポートレット・パラメータに対応していないのに対して、WSRP 2.0では、ナビゲーション・パラメータを導入して、ポートレット間の通信を可能にします。新しいポートレットApplication Programming Interface(API)標準、JSR 286の発表により、ベンダー固有のAPI拡張機能は不要になります。それまでは、Oracle固有のポートレット・コンテナおよびAPI拡張機能を使用する必要があります。
ポートレット・ウィザードを使用することで、ナビゲーション・パラメータによりポートレットを簡単に作成できます。プロデューサを登録し、ページ上にポートレットをドロップすると、ポートレットのパラメータがページの変数に自動的にリンクされます。
WSRP 2.0ナビゲーション・パラメータを使用したパブリック・パラメータのJPSポートレットへの追加
プロジェクトを右クリックし、ポップアップ・メニューから「新規」を選択します。
「新規ギャラリ」から、「Portlets」カテゴリ、次に「規格に基づいたJavaポートレット(JSR 168)」項目を選択します。
ウィザードの「一般プロパティ」ページが表示されたら、図19-4に示すように、必ず「Oracle拡張機能を使用してWSRP V2のポートレット間通信を可能にします。」チェック・ボックスを選択します。
「ポートレット・ナビゲーション・パラメータ」ページが表示されるまで、普通どおりにウィザードの手順を進めます。ウィザードの手順の進め方についての基本情報は、18.5項「Oracle JDeveloperを使用したJPS準拠のポートレットの構築」を参照してください。
「ポートレット・ナビゲーション・パラメータ」ページ(図19-5)が表示されたら、「追加」ボタンをクリックします。「ナビゲーション・パラメータ」表に新しい行が追加されます。
「名前」列に表示されるデフォルト名をクリックします。[Backspace]キーを使用して、デフォルト名を削除します。
新しいパラメータ名(Parameter_01
など)を入力します。
「ラベル」列と「ヒント」列について、手順6および7を繰り返します。
ポートレットに追加するパブリック・パラメータごとに、手順5〜8を繰り返します。
「次へ」をクリックします。
「終了」をクリックします。
ポートレット・ウィザードを終了すると、ポートレットが作成されます。
アプリケーション・ナビゲータで、「Webコンテンツ」ノードと「WEB-INF」ノードを開きます。portlet.xml
ファイルとweb.xml
ファイルおよびoracle-portlet.xml
ファイルが表示されます。
oracle-portlet.xml
を右クリックし、ポップアップ・メニューから「開く」を選択します。ウィザードの「ポートレット・ナビゲーション・パラメータ」ページで追加したパラメータのエントリが、例19-3に示すように表示されます。
例19-3 oracle-portlet.xmlのサンプル、ナビゲーション・パラメータ
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <portlet-app-extension xsi:schemaLocation="http://xmlns.oracle.com/portlet/oracle-portlet-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/portlet/oracle-portlet-app"> <portlet-extension> <portlet-name>portlet1</portlet-name> <navigation-parameters> <name>Parameter_01</name> <type>xsi:string</type> <label xml:lang="en">Parameter 1</label> <hint xml:lang="en">First parameter.</hint> </navigation-parameters> <navigation-parameters> <name>Parameter_02</name> <type>xsi:string</type> <label xml:lang="en">Parameter 2</label> <hint xml:lang="en">Second parameter.</hint> </navigation-parameters> <portlet-id>1164232649525</portlet-id> </portlet-extension> </portlet-app-extension>
例19-4のサンプル・ポートレットは、フォームが含まれ、ナビゲーション・パラメータを送信するポートレットを示しています。
例19-4 パラメータを送信するフォーム・ポートレット
/* Copyright (c) 2006, Oracle. All rights reserved. */ package oracle.portlet.server.wsrpsample; import java.io.IOException; import java.io.PrintWriter; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletException; import javax.portlet.PortletMode; import javax.portlet.PortletPreferences; import javax.portlet.PortletSession; import javax.portlet.PortletURL; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.WindowState; public class ParameterFormPortlet extends CustomizablePortlet { // Form field names public static final String PARAMETER1 = "ora_wsrp_navigparam_Parameter1"; public static final String PARAMETER2 = "ora_wsrp_navigparam_Parameter2"; public static final String PARAMETER3 = "ora_wsrp_navigparam_Parameter3"; public static final String FORM_PARAMETER1 = "form_Parameter1"; public static final String FORM_PARAMETER2 = "form_Parameter2"; public static final String FORM_PARAMETER3 = "form_Parameter3"; public static final String FORM_SUBMIT = "dosub"; public static final String P1PROMPT_KEY = "p1Prompt"; public static final String P2PROMPT_KEY = "p2Prompt"; public static final String P3PROMPT_KEY = "p3Prompt"; public static final String MODE_NAME_PARAM = "mode"; public static final String MODE_VIEW = "view"; public static final String MODE_EDITDEFAULTS = "editDefaults"; /** * Helper method to serve up the VIEW mode. * * @param request the portlet request * @param response the portlet response * * @exception PortletException if the portlet has trouble fulfilling the * request * @exception IOException if the streaming causes an I/O problem */ public void doView (RenderRequest request, RenderResponse response) throws PortletException, IOException { String p1Prompt = request.getPreferences().getValue(P1PROMPT_KEY, "Parameter 1:"); String p2Prompt = request.getPreferences().getValue(P2PROMPT_KEY, "Parameter 2:"); String p3Prompt = request.getPreferences().getValue(P3PROMPT_KEY, "Parameter 3:"); response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); PortletURL formURL = response.createActionURL(); //Retrieve any values for the nav parameters from the request String param1 = request.getParameter(PARAMETER1); String param2 = request.getParameter(PARAMETER2); String param3 = request.getParameter(PARAMETER3); param1 = (param1 != null)?param1:""; param2 = (param2 != null)?param2:""; param3 = (param3 != null)?param3:""; out.print("<form method=\"POST\" action=\""); out.print(formURL.toString()); out.println("\">"); out.print("<center><table>"); if (!"".equals(p1Prompt)) { out.print("<tr><td class=\"portlet-form-field\">"); out.print(p1Prompt); out.print("</td><td>"); out.print("<input class=\"portlet-form-input-field\" type=\"text\" size=\"20\" name=\""); out.print(FORM_PARAMETER1); out.print("\" value=\""); out.print(escapeForHTMLAttr(param1)); out.print("\">"); out.print("</td></tr>"); } else { out.print("<input type=\"hidden\" name=\""); out.print(FORM_PARAMETER1); out.print("\" value=\"\">"); } if (!"".equals(p2Prompt)) { out.print("<tr><td class=\"portlet-form-field\">"); out.print(p2Prompt); out.print("</td><td>"); out.print("<input class=\"portlet-form-input-field\" type=\"text\" size=\"20\" name=\""); out.print(FORM_PARAMETER2); out.print("\" value=\""); out.print(escapeForHTMLAttr(param2)); out.print("\">"); out.print("</td></tr>"); } else { out.print("<input type=\"hidden\" name=\""); out.print(FORM_PARAMETER2); out.print("\" value=\"\">"); } if (!"".equals(p3Prompt)) { out.print("<tr><td class=\"portlet-form-field\">"); out.print(p3Prompt); out.print("</td><td>"); out.print("<input class=\"portlet-form-input-field\" type=\"text\" size=\"20\" name=\""); out.print(FORM_PARAMETER3); out.print("\" value=\""); out.print(escapeForHTMLAttr(param3)); out.print("\">"); out.print("</td></tr>"); } else { out.print("<input type=\"hidden\" name=\""); out.print(FORM_PARAMETER3); out.print("\" value=\"\">"); } out.print("<tr><td colspan=\"2\" align=\"center\">"); out.print("<input type=\"submit\" class=\"portlet-form-button\" name=\""); out.print(FORM_SUBMIT); out.print("\" value=\"OK\">"); out.print("</td></tr></table>"); out.print("<input type=\"hidden\" name=\""); out.print(MODE_NAME_PARAM); out.print("\" value=\""); out.print(MODE_VIEW); out.print("\">"); out.print("</form>"); out.println("</center>"); } /** * Handles actions. * * @param request the portlet request * @param actionResponse the portlet response * * @exception IOException if streaming causes an I/O problem * @exception PortletException if something else goes wrong */ public void processAction (ActionRequest request, ActionResponse actionResponse) throws PortletException, IOException { // // Determine what kind of action we have by examining the mode parameter // boolean editDefaults = MODE_EDITDEFAULTS.equals(request.getParameter (MODE_NAME_PARAM)); boolean viewMode = MODE_VIEW.equals(request.getParameter(MODE_NAME_PARAM)); String param1 = request.getParameter(FORM_PARAMETER1); String param2 = request.getParameter(FORM_PARAMETER2); String param3 = request.getParameter(FORM_PARAMETER3); String title = request.getParameter(TITLE_KEY); String p1Prompt = request.getParameter(P1PROMPT_KEY); String p2Prompt = request.getParameter(P2PROMPT_KEY); String p3Prompt = request.getParameter(P3PROMPT_KEY); if (viewMode) { // // Set the new parameter values. These will be intepreted by the // container as navigational parameters as the names match the names of // the declared parameters. // actionResponse.setRenderParameter(PARAMETER1, param1); actionResponse.setRenderParameter(PARAMETER2, param2); actionResponse.setRenderParameter(PARAMETER3, param3); } else if (editDefaults) { // // In edit defaults we just set the new title and parameter prompts in // the preference store. // PortletPreferences prefs = request.getPreferences(); prefs.setValue(TITLE_KEY, title); prefs.setValue(P1PROMPT_KEY, p1Prompt); prefs.setValue(P2PROMPT_KEY, p2Prompt); prefs.setValue(P3PROMPT_KEY, p3Prompt); prefs.store(); actionResponse.setPortletMode(PortletMode.VIEW); actionResponse.setWindowState(WindowState.NORMAL); } else { super.processAction(request, actionResponse); } } /** * Helper method to serve up the EDIT mode. * * @param request the portlet request * @param response the portlet response * * @exception PortletException if the portlet cannot fulfill the request * @exception UnavailableException if the portlet is unavailable to perform edit * @exception PortletSecurityException if the portlet cannot fullfill this * request because of security reasons * @exception IOException if the streaming causes an I/O problem */ public void doEdit (RenderRequest request, RenderResponse response) throws PortletException, IOException { response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); String p1Prompt = request.getPreferences().getValue(P1PROMPT_KEY, "Parameter 1:"); String p2Prompt = request.getPreferences().getValue(P2PROMPT_KEY, "Parameter 2:"); String p3Prompt = request.getPreferences().getValue(P3PROMPT_KEY, "Parameter 3:"); // create an action link back to this portlet out.print("<FORM ACTION=\""); out.print(getEditFormSubmitURL(request, response)); out.println("\" METHOD=\"POST\">"); out.println("<TABLE BORDER=\"0\">"); out.println("<TR>"); out.println("<TD WIDTH=\"20%\">"); out.println("<P CLASS=\"portlet-form-field\" ALIGN=\"RIGHT\">Title:"); out.println("</TD>"); out.println("<TD WIDTH=\"80%\">"); out.print("<INPUT CLASS=\"portlet-form-input-field\" TYPE=\"TEXT\" NAME=\""); out.print(TITLE_KEY); out.print("\" VALUE=\""); out.print(getTitle(request)); out.println("\" SIZE=\"20\">"); out.println("</TD>"); out.println("</TR>"); out.println("<TR>"); out.println("<TD WIDTH=\"20%\">"); out.println("<P CLASS=\"portlet-form-field\" ALIGN=\"RIGHT\">Parameter 1 Prompt:"); out.println("</TD>"); out.println("<TD WIDTH=\"80%\">"); out.print("<INPUT CLASS=\"portlet-form-input-field\" TYPE=\"TEXT\" NAME=\""); out.print(P1PROMPT_KEY); out.print("\" VALUE=\""); out.print(p1Prompt); out.println("\" SIZE=\"20\">"); out.println("</TD>"); out.println("</TR>"); out.println("<TR>"); out.println("<TD WIDTH=\"20%\">"); out.println("<P CLASS=\"portlet-form-field\" ALIGN=\"RIGHT\">Parameter 2 Prompt:"); out.println("</TD>"); out.println("<TD WIDTH=\"80%\">"); out.print("<INPUT CLASS=\"portlet-form-input-field\" TYPE=\"TEXT\" NAME=\""); out.print(P2PROMPT_KEY); out.print("\" VALUE=\""); out.print(p2Prompt); out.println("\" SIZE=\"20\">"); out.println("</TD>"); out.println("</TR>"); out.println("<TR>"); out.println("<TD WIDTH=\"20%\">"); out.println("<P CLASS=\"portlet-form-field\" ALIGN=\"RIGHT\">Parameter 3 Prompt:"); out.println("</TD>"); out.println("<TD WIDTH=\"80%\">"); out.print("<INPUT CLASS=\"portlet-form-input-field\" TYPE=\"TEXT\" NAME=\""); out.print(P3PROMPT_KEY); out.print("\" VALUE=\""); out.print(p3Prompt); out.println("\" SIZE=\"20\">"); out.println("</TD>"); out.println("</TR>"); out.println("<TR>"); out.println("<TD COLSPAN=\"2\" ALIGN=\"CENTER\">"); out.print("<INPUT CLASS=\"portlet-form-button\" TYPE=\"SUBMIT\" NAME=\""); out.print(OK_ACTION); out.print("\" VALUE=\"OK\">"); out.print("<input type=\"hidden\" name=\""); out.print(MODE_NAME_PARAM); out.print("\" value=\""); out.print(MODE_EDITDEFAULTS); out.print("\">"); out.print("<INPUT CLASS=\"portlet-form-button\" TYPE=\"SUBMIT\" NAME=\""); out.print(APPLY_ACTION); out.print("\" VALUE=\"Apply\">"); out.println("</TD>"); out.println("</TR>"); out.println("</TABLE>"); out.println("</FORM>"); } protected String escapeForHTMLAttr(String original) { String escaped = original.replaceAll("&", "&"); escaped = escaped.replaceAll("<", "<"); escaped = escaped.replaceAll(">", ">"); escaped = escaped.replaceAll("\"", """); escaped = escaped.replaceAll("'", """); return escaped; } }
次のAPIを使用すると、ポートレットに渡されるパラメータを読み取れます。
String param1 = request.getParameter("Parameter_01"); String param2 = request.getParameter("Parameter_02");
例19-5のサンプル・ポートレットは、ナビゲーション・パラメータを読み取ります。
例19-5 パラメータを読み取るポートレット
/* Copyright (c) 2006, Oracle. All rights reserved. */ package oracle.portlet.server.wsrpsample; import java.io.IOException; import java.io.PrintWriter; import javax.portlet.PortletException; import javax.portlet.PortletURL; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; public class ReadOnlyParameterFormPortlet extends ParameterFormPortlet { /** * Helper method to serve up the VIEW mode. * * @param request the portlet request * @param response the portlet response * * @exception PortletException if the portlet has trouble fulfilling the * request * @exception IOException if the streaming causes an I/O problem */ public void doView (RenderRequest request, RenderResponse response) throws PortletException, IOException { String p1Prompt = request.getPreferences().getValue(P1PROMPT_KEY, "Parameter 1:"); String p2Prompt = request.getPreferences().getValue(P2PROMPT_KEY, "Parameter 2:"); String p3Prompt = request.getPreferences().getValue(P3PROMPT_KEY, "Parameter 3:"); response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); //Retrieve any values for the nav parameters from the request String param1 = request.getParameter(PARAMETER1); String param2 = request.getParameter(PARAMETER2); String param3 = request.getParameter(PARAMETER3); param1 = (param1 != null)?param1:""; param2 = (param2 != null)?param2:""; param3 = (param3 != null)?param3:""; out.print("<center><table>"); if (!"".equals(p1Prompt)) { out.print("<tr><td class=\"portlet-form-field\">"); out.print(p1Prompt); out.print("</td><td>"); out.print(escapeForHTMLAttr(param1)); out.print("</td></tr>"); } if (!"".equals(p2Prompt)) { out.print("<tr><td class=\"portlet-form-field\">"); out.print(p2Prompt); out.print("</td><td>"); out.print(escapeForHTMLAttr(param2)); out.print("</td></tr>"); } if (!"".equals(p3Prompt)) { out.print("<tr><td class=\"portlet-form-field\">"); out.print(p3Prompt); out.print("</td><td>"); out.print(escapeForHTMLAttr(param3)); out.print("</td></tr>"); } out.println("</table></center>"); } }
プロデューサを登録して、これら2つのポートレットがコンポーネント・パレットに表示されるようにします。4.3.1.1項「WSRPポートレット・プロデューサの登録」で示した手順に従ってください。
新規または既存のページへ、作成した2つのポートレットをコンポーネント・パレットからドラッグ・アンド・ドロップします。詳細は、4.3.2項「ページへのポートレットの追加」を参照してください。
「構造」ペインでページの要素を右クリックし、「ページ定義に移動」を選択します。例19-6のようなページ定義が表示されます。ページ・レベルの変数とポートレット・レベルのパラメータに注意してください。
例19-6 ページ定義ファイルのサンプル
<?xml version="1.0" encoding="UTF-8" ?> <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="10.1.3.38.82" id="untitled2PageDef" Package="view.pageDefs"> <parameters/> <executables> <variableIterator id="variables"> <variable Name="Parameter_01" Type="java.lang.Object"/> <variable Name="Parameter_02" Type="java.lang.Object"/> <variable Name="Parameter_03" Type="java.lang.Object"/> </variableIterator> <portlet id="portlet1" portletInstance="/oracle/adf/portlet/Samples_1153150955927/ applicationPortlets/E10default_7d3d5f76_010c_1000_8004_8a031f56d48d" class="oracle.adf.model.portlet.binding.PortletBinding" xmlns="http://xmlns.oracle.com/portlet/bindings"> <parameters> <parameter name="ora_wsrp_navigparam_Parameter1" pageVariable="Parameter_01"/> <parameter name="ora_wsrp_navigparam_Parameter2" pageVariable="Parameter_02"/> <parameter name="ora_wsrp_navigparam_Parameter3" pageVariable="Parameter_03"/> </parameters> </portlet> <portlet id="portlet2" portletInstance="/oracle/adf/portlet/Samples_1153150955927/ applicationPortlets/E11default_7d3d7ef3_010c_1000_8005_8a031f56d48d" class="oracle.adf.model.portlet.binding.PortletBinding" xmlns="http://xmlns.oracle.com/portlet/bindings"> <parameters> <parameter name="ora_wsrp_navigparam_Parameter1" pageVariable="Parameter_01"/> <parameter name="ora_wsrp_navigparam_Parameter2" pageVariable="Parameter_02"/> <parameter name="ora_wsrp_navigparam_Parameter3" pageVariable="Parameter_03"/> </parameters> </portlet> </executables> </pageDefinition>
WSRP 2.0で提供されるもう1つの新機能は、ポートレットを1つのデプロイメントから別のデプロイメントに移動する際に、ポートレットのカスタマイズを維持する能力です。たとえば、ポートレットを作成し、開発環境内でそのタイトルをカスタマイズしたとします。ポートレットおよびそのプロデューサのエクスポートとインポートを有効にしたとすると、カスタマイズされたタイトルは、ポートレットを本番環境にデプロイする際に、ポートレットとともにトランスポートされます。エクスポートおよびインポートを有効にしないと、ポートレットをあるデプロイメント環境から別のデプロイメント環境にトランスポートする際に、カスタマイズはすべて失われてしまいます。
ポートレットおよびそのプロデューサのエクスポートまたはインポートを実装する手順は、次のとおりです。
使用するプロデューサのoracle-portlet.xml
ファイルを開きます。各ポートレットおよびプロデューサのallow-export
タグとallow-import
タグを、例19-7に示すように追加します。
例19-7 oracle-portlet.xmlのサンプル、エクスポート/インポート
<portlet-app-extension xsi:schemaLocation="./oracle-portlet-app.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="./oracle-portlet-app.xsd"> <portlet-extension> <portlet-name>portlet1</portlet-name> <navigation-parameters> <name>Parameter_01</name> <type>xsi:string</type> <label xml:lang="en">First Parameter</label> <hint xml:lang="en">hint0</hint> </navigation-parameters> <navigation-parameters> <name>Parameter_02</name> <type>xsi:string</type> <label xml:lang="en">Second Parameter</label> <hint xml:lang="en">hint1</hint> </navigation-parameters> <navigation-parameters> <name>Parameter_03</name> <type>xsi:string</type> <label xml:lang="en">Third Parameter</label> <hint xml:lang="en">hint2</hint> </navigation-parameters> <portlet-id>1</portlet-id> <allow-export>true</allow-export> <allow-import>true</allow-import> <portlet-name>portlet2</portlet-name> <navigation-parameters> <name>Parameter_01</name> <type>xsi:string</type> <label xml:lang="en">First Parameter</label> <hint xml:lang="en">hint0</hint> </navigation-parameters> <navigation-parameters> <name>Parameter_02</name> <type>xsi:string</type> <label xml:lang="en">Second Parameter</label> <hint xml:lang="en">hint1</hint> </navigation-parameters> <navigation-parameters> <name>Parameter_03</name> <type>xsi:string</type> <label xml:lang="en">Third Parameter</label> <hint xml:lang="en">hint2</hint> </navigation-parameters> <portlet-id>2</portlet-id> <allow-export>true</allow-export> <allow-import>true</allow-import> </portlet-extension> <allow-export>true</allow-export> <allow-import>true</allow-import> </portlet-app-extension>
リソース・プロキシは、WSRPでリソースを取得する標準的な方法です。ポートレット内でのURLの問題を回避するには、指定したリソース内のURLをすべて書きなおすためのフラグを設定できます。たとえば、URLを含むHTMLのフラグメントがある場合、WSRPリソース・プロキシを考慮に入れてURLを書きなおすために、このフラグを設定できます。
PortletRequest
属性、oracle.portlet.server.resourceRequiresRewriting
をtrueに設定することにより、URLの書きなおしが必要であることを指示します。たとえば、例19-8に示すようなコードを含めて、エンコード中のURLにリソース・プロキシを使用します。通常は、このコードをメソッド内にカプセル化して、URLごとにこれを繰り返すことを避けます。
例19-8 WSRP用のリソース・プロキシ
request.setAttribute("oracle.portlet.server.resourceRequiresRewriting", Boolean.TRUE); String url = response.encodeURL(pathToResourceForRewriting); request.removeAttribute("oracle.portlet.server.resourceRequiresRewriting");
oracle.portlet.server.resourceRequiresRewriting
を明確に設定しないと、falseにデフォルト設定され、URLが書きなおされなくなります。この属性をtrueに設定することで、機能を明示的にアクティブにする必要があります。
WSRPプロデューサ側とクライアント側でセキュリティを構成することにより、WSRPプロデューサにデプロイされるJPSポートレットを保護できます。WSRPプロデューサを介したJPSポートレットの保護については、10.10項「WS-Securityを使用したWSRPプロデューサを介するアイデンティティ伝播の保護」を参照してください。
18.7項「Oracle JDeveloperを使用したPDK-Javaポートレットの構築」に示すように、ポートレット・ウィザードで初期ポートレットを作成すると、次のタスクを実行してこれを拡張できます。
この項では、次のことを前提にしています。
ポートレット・モードなど、ポートレットに関する用語の知識があること。第14章「ポートレットの概要」および18.1項「Javaポートレット作成のガイドライン」を参照してください。
Javaポートレット・コンテナのダウンロードおよびインストールが済んでおり、ポートレットをデプロイするOracle Containers for J2EE(OC4J)のコンテナが存在すること。
Oracle JDeveloperに関する知識があり、それを使用したJavaコンポーネントを構築およびデプロイする方法を習得していること。Oracle JDeveloperはOTNからダウンロードできます。次のURLでOTNの「Oracle JDeveloper」ページにアクセスします。
http://www.oracle.com/technology/products/jdev/index.html
ポートレット・モードを追加するには、ポートレット・ウィザードの各ページで該当するボックスを選択します。ウィザードの使用方法の詳細は、18.7項「Oracle JDeveloperを使用した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
の下に、HelpPage.html
というHTMLページを作成します。ファイルのコンテンツは、たとえば次のようになります。
<p>This is the <i>Help</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>
タグでプレビュー・モードが有効になるように次のようにタグを追加します。
<hasHelp>true</hasHelp>
19.2.1.2項「追加のポートレット・モードの実装」で作成したHTMLページをプレビュー・ページとして指定します。
<helpPage>/htdocs/myportlet/MyPortletHelpPage.html</helpPage>
更新内容をprovider.xml
に保存します。
ポートレットを再デプロイします。18.9項「アプリケーション・サーバーへのポートレットのデプロイ」の手順8を参照してください。
再デプロイする場合は、Oracle JDeveloperにより、コードが自動的に保存およびコンパイルされた上で、ポートレットがデプロイされます。
新規のポートレット・モードを表示するには、更新したXMLプロデューサ定義が再解析されるようにする必要があります。そのための手順は、次のとおりです。
19.2.1.2項「追加のポートレット・モードの実装」で作成したHTMLファイルおよびprovider.xml
を、ポートレットをデプロイするOC4Jインスタンスにコピーします。
プロデューサをリフレッシュします。
ポートレットが含まれているページをリフレッシュします。
「ヘルプ」リンクをクリックします。
PDK-JavaおよびOracle WebCenter Frameworkは、ポートレット開発者が再利用可能で複雑なポートレットを簡単に作成できるように、パブリック・ポートレット・パラメータ、プライベート・ポートレット・パラメータおよびプライベート・イベントを提供しています。Oracle JDeveloperのポートレット・ウィザードは、パラメータとイベントを使用するように設定されたポートレットを作成します。この機能によって、開発者はビジネス・ロジックをポートレットに追加するのみで、provider.xml
を変更する必要はありません。
パラメータおよびイベントの概要は、次の項を参照してください。
この項の内容は、次のとおりです。
次の前提は、この項でのタスクを実行するためのものです。
18.7項「Oracle JDevelopeを使用したPDK-Javaポートレットの構築」を読み終えて理解していること。
ウィザードで作成したポートレットがページに正常に追加されていること。
注意: 各ポートレットのデータは4Kに制限されています。パラメータ、イベント名、表示名および説明の各長さもすべてこの4Kの制限に対するカウント対象に含まれます。このため、各ポートレットに対して必要以上の数のパラメータやイベントを使用しないこと、またはこれらの名前や説明を長くしないことが必要です。 |
ポートレット・ウィザードを使用することで、パブリック・パラメータによりポートレットを簡単に作成できます。プロデューサを登録し、ページ上にポートレットをドロップすると、ポートレットのパラメータがページの変数に自動的にリンクされます。
パラメータをポートレットに追加する手順は、次のとおりです。
プロジェクトを右クリックし、ポップアップ・メニューから「新規」を選択します。
「新規ギャラリ」から、「Portlets」カテゴリ、次に「Oracle PDK Javaポートレット」項目を選択します。
「パブリック・ポートレット・パラメータ」ページが表示されるまで、普通どおりにウィザードの手順を進めます。ウィザードの手順の進め方についての基本情報は、18.7項「Oracle JDeveloperを使用したPDK-Javaポートレットの構築」を参照してください。
「パブリック・ポートレット・パラメータ」ページ(図19-6)が表示されたら、「追加」ボタンをクリックします。表に新しい行が追加されます。
「名前」列に表示されるデフォルト名をクリックします。[Backspace]キーを使用して、デフォルト名を削除します。
新しいパラメータ名(Parameter_01
など)を入力します。
「表示名」列と「説明」列について、手順6および7を繰り返します。
ポートレットに追加するパブリック・パラメータごとに、手順4〜7を繰り返します。
「終了」をクリックします。
ポートレット・ウィザードを終了すると、ポートレットが作成されます。
アプリケーション・ナビゲータで、「Webコンテンツ」ノードとWEB-INF\providers\
providername
ノードを開きます。そこにはprovider.xml
ファイルがあります。
provider.xml
を右クリックし、ポップアップ・メニューから「開く」を選択します。ウィザードの「パブリック・ポートレット・パラメータ」ページで追加したパラメータのエントリが、例19-9に示すように表示されます。
例19-9 provider.xmlのサンプル、パブリック・パラメータ
<?xml version = '1.0' encoding = 'UTF-8'?><?providerDefinition version="3.1"?> <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>MyPortlet</name> <title>My Portlet</title> <description>My Portlet Description</description> <timeout>40</timeout> <showEditToPublic>false</showEditToPublic> <hasAbout>false</hasAbout> <showEdit>true</showEdit> <hasHelp>false</hasHelp> <showEditDefault>false</showEditDefault> <showDetails>false</showDetails> <inputParameter class= "oracle.portal.provider.v2.DefaultParameterDefinition"> <name>Parameter_01</name> <displayName>Parameter_01</displayName> <description>My first parameter</description> </inputParameter> <inputParameter class= "oracle.portal.provider.v2.DefaultParameterDefinition"> <name>Parameter_02</name> <displayName>Parameter_02</displayName> <description>My second parameter</description> </inputParameter> <inputParameter class= "oracle.portal.provider.v2.DefaultParameterDefinition"> <name>Parameter_03</name> <displayName>Parameter_03</displayName> </inputParameter> <renderer class="oracle.portal.provider.v2.render.RenderManager"> <renderContainer>true</renderContainer> <renderCustomize>true</renderCustomize> <autoRedirect>true</autoRedirect> <contentType>text/html</contentType> <showPage>/htdocs/myportlet/MyPortletShowPage.jsp</showPage> <editPage>/htdocs/myportlet/MyPortletEditPage.jsp</editPage> </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
ウィザードでは、ポートレットのportletname
ShowPage.jsp
でもコードが生成されます。アプリケーション・ナビゲータでhtdocs\
portletname
ノードを開きます。
portletname
ShowPage.jsp
を右クリックし、ポップアップ・メニューから「開く」を選択します。コードは、例19-10のように表示されます。パラメータを取得するコードに注意してください。
例19-10 ShowPage.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.ParameterDefinition" %> <% PortletRenderRequest pReq = (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); %> <P>Hello <%= pReq.getUser().getName() %>.</P> <P>This is the <b><i>Show</i></b> render mode!</P> <% ParameterDefinition[] params = pReq.getPortletDefinition().getInputParameters(); %> <p>This portlet's input parameters are...</p> <table align="left" width="50%" ><tr><td><span class="PortletHeading1">Name</span></td><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 < values.length; j++) { temp.append(values[j]); if (j + 1 != values.length) { temp.append(", "); } } value = temp.toString(); } else { value = "No values have been submitted yet."; } %> <tr> <td><span class="PortletText2"><%= name %></span></td> <td><span class="PortletText2"><%= value %></span></td> </tr> <% } %> </table>
ポートレットに、ユーザーが入力したパラメータ値を送信できるようにするロジックを追加します。
手順1〜15を繰り返し、この2番目のポートレットに、取得したパラメータ値を単に表示できるようにするロジックを追加します。
プロデューサを登録して、これら2つのポートレットがコンポーネント・パレットに表示されるようにします。4.3.1.2項「PDK-Javaポートレット・プロデューサの登録」で示した手順に従ってください。
新規または既存のページへ、作成した2つのポートレットをコンポーネント・パレットからドラッグ・アンド・ドロップします。詳細は、4.3.2項「ページへのポートレットの追加」を参照してください。
「構造」ペインでページの要素を右クリックし、「ページ定義に移動」を選択します。例19-11のようなページ定義が表示されます。ページ・レベルの変数とポートレット・レベルのパラメータに注意してください。
例19-11 ページ定義ファイルのサンプル
<?xml version="1.0" encoding="UTF-8"?> <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="10.1.3.38.90" id="untitled1PageDef" Package="view.pageDefs"> <executables> <variableIterator id="variables"> <variable Name="portlet1_Parameter_01" Type="java.lang.Object"/> <variable Name="portlet1_Parameter_02" Type="java.lang.Object"/> <variable Name="portlet1_Parameter_03" Type="java.lang.Object"/> </variableIterator> <portlet id="portlet1" portletInstance="/oracle/adf/portlet/PdkPortletProducer1_1153936627784 /applicationPortlets/Portlet1_abfc5a10_010c_1000_8003_82235f50d831" class="oracle.adf.model.portlet.binding.PortletBinding" xmlns="http://xmlns.oracle.com/portlet/bindings"> <parameters> <parameter name="Parameter_01" pageVariable="portlet1_Parameter_01"/> <parameter name="Parameter_02" pageVariable="portlet1_Parameter_02"/> <parameter name="Parameter_03" pageVariable="portlet1_Parameter_03"/> </parameters> </portlet> </executables> </pageDefinition>
これで、アプリケーションを実行し、作成した最初のポートレットに値を入力すると、それらが2番目のポートレットに表示されるようになります。
場合によっては、ポートレット・インスタンスに対してのみ認識されるパラメータが必要なことがあります。これらのパラメータは、ページには関係がなく、ポートレットに対してのみ認識されるため、プライベート・パラメータとして知られています。プライベート・パラメータは、ポートレットのナビゲーション作成中に思いがけずに役に立つことがよくあります。たとえば、複数ページのポートレットを持っている場合、これらのプライベート・パラメータを使用して、ポートレットの別のリソースにジャンプすることができます。
この項の内容は、次のとおりです。
プライベート・パラメータは、標準的なWebアプリケーションで情報をブラウザのリンクまたはフォームからサーバーに渡すために使用されます。サーバーはこれに対して処理を行い、適切なコンテンツを戻します。たとえば、ディクショナリWebサイトのユーザーがハリネズミに関する情報を求めると、サーバーに送信されるURLには、プライベート・パラメータが次のように追加されます。
http://dictionary.reference.com/search?q=Hedgehog
サーバーがページ全体のレンダリングを担当し、クライアントがサーバーと直接通信する場合、このURLのフォームは非常に役に立ちます。WebCenterアプリケーションの場合、クライアントはポートレットと直接通信しません。かわりに、Oracle WebCenter Frameworkが、クライアントとポートレットの間を仲介します。また、ほとんどのページには複数のポートレットがあるため、Oracle WebCenter Frameworkは複数のポートレットと通信します。
たとえば、ページにシソーラス・ポートレットとディクショナリ・ポートレットという2つのポートレットがあるとします。これら2つのポートレットはq
をパラメータとして使用して、ユーザーによって実行された検索問合せを記録します。ユーザーがシソーラス・ポートレットを問い合せる場合、更新されたシソーラス・ポートレットがあるページを再リクエストするためのURLには、シソーラス・ポートレットのパラメータq
を含める必要があります。また、このシソーラス・パラメータは、このポートレットに対して同じ機能を実行するディクショナリ・ポートレット・パラメータ1とは区別する必要があります。正しく修飾されたシソーラス・パラメータが使用されたURLの例は、次のようになります。
http://host/portal/page?_pageid=33,1&_dad=portal&_schema=PORTAL
&_piref33_38279_33_1_1.q=Hedgehog
パラメータ名である_piref33_38279_33_1_1.q
は完全修飾されています。このパラメータは識別され、ページ上のその他のパラメータとは区別されます。また、このURLには、ポートレットとは関係のないパラメータが含まれています。これらのパラメータは、このポートレットのものではないため、このポートレットによって使用されることはありません。
ポートレットが、次の基準を満たしていることを確認する必要があります。
ポートレット独自のパラメータがリンクおよびフォームに組み込まれるときにポートレットがこれらのパラメータを正しく修飾していること。
ポートレットに属さないパラメータをポートレットで変更しないこと。
次の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");
プライベート・パラメータに関するポートレットの役割には、ポートレットに属さないURLパラメータを妨害しないという側面もあります。このルールに準拠するために使用するユーティリティの詳細は、19.2.2.3.3項「ポートレットのURLタイプを使用したリンクの構築」および19.2.2.3.4項「ポートレットのURLタイプを使用したフォームの構築」を参照してください。
ポートレットが自身をレンダリングする場合、Oracle WebCenter Frameworkではポートレットに様々なURLを渡し、ポートレットはそれらを使用してリンクをレンダリングします。これらのURLをフェッチし、操作して、リンク作成のタスクを簡略化できます。ポートレットに提供されるURLのリストは、次のとおりです。
PAGE_LINK: ポートレット・インスタンスがあるページのURLです。このURLは、すべてのポートレット内リンクのベースとして使用します。ユーザーを同じポートレットの別のセクションにナビゲートするリンクをポートレットでレンダリングする場合、このナビゲーションは、PAGE_LINKを使用してパラメータ・セットとしてエンコードする必要があります。
DESIGN_LINK: ポートレットのパーソナライズ(編集モード)・ページのURLです。ポートレットの編集モードおよびデフォルト編集モードは、ポートレットと同じページ上にはレンダリングされません。編集モードおよびデフォルト編集モードは、ブラウザ・ウィンドウ全体を占有します。ポートレットの編集モードおよびデフォルト編集モードは、必ずしもすべてのユーザーがアクセスできるとはかぎりません。このページは、ポートレットがそのパーソナライズオプションを自由にレンダリングできる最小限の静的フレームワークです。このURLは、パーソナライズ・リンクをレンダリングする際にのみ役立ちます。
BACK_LINK: ポータルが自身をレンダリングする現行ページから戻る便利なポイントのURLです。たとえば、ポートレットがそのパーソナライズ・ページ(編集モード)をレンダリングする場合、このリンクは、ポートレットがあり、ユーザーがパーソナライズ・ページへナビゲートした元のページを参照します。このため、このリンクは、保留中のアクションを受け入れる、または取り消すボタンにエンコードします。このURLは、ポートレットのデスクトップ・レンダリングでのみ役に立ちます(通常は編集またはデフォルト編集モード)。
ポートレットのURLタイプを使用してリンクを構築するには、ポートレットのレンダリング・コードの作成時にこれらにアクセスして使用する必要があります。リンクのURLをフェッチするには、PDK-Javaで次の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
を設定する初期の実行フォームの詳細は、19.2.2.3.4項「ポートレットのURLタイプを使用したフォームの構築」の例を参照してください。
<% 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 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つの基本ルールに準拠するためのユーティリティが含まれています。
ポートレットのパラメータ名を正しく修飾するためのコードは、19.2.2.3.3項「ポートレットの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を戻すのみであるため、これはモバイル・ポートレットでも使用できます。
次の例のフォームは、シソーラス・ポートレットの送信フォームをレンダリングします。このフォームの送信結果であるポートレットの詳細は、19.2.2.3.3項「ポートレットの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に基づいて、ポートレット・コード内のブランチ・ロジックは、どのポートレットのセクションをレンダリングするのかを確認できます。このオプションは、19.2.2.3.3項「ポートレットのURLタイプを使用したリンクの構築」および19.2.2.3.4項「ポートレットのURLタイプを使用したフォームの構築」に示されているシソーラス例を少し拡張したものです。基本的に、このポートレットは、パラメータ値q
を使用してシソーラスの検索動作を実行するのでなく、パラメータ値に基づいて分岐し、これに応じて様々なコンテンツをレンダリングします。
前の項目と同じようにナビゲーション情報を渡します。ただし、PDK-Javaを使用してパラメータを解釈し、その値に基づいて分岐してください。この方法の場合、シソーラスの例をいくらか変更する必要があるため、後でその詳細を説明します。
セッション記憶域を使用してポートレットの状態を記録し、プライベート・パラメータを使用して明示的なナビゲーションではなくアクションを示します。この方法は、ポートレットが含まれるページからユーザーが移動したときにポートレットを前の状態にリストアする唯一の方法です。ユーザーがこのページから移動すると、すべてのプライベート・ポートレット・パラメータは失われ、セッション記憶域にある状態のみをリストアできます。ただし、その状態がセッション記憶域に保管されていることが前提です。このオプションを使用するには、セッション記憶域について理解し、これを実装する必要があります。セッション記憶域の実装の詳細は、19.2.4.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-JavaフレームワークがshowPage
パラメータ値の上書きとして取得および解釈するポートレット・パラメータの名前です。PDK-Javaフレームワークは、マルチページ・ポートレットのリクエスト時にパラメータの修飾バージョンを検出すると、first.jsp
ではなくnext_page
によって示されたリソースをレンダリングします。ポートレットのパラメータであるfirst.jspは、ポートレットによってレンダリングされるため、PDK-Javaではレンダリングされません。
シソーラスの例をこのパラメータで動作するように変更できます。特に、フォーム送信ポートレットをシソーラスの入力用(ポートレットの先頭ページ)として使用し、シソーラス内をさらにドリルダウンしていくためのリンクが含まれる結果ページにユーザーをナビゲートできます。次の例は、これらの変更内容を示します。
注意: 次の例は、このシソーラスの例のように、比較的簡単なケースの場合に最も役に立ちます。ウィザードの使用経験を積む必要があるなど、より込み入った必要性がある場合は、StrutsなどのMVCフレームワークを使用することを検討してください。Strutsアプリケーションからポートレットを構築する方法の詳細は、19.4項「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 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>
プライベート・パラメータによるナビゲーションの実装における危険の1つは、制限する必要のあるポートレット・リソースにユーザーがナビゲートできることです。ユーザーがナビゲートしてもよいリソースを制御するには、ユーザーがナビゲートできる受入可能なリソースのホワイトリストを作成します。ナビゲーションを制限するためのホワイトリストを作成しないと、ポートレットのリソースは、次のデフォルト・ルールに従ってアクセス可能になります。
サーブレット・ルート直下のパスはナビゲート可能です。たとえば、/index.jsp
はアクセス可能ですが、/WEB-INF/web.xml
にはアクセスできません。
htdocs
ディレクトリの下のパスはナビゲート可能です。たとえば、/htdocs/multipage/first.jsp
と/htdocs/lottery/lotto.jsp
はどちらもアクセス可能です。
このデフォルトの動作を変更するには、許容できるパス値をプロバイダ定義ファイルprovider.xml
に追加します。たとえば、pageParameterName
プライベート・パラメータに応じて、リクエストを他のページに転送するコントローラとして、JSPが使用されるポートレットがあるとします。例19-12のXMLの抜粋では、/htdocs/multiportlet
の下のリソースのみが表示されます。その他のリソースは、すべて制限されます。
例19-12 provider.xmlファイルからのホワイトリストの抜粋
<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
<id>1</id>
<name>Multipage</name>
<title>A MultiPage Portlet</title>
...
<renderer class="oracle.portal.provider.v2.render.RenderManager">
<contentType>text/html</contentType>
<showPage>/htdocs/multiportlet/controller.jsp</showPage>
<pageParameterName>show_page</pageParameterName>
<allowedPath>/htdocs/multiportlet/*</allowedPath>
</renderer>
</portlet>
この機能のパターン一致ルールは、web.xml
ファイルのURLパターン一致と類似しています。ルールは次のとおりです。
定義されたパターンに一致する場合、リソース・パスは、ワイルドカードが使用されないかぎり、正解に一致する必要があります。
最初のワイルドカードはパス一致のためのもので、/
で始まり/*
で終わる文字列で構成されています。パスがこの文字列で始まるリソースは一致します。/htdocs/sub1/*
の<allowedPath>
値の場合、プライベート・パラメータの有効値には、/htdocs/sub1/file.jsp
と/htdocs/sub1/sub2/file2.jsp
が含まれます。
2番目のワイルドカードはタイプ一致のためのもので、*.
で始まりファイル拡張子で終わる文字列で構成されています。ページ・パラメータの有効値は、そのファイル拡張子で終わります。*.jsp
の<allowedPathvalue>
の場合、プライベート・パラメータの有効値には、/htdocs/sub1/file.jsp
と/htdocs/sub1/file2.jsp
が含まれます。
トランザクションとレンダリングを同時に実行するのではなく、トランザクションを完了してからそのトランザクションがあるページをレンダリングする方が、ポートレットにとって都合がよい場合があります。たとえば、ポートレットにデータ値を更新するリンクがあり、その更新はページ上の他のポートレットに影響を与える可能性があるとします。ページのリフレッシュによって同時にトランザクションも実行されると、そのデータ値に依存する他のポートレットは最新の値でリフレッシュされる場合と、されない場合があります。さらに、トランザクションとレンダリングがこのように結び付けられると、ブラウザでユーザーが「戻る」を押すなどの操作によって、トランザクションが繰り返され、レコードが重複して作成されるなどの可能性があります。
JSPポートレットでは、processAction
メソッドを使用してこの問題を解決できます。このメソッドを使用すると個々のポートレットは、ページのレンダリングが行われる前に、値の更新などのトランザクションを完了できます。PDK-JavaにはprocessAction
がありませんが、別のメカニズムを使用してサーブレットにデータを送信することにより、同じ結果を得ることができます。ページ・フローおよびポートレットの制御にStrutsを使用している場合は、form
タグおよびトランザクション・トークンを使用して、同じパラメータが2回送信されないようにすることができます。Strutsポートレットの詳細は、19.4項「Strutsポートレットの作成」を参照してください。
別の方法として、共有画面モードではなく、編集モードでデータを送信することもできます。編集モードなど、フル・ページ・ポートレット・モードに基づくリクエストは、リンクを生成したポートレットにのみ送信されます。同じポータル・ページの他のポートレットはレンダリング・リクエストに気付くこともありません。このため、このようなフル・ページ・ポートレット・モードを使用すると、ページおよびその他のポートレットと切り離してポートレットのトランザクションを実行できます。
ポートレットの送信を実行した後は、戻りURLを使用してフル・ページ・ポートレット・モードからページにリダイレクトします。この操作により、次の2つの効果を得ることができます。
ユーザーは元のページに戻ります。
フォーム送信のすべてのトレースをブラウザから消去します。
この結果、データ送信処理の後にすべてのページ・リフレッシュが行われることが保証されます。ページ・リフレッシュは送信後に行われるので、ページ上のすべてのポートレットは更新後のデータにアクセスし、送信の重複は発生しないことになります。
この手法は、プライベート・イベント送信ポートレットというPDK-Java内のサンプル・ポートレットで説明されています。これは、ポートレットに単純なフォームを送信し、フォームのコンテンツのログを記録する処理を示します。プライベート・イベント送信ポートレットでは、データ送信とパーソナライズのためのポートレット・レンダリングの両方を扱うように、編集モードをオーバーロードします。他のフル・ページ・ポートレット・モード(ヘルプ、情報、デフォルト編集)でもこの目的に関して同じ効果が得られます。
このポートレットの編集モードには、最初に特定のパラメータを探す追加コードが含まれています。このパラメータが存在する場合は、リクエストはプライベート・イベントを表すことになります。パラメータを識別するために様々な値を使用して、同じモードで多数の様々なプライベート・イベントを扱うことができます。識別パラメータが存在しない場合は、編集モードは標準のポートレット・パーソナライズ・ロジックになります。
プライベート・イベントを処理した後は、このモードはユーザーが「OK」をクリックしたときに編集モードが使用するものとまったく同じロジックを使用して、ページにリダイレクトされます。この手法を示す完全なソース・コードは、サンプル・ファイルのEditServlet.java
を参照してください。
注意: この手法を使用するときは、イベントの詳細情報が永続化されている必要があります。ポートレット・レンダリングはイベント・プロセスと同じリクエスト・サイクルで起こらないので、ポートレットをレンダリングするために必要なイベントのすべてのデータは、ストレージから入手できる必要があります。そうしないと、次にレンダリングするときに、必要なデータがポートレットまたはページにない場合があります。データを永続化する必要がある場合は、(ユーザー・リファレンスおよびポートレット・リファレンスで)修飾した形式で格納します。修飾されていないと、あるユーザー/ポートレットからのイベントが、誤って別のページで別のユーザーの同じポートレットのレンダリングと関連付けられたり、同じユーザー/同じポートレットが同じページ上の別のポートレット・リファレンスと関連付けられたりする可能性があります。 |
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}/{producer name}/{variable name}
共有名の書式は、次のようにする必要があります。
{company}/{component name}/{producer name}/global
これらの意味は、次のとおりです。
{company}
: アプリケーションを所有する会社名です。
{component name}
: プロバイダが関連付けられているアプリケーションまたはコンポーネントの名前です。
{provider name}
: プロデューサのサービス名です。
{variable name}
: 変数自体の名前です。
これらの命名規則は、Javaパッケージに使用されている命名規則と似ています。この方法により、アプリケーションまたはアプリケーション・コンポーネントの間で名前が衝突する可能性を最小限に抑えることができます。PDK-Javaには、プロデューサのサービス名をサーブレットまたはJSPにハードコーディングせずにこの書式の変数を取得するためのユーティリティが用意されています。このサービス名は、プロデューサのWARファイルに定義しておくのみでよいのです。JNDI変数の取得方法は、19.2.3.3項「JNDI変数の取得」を参照してください。
プロデューサ・デプロイでは、JNDI変数の一部またはすべてに対して新しい値を設定できます。このタスクは次の2つの方法で実行できます。
Oracle Enterprise Manager 10gを使用している場合は、そこから変数を設定できます。
OC4Jのスタンドアロン・インスタンスを使用している場合は、PDK-Javaのorion-web.xml
ファイルの変数値を手動で変更する必要があります。
Oracle Enterprise Manager 10gで変数値を設定する手順は、次のとおりです。
Oracle Enterprise Manager 10gで、PDK-JavaをデプロイしたApplication Serverインスタンスをクリックします。
このデプロイを示す名前をクリックします。
「アプリケーション」タブをクリックします。
「表示」プルダウン・リストから、「モジュール」を選択します。
モジュールの名前をクリックします。
「管理」タブをクリックします。
「環境エントリ・マッピング」の「タスクに移動」アイコンをクリックします。
「環境エントリ・マッピング」ページに、すべての環境変数が表示されます。デフォルト値は値ヘッダーの下に表示されます(存在する場合)。特定の変数の値を更新するには、この変数の行のテキスト・ボックスに新しい値を入力します。
必要なすべての変数値を更新した後、「OK」をクリックします。
新しい設定が有効になるようにOC4Jを再起動します。
変数値を手動で設定する手順は、次のとおりです。
テキスト・エディタでorion-web.xml
ファイルを開きます。このファイルが存在しない場合は、これを作成する必要があります。Oracle Application Serverのフル・インストールの場合、ファイルは次の場所にあります。
ORACLE_HOME\j2ee\OC4J_instance\application-deployments\deployment_name
OC4Jのスタンドアロン・インスタンスの場合、ファイルは次の場所にあります。
ORACLE_HOME\j2ee\home\application-deployments\jpdk\jpdk
設定対象のデプロイ・プロパティごとに、次のエントリを追加します。
<env-entry-mapping name="jndi_var_name">value</env-entry-mapping>
ファイルを保存して閉じます。作業完了後のファイルは次のようになるはずです。
<orion-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation= "http://xmlns.oracle.com/oracleas/schema/orion-web-10_0.xsd" deployment-version="10.1.3.0.0" deployment-time="1134715871939" default-charset="iso-8859-1" jsp-cache-directory="./persistence" jsp-cache-tlds="standard" autojoin-session="true" temporary-directory="./temp" servlet-webdir="/servlet/" context-root="newapp1p" schema-major-version="10" schema-minor-version="0" > <!-- Uncomment this element to control web application class loader behavior. <web-app-class-loader search-local-classes-first="true" include-war-manifest-class-path="true" /> <web-app> --> <env-entry-mapping name="oracle/portal/sample/rootDirectory"> D:\prefs</env-entry-mapping> <env-entry-mapping name="oracle/portal/sample/definition"> D:\definitions\def.xml</env-entry-mapping> </web-app> </orion-web-app>
新しい設定が有効になるようにOC4Jを再起動します。
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自体によって定義および使用される変数値を取得するための簡素なユーティリティ・クラスが用意されています。これらの変数はすべて、19.2.3.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);
表19-1は、デフォルトでPDK-Javaに用意されているJNDI変数を示しています。これらの変数を宣言しない場合、PDK-Javaは、元の場所(web.xml
およびデプロイ・プロパティ・ファイル)でこれらの値を検索します。
表19-1 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 Application Server 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 |
「デフォルトの編集」のパーソナライズをエクスポートおよびインポート可能かを決定するブール型フラグ。 |
ユーザーがページにアクセスすると、ページではパブリックの認証されていないセッションを開始し、リクエスト全体のセッションに関する情報を追跡します。ユーザーがログインすると、このセッションはログイン・ユーザーの認証済セッションとなります。このセッションは、次の場合に終了します。
ブラウザ・セッションが終了したとき(つまり、ユーザーがすべてのブラウザ・ウィンドウを閉じたとき)
ユーザーが明示的にログアウトしたとき
ユーザーのアイドル時間が設定時間を超えたためにセッションがタイムアウトしたとき
ポートレットをページに提供するプロデューサが、なんらかの特別な処理のためにコールされるように登録時に指定している場合、メタデータ生成の一環として、プロデューサすべてに連絡します。このコールにより、プロデューサは、ユーザー・セッションに基づいて処理を行い、必要に応じてプロデューサのアプリケーションのユーザーをログに記録し、プロデューサ・セッションを確立できるようになります。プロデューサの場合、このコールはinitSession
と呼ばれます。Web対応型アプリケーションの大部分はCookieを使用してセッションを追跡するため、アプリケーションのプロデューサはCookieを戻すのにこのAPIコールを利用できます。
セッション・ストアを使用すると、ポータル・セッションの間存続する情報を保存および取得できます。この情報が有効で使用可能なのは、そのセッションの存続期間中のみです。セッション・ストアに格納するのは、一時情報のみです。アプリケーション開発者はこのセッション・ストアを使用して、現行のユーザー・セッションに関する情報を格納できます。セッション・ストアのデータは複数のポートレット間で共有できます。
格納する情報を複数のセッションにわたって存続させる必要がある場合は、セッション・ストアのかわりにプリファレンス・ストアに格納できます。一般的なセッション・ストアの適用例を次に示します。
ロードや演算にコストがかかるデータ(たとえば、検索結果)をキャッシュする場合。
ポートレットの現在の状態(たとえば、ポートレットに表示された検索結果の現在の範囲(ページ)やユーザーが実行したイベントの順序)をキャッシュする場合。
注意: 複数の中間層間でセッション状態をレプリケートする必要がある場合、Webアプリケーションを分散可能としてマークし、OC4Jサーバーのクラスタ・アイランドを作成する必要があります。詳細は、『Oracle Containers for J2EEサーブレット開発者ガイド』を参照してください。 |
セッション記憶域を実装する前には、パフォーマンス・コストを慎重に検討する必要があります。ポートレットとプロデューサはリモートであるため、セッション・ストアに情報を作成して保持する操作は、少ない情報量であっても比較的コストがかかる可能性があります。このため、多数のユーザーが頻繁にアクセスするパブリック・ページについては、セッション記憶域の実装を避けた方がよい場合があります。
また、Webプロデューサでセッション・ストアを使用する場合は、メモリー内の状態情報を追跡する必要があるステートフルなアプリケーションを作成します。同様に、プリファレンス・ストアのファイル・システム実装を使用する場合も、ステートフルなアプリケーションを作成します。
スケーラビリティに重要な関心がある場合、ステートフルなアプリケーションは問題発生の原因となる可能性があります。ステートフルなアプリケーションは、使用している構成のロード・バランシングとフェイルオーバー・メカニズムに影響を与えることがあります。これは、複数の中間層をデプロイしても、状態を追跡するためには面倒なルーティング(同じノードが後続のリクエストを同じセッションで処理する)を実装する必要があるためです。このルーティングによって、ノードがクラッシュした場合に不均衡なロード・バランスやセッション・データの消失が発生し、フェイルオーバーに影響を与えることがあります。多くの開発者がステートレスなアプリケーションの構築を選ぶ理由の1つはここにあります。ただし、スケーラビリティが問題でない場合、ステートフルなアプリケーションによる問題は発生しません。
この項の例では、共有画面モードでポートレットをレンダリングした回数をカウントするために、セッション記憶域を使用します。
次の前提は、この項でのタスクを実行するためのものです。
18.7項「Oracle JDevelopeを使用したPDK-Javaポートレットの構築」を読み終えて理解していること。
ウィザードで作成したポートレットがページに正常に追加されていること。
PDKフレームワークでは、セッションをProviderSession
オブジェクトを使用して表します。このオブジェクトはプロバイダ・インスタンスのinitSession
メソッドへのコールの際に確立されます。このオブジェクトは、ProviderUser
と関連付けられています。リクエスト間でデータを永続的に保持するには、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
プロデューサをセッション・サポートに登録します。ポートレットの登録方法に関する注意は、18.10項「ポートレットの登録と表示」を参照してください。
この項では、Javaポートレットで使用できるセキュリティ・サービスについて説明します。
この項で参照されているPDKクラスの詳細は、次の「Portlet Development」ページの「Java Doc API」をクリックして、OTNのJavaDocを参照してください。
http://www.oracle.com/technology/products/ias/portal/portlet_development_10g1014.html
次の前提は、この項でのタスクを実行するためのものです。
18.7項「Oracle JDevelopeを使用したPDK-Javaポートレットの構築」を読み終えて理解していること。
ウィザードで作成したポートレットがページに正常に追加されていること。
この項では、ポートレット・プロデューサの保護に使用できる主な機能について説明します。
ユーザーが初めてログインするときは、アイデンティティを確認してアクセス権限を取得するためにパスワードを入力する必要があります。詳細は、第10章「WebCenterアプリケーションの保護」を参照してください。
ユーザーが認証されると、プロデューサ・コードは、次のように、HttpServletRequest
オブジェクトにあるPortletRenderRequest
から、認証されたユーザーのアイデンティティにアクセスできます。
PortletRenderRequest pr = (PortletRenderRequest)request.getAttribute (HttpCommonConstants.PORTLET_RENDER_REQUEST); String userName = pr.getUser().getName();
このユーザー・アイデンティティを機密性の高い操作に使用する場合、基本的なメッセージ認証を使用してアイデンティティ・アサーションの整合性を確認するようにこのプロデューサが構成されているかどうかを確認することが重要です。
また、JAZN-LDAPを使用してからJ2EEセキュリティを使用するように、JPDKプロデューサが含まれるOC4Jを構成することもできます。この場合、次のメソッドを使用してユーザー・アイデンティティを取得できます。このメソッドも、HttpServletRequest
オブジェクトにあります。
String userName = request.getRemoteUser();
ユーザーPrincipal
が必要な場合、次を使用することもできます。
Principal userPrincipal = request.getUserPrincipal();
この方法でプロデューサのOC4Jコンテナを構成する場合、拡張メッセージ認証を使用してこの形式のアイデンティティ・アサーションの整合性を確認するようにこのプロデューサを構成する必要があります。
認可によって、特定のユーザーがポートレットの表示または対話を行えるかどうかが判断されます。認可チェックの詳細は、第10章「WebCenterアプリケーションの保護」を参照してください。
これまでに説明したユーザー認証と認可では、プロデューサが受信したメッセージの信頼性までは確認されません。プロデューサを完全に保護するには、プロデューサとの通信を保護します。通信が保護されていないと、誰かがアプリケーション・インスタンスを装い、プロデューサをだまして機密情報を返信させる恐れがあります。通信セキュリティには、次の4種類があります。
サーバー認証では、プロデューサへのアクセスを少数の認証されているマシンに制限します。この方法では、受信したHTTPメッセージのIPアドレスまたはホスト名をトラステッド・ホストのリストと比較します。リストにIPアドレスまたはホスト名がある場合、メッセージはプロデューサに渡されます。リストにないと、そのメッセージはプロデューサに達する前に拒否されます。詳細は、19.2.5.5項「サーバー・セキュリティ」を参照してください。
メッセージ認証では、共有キーに基づいてチェックサムをプロデューサのメッセージに追加します。プロデューサがメッセージを受信すると、予想されるチェックサムの値を計算し、その値と実際に受信した値とを比較することによって、メッセージの信頼性が確認されます。それらの値が同じ場合、メッセージは受け入れられます。値が異なっている場合、メッセージは拒否され、その後の処理も行われません。送信中にメッセージが不法に記録されて後で再送信される可能性を低くするために、チェックサムにはタイムスタンプが含まれています。詳細は、19.2.5.6項「メッセージ認証」を参照してください。
メッセージの暗号化は、アプリケーションとプロデューサ間の通信にHTTPSプロトコルを使用することによって行われます。メッセージは高度に暗号化され、その中でデータが保護されます。暗号化によって高水準のセキュリティを確保できますが、メッセージごとに追加処理が必要になるため、パフォーマンスが低下します。
ユーザー入力のエスケープでは、アプリケーションはXSS攻撃から保護するために、ユーザーが入力した任意の文字列をエスケープし、テキストのみとして処理します。XSS攻撃では、攻撃者はユーザー入力フォームを介して悪意のあるスクリプトで渡そうとします。たとえば、ポートレット・タイトルがカスタマイズ可能な場合、攻撃者はタイトル・パラメータ・エントリによってポートレットにスクリプトまたはコマンドを渡そうとすることがあります。このため、デフォルトの動作では、ユーザー入力がエスケープされ、すべての着信スクリプトが使用不可になっています。詳細は、19.2.5.7項「ユーザー入力のエスケープ」を参照してください。
ポートレットは、アプリケーションへのウィンドウの役目を果します。ポートレットにはサマリー情報が表示され、アプリケーションのすべての機能にアクセスする方法が提供されます。ポートレットにはWebCenterアプリケーションにアプリケーションの一部が表示され、通常はユーザーがいくつかのアプリケーション・タスクを実行できます。
注意: Oracle WebCenter Frameworkでは、ポートレットからアプリケーションへのディープ・リンクはサポートされていません。ユーザーは、アプリケーション・ポートレット自体の中に表示されるものにしかアクセスできません。 |
アプリケーションでは、ポートレットを介してアプリケーションにアクセスするユーザーを認証する必要があります。次のアプリケーション認証方法があります。
外部アプリケーション。この認証方法では、Oracle Application Server Portal(OracleAS Portal)ユーザーとアプリケーションのユーザーは異なりますが、アプリケーションのユーザー名とパスワードはOracleAS Portalユーザーが管理します。
アプリケーションによる認証がない場合。この場合、プロデューサとOracleAS Portal間の通信はまったく保護されません。
外部アプリケーションでは、WebCenterアプリケーションとは異なる認証サーバーを使用します。これは、ユーザーがWebCenterアプリケーションにすでにログインしている場合、そのユーザーを、ユーザー名やパスワードを入力せずに、外部アプリケーションにもログインできるようにすることを意味します。
注意: Oracle WebCenter Frameworkでは、ポートレットからアプリケーションへのディープ・リンクはサポートされていません。ユーザーは、アプリケーション・ポートレット自体の中に表示されるものにしかアクセスできません。 |
ユーザーの認証を管理しているアプリケーションは、管理者がそのアプリケーションを外部アプリケーションとして登録している場合、Oracle Single Sign-Onと柔軟に統合できます。以前にOracle Single Sign-Onによって認証されたユーザーが初めて外部アプリケーションにアクセスすると、Oracle Single Sign-Onでは、その外部アプリケーションを使用してユーザーの認証を試みます。認証プロセスでは、そのアプリケーションの登録情報と、ユーザーのユーザー名とパスワードとを結合するHTTPリクエストが送信されます。ユーザーがまだその外部アプリケーションのユーザー名とパスワードを登録していない場合、Oracle Single Sign-Onでは、認証リクエストを行う前に、必要な情報の入力をユーザーに要求します。ユーザーが外部アプリケーションのユーザー名とパスワードを入力すると、Oracle Single Sign-Onでは新しいユーザー名とパスワードがユーザーのWebCenterアプリケーションのユーザー名にマップされ、格納されます。格納された情報は、次回ユーザーが外部アプリケーションによる認証が必要なときに使用されます。
外部アプリケーションの利点は次のとおりです。
多数のポータルとの統合が可能です。ただし、優先するポータルがある場合は、アプリケーションをその優先ポータルのパートナ・アプリケーションとして統合し、他のポータルの外部アプリケーションとして統合できます。
ユーザーはシングル・サインオンを利用できます。ただし、ユーザーは異なるユーザー名やパスワードを保持する必要があります。さらに、外部アプリケーションのユーザー名のマッピングも保持する必要があります。
ユーザー・リポジトリおよびOracle Single Sign-Onに依存せずに、複数のポータルと統合できます。
アプリケーションのソース・コードへのアクセス権限が不要です。
外部アプリケーションの不利な点は次のとおりです。
ポータルと同じユーザー・リポジトリを共有しません。このため、エンド・ユーザーによるユーザー情報の管理が必要です。
ユーザー名とパスワードは、Secure Sockets Layer(SSL)を実装しないかぎり、プレーン・テキストでプロデューサに送信されます。
プロデューサはリクエストを送信するWebCenterアプリケーション・インスタンスを完全に信頼します。プロデューサは、ユーザーがログインしているかどうかの確認やポータル・ユーザー名の確認はできますが、アプリケーションによるユーザーの認証は行われていません。
アプリケーションによる認証がない場合の利点は次のとおりです。
最も簡単な形式で統合し、最も短時間で実装できます。
アプリケーションによる認証がない場合の不利な点は次のとおりです。
最も低いセキュリティ・レベルになります。
WebCenterアプリケーションとの最も弱い統合になります。
ポートレットのセキュリティ・マネージャはプロデューサ内部に実装され、特定のユーザーがポートレットのインスタンスを表示できることを確認します。ユーザーがポートレット・インスタンスを含むページを表示すると、セキュリティ・マネージャによって、そのユーザーにポートレットを表示する適切な権限があるかどうかが判断されます。プロデューサでアクセス制御メソッドを実装することで、適切な権限のないユーザーはポートレットからコンテンツを取得できない(つまり、ポートレットを表示しない)ように制限します。ユーザーの詳細や設定項目など指定の特性が認可ロジックを通過した場合のみ、そのユーザーはコンテンツを取得できます。プロデューサでポートレットのセキュリティ・メソッドを実装しない場合は、偽名や認証されていない名前であっても、すべてのユーザー名が通過する可能性があります。
プロデューサでは、次の2つのポートレットのセキュリティ・メソッドを実装できます。
ポートレットのリストの取得
ポートレットのアクセス可能性の確認
ポートレットは、WebCenterアプリケーションのユーザー権限、およびユーザーがメンバーとして属しているグループにアクセスできます。セキュリティ・メソッドで使用できる情報は次のとおりです。
ユーザーのデフォルト・グループ
ユーザーまたはグループの権限
すべてのグループで利用できる最高のユーザー権限
ユーザーがアクセスできるオブジェクト(データベース・プロデューサのみ)
AuthLevelSecurityManager
は、認可レベルに関する次の情報にアクセスできます。
強い認証
ユーザーは、現行のWebCenterアプリケーション・セッションでOracle Single Sign-Onによって認証されています。つまり、ユーザーは有効なユーザー名とパスワードを使用してログインし、そのセッションのコンテキスト内でポートレットをリクエストしました。
弱い認証
以前に強い認証を受けているユーザーは、セッションがアクティブではないページに戻り、そのページを表示します。永続的なCookie(ユーザーのブラウザで保持)には、以前のセッションでユーザーが有効なユーザー名とパスワードでログインしたことが示されます。
パブリックまたは認証なし
ユーザーは現行セッションのコンテキスト内でログインしたことがなく、以前にログインしたことを示す永続的な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
セキュリティ・メソッドの利点は次のとおりです。
ポートレットでは、認可レベルに従って異なる出力を作成できます。
セキュリティ・メソッドの不利な点は次のとおりです。
セキュリティ・マネージャのほとんどの実装では、認可レベルや受信メッセージにあるユーザー固有の他の要素が使用されます。このような確認は、WebCenterアプリケーション・インスタンスを装ったエンティティによって無視されることがあります。
セキュリティ・マネージャをポートレットに追加した後、次の手順に従ってこれを検証できます。
ページ作成とページへのポートレット追加を実行できる権限でWebCenterアプリケーション・インスタンスにログインしていることを確認します。
PUBLICに対して表示可能な新しいページを作成します。
Javaポートレットをページに追加します。
新しいページへの直接URLを書き留めておきます。
「ログアウト」リンクをクリックして、WebCenterアプリケーション・インスタンスからログアウトします。
ブラウザのアドレス・バーに手順4で書き留めたURLを入力して、ページに直接アクセスします。
手順2で作成したページが表示されますが、手順3で作成したポートレットは表示されません。ページにポートレットを追加したときはログインしていたため、強い認証を受けています。PDKランタイムはこれを検出し、ポートレットの追加を可能にしました。ログアウトしてページを表示したときには、強い認証がすでに失われていたため、PDKフレームワークはポートレットのコンテンツのレンダリングを許可しませんでした。
再度ログインしてページを表示すると、ポートレットの存在を確認できます。
PDKに付属の実装では提供されない特別なセキュリティ対策がポートレットに必要な場合は、独自のカスタムのPortletSecurityManager
コントローラ・クラスを用意する必要があります。そのためには、oracle.portal.provider.v2.security.
PortletSecurityManager
クラスを拡張し、インタフェースで指定されている2つのメソッドに対して実装を提供します。次に、XMLプロデューサ定義でsecurityManager
コントローラ要素のクラス属性を新しいクラス名に置き換え、子要素を適切に構成します。
プロデューサへの認可されていないアクセスを回避する1つの方法は、プロデューサへのアクセスを既知のクライアント・コンピュータに、サーバー・レベルで制限することです。プロデューサにアクセスできるのは識別されたクライアントのみであるため、この方法により、DoS攻撃を防御できます。
HTTPサーバーがこの種のセキュリティを処理する方法は、変化しがちです。使用しているHTTPサーバーを調べて、このレベルのセキュリティの実装方法を理解する必要があります。
サーバー・セキュリティの利点は次のとおりです。
プロデューサへのアクセスをトラステッド・ホストのみに制限できます。
構成を簡略化できます。
サーバー・セキュリティの不利な点は次のとおりです。
Oracle Web CacheにはIPアドレスのチェック機能がありません。プロデューサの前にOracle Web Cacheがある場合は、すべてのホストのクライアントがOracle Web Cacheに表示リクエストを送信することを防止できません。
アクセスを特定のIPアドレスとホスト名に制限しても、偽のIPアドレスとホスト名が含まれたプロデューサにメッセージを送信することで回避される可能性があります。この方法の場合、リターン・メッセージはIPアドレスがコピーされたコンピュータに送信されますが、その後も問題が発生する可能性があるため、効果的に実行するのは困難です。
PDK-Javaではメッセージ認証がサポートされているため、アクセスを指定されたプロデューサ・インスタンスまたはプロデューサ・インスタンスのグループに制限できます。プロデューサは、WebCenterアプリケーションとプロデューサの管理者のみが知っている秘密共有キーに登録されます。
WebCenterアプリケーションでは、Hashed Message Authentication Code(HMAC)アルゴリズムを使用して計算されたデジタル署名が各メッセージとともにプロデューサに送信されます。プロデューサは、そのプロデューサ独自の共有キーのコピーを使用して署名を確認し、メッセージを認証できます。この手法は、プロデューサとのSecure Socket Layer(SSL)通信で、クライアント証明書のかわりに使用できます。
WebCenterアプリケーションでは、ユーザー情報、共有キーおよびタイムスタンプに基づいて署名が計算されます。署名とタイムスタンプは、SOAPメッセージの一部として送信されます。このタイムスタンプは、UTC(協定世界時、グリニッジ標準時の学術名)を基にしているため、異なるタイム・ゾーンにある複数コンピュータ間のメッセージに使用できます。
プロデューサはこのメッセージを受信すると、その署名の独自のコピーを作成します。署名が合致すると、メッセージのタイムスタンプを現在の時刻と比較します。2つの時刻の差が許容範囲内の場合、メッセージは本物とみなされて処理されます。
セキュリティや管理上の問題が発生する可能性があるため、1つのプロデューサ・インスタンスで複数の共有キーはサポートできません。たとえば、共有キーのコピーの1つがなんらかの方法で侵害された場合、プロデューサの管理者は新しいキーを作成してすべてのアプリケーション・クライアントに配布し、クライアントはそのプロデューサ定義を更新する必要があります。この問題を回避するには、異なるプロデューサ・サービスをデプロイして、サービスごとに一意の共有キーを指定します。各プロデューサ・サービスには独自のデプロイ・プロパティ・ファイルがあるため、各サービスは他のサービスとは無関係に構成されます。同じプロデューサ・アダプタ内に複数のプロデューサ・サービスをデプロイすることによるオーバーヘッドは比較的小さいものです。
プロデューサの前にOracle Web Cacheがない場合、プロデューサ・セッションの存続期間中に同じ署名Cookieを使用するこの方法は、パフォーマンスと、リクエストを認証することによるセキュリティの間のトレードオフを意味します。署名Cookieの値が計算されるのは、最初のSOAPリクエストによってプロデューサとのセッションが確立された後の1回のみです。プロデューサ・セッションのタイムアウトが短いほど、署名の計算頻度が高くなり、不正に再送信される表示リクエストに対するセキュリティが高まります。ただし、セッションの確立に必要なSOAPリクエストでは時間がかかります。
Oracle Web Cacheを使用して表示リクエストのレスポンスをキャッシュするプロデューサでも、同様のトレードオフが必要です。キャッシュされたコンテンツは、それを取得するための署名Cookieが受信リクエストに含まれているという点で安全ですが、長期間にわたってコンテンツをキャッシュすると、プロデューサは不正な表示リクエストに対して無防備になります。
署名要素は、メッセージの傍受や再送信に対する保護を提供しますが、メッセージ・コンテンツの傍受や読取りを防ぐための処理は何も行いません。しかも、メッセージはプレーン・テキストで送信されます。メッセージの内容が認可されていない者に読み取られるのが心配な場合は、メッセージ認証をSSLと組み合せて使用する必要があります。
メッセージ認証の利点は次のとおりです。
プロデューサによって受信されたメッセージが正当なWebCenterアプリケーション・インスタンスから送信されたものであることが保証されます。
メッセージ認証の不利な点は次のとおりです。
プロデューサが複数のポータルを処理する場合は、管理上の問題が発生します。セッションのタイムアウトを短くすることによってセキュリティを非常に高くした場合は、パフォーマンス上の影響があります。
テキストにエスケープせずにユーザー入力を受け入れると、攻撃者がユーザー入力フォームを介して悪意のあるスクリプトで渡そうとするXSS攻撃の危険があります。たとえば、ポートレット・タイトルがカスタマイズ可能な場合、攻撃者はタイトル文字列を使用して、ポートレットにスクリプトまたはコマンドを渡そうとすることができます。PDK-Javaでは、そのような攻撃からポートレットを保護できるように、次の機能が提供されています。
ポートレット・タイトル内のスクリプトが実行されないように、フレームワーク・デフォルト・コンテナ・レンダラ・クラスはすべてのスクリプト文字をエンコードします。このデフォルトの動作は、JNDI変数escapeStrings
で制御されます。true
に設定すると、ポートレット・タイトル内のマークアップ・タグが表示タグ文字としてレンダリングされます。たとえば、<i>title</i>
というタイトルのカスタマイズは、titleではなく<i>title</i>
としてレンダリングされます。このモードは安全ですが、そのようにしたくない場合は、そのプロデューサのescapeStrings
をfalse
に設定できます。
escapeStrings
はWebプロデューサ内のすべての論理プロデューサに適用されます。escapeStrings
の値は、Application Server Controlコンソールから、他のJNDI変数と同じように設定できます。詳細は、19.2.3.2項「JNDI変数値の設定」を参照してください。
カスタマイズされた値をレンダリングするコードがある場合、XSS攻撃を避けるためにそれらの入力値を適切にエスケープする必要があります。これは、どのモードでページをレンダリングするコードでも同様です。PDK-Javaではこのための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());
この章の前述の各項では、完全に機能するJavaポートレットをPDKフレームワークを使用して作成する方法を説明しました。ポートレットの基本機能の設定が完了した後は、ポートレットのパフォーマンスに注目する必要があります。
キャッシュは、高度な動的コンテンツを含むWebサイトのパフォーマンスの向上に使用される一般的な手法です。この手法では、キャッシュと呼ばれる待機時間の短い大きなデータ・ストアを備えたローカル・エージェントを使用してリクエストをプロキシ化することで、動的コンテンツのデータの取得と出力の生成に伴うオーバーヘッドを大幅に削減できます。キャッシュ・エージェントは、リクエストに対して次のいずれかの方法で応答します。
リクエストされたコンテンツの有効なバージョンがキャッシュ内に存在する場合、エージェントはキャッシュされた既存のコピーをそのまま戻します。これによって、コンテンツの取得と生成というコストがかかるプロセスを省くことができます。この状況はキャッシュ・ヒットと呼ばれます。
リクエストされたコンテンツの有効なバージョンがキャッシュ内に存在しない場合、エージェントはリクエストをその宛先に転送し、コンテンツが戻されるのを待機します。エージェントはコンテンツをリクエスト元に戻し、そのキャッシュ内にローカル・コピーを格納して、同じコンテンツに対するリクエストが後で発生した場合に再利用します。この状況はキャッシュ・ミスと呼ばれます。
プロデューサは、動的コンテンツ(つまり、ポートレット)の生成元であり、多くの場合、デプロイされているWebCenterアプリケーション・インスタンスから離れた場所にあります。このため、キャッシュによるパフォーマンス向上が可能となります。アーキテクチャは、キャッシュに適切です。プロデューサでレンダリングされたポートレットをキャッシュし、キャッシュされたコピーを再利用して後続のリクエストを処理することによって、プロデューサがページ作成にもたらすオーバーヘッドを最小限にできます。
プロデューサでは、どれがアプリケーションに最も適しているかによって、次の3種類のキャッシュ方法のいずれかを使用できます。これらのキャッシュ方法の主な違いは、コンテンツが有効かどうかを判断する方法にあります。3種類のキャッシュ方法を次に示します。
有効期限ベースのキャッシュ: プロデューサはレンダリング・リクエストを受信すると、そのレスポンスに有効期限のスタンプを付けます。レンダリングされたレスポンスはキャッシュに格納され、同じコンテンツに対する後続のすべてのリクエストは、有効期限が経過するまで、このキャッシュを使用して処理されます。このキャッシュ・スキームは最も簡単でパフォーマンスが優れていると考えられます。それは、キャッシュの有効性をテストするためのオーバーヘッドがほとんどなく、ネットワークのラウンドトリップを伴わないためです。有効期限ベースのキャッシュは、コンテンツの使用期間が効率よく定義されているアプリケーションに適しています。コンテンツの使用期間が確実ではない場合、有効期限ベースのキャッシュは効果的ではありません。詳細は、19.2.6.2項「キャッシュのアクティブ化」および19.2.6.3項「有効期限ベースのキャッシュの追加」を参照してください。
無効化ベースのキャッシュ: 無効化ベースのキャッシュは、基本的には有効期限ベースのキャッシュと同様に機能しますが、任意の時点でキャッシュのコンテンツを期限切れ、つまり無効化できる点が異なります。キャッシュのコンテンツの無効化は、通常、イベントによってトリガーされます。
たとえば、当日の予定を表示するカレンダ・ポートレットの場合、ポートレットのコンテンツが生成されるのは、初めてその日のカレンダを表示したときの1回のみです。予定の追加や取消し、予定時間の変更などその日の予定に変更が発生するまで、コンテンツはキャッシュされたままです。各変更イベントは、カレンダ・アプリケーションでアクションをトリガーできます。変更イベントが発生すると、カレンダ・アプリケーションは、その変更の影響を受けるキャッシュされたポートレット・コンテンツに対して無効化リクエストを生成できます。カレンダ・ポートレットを含むページを次回に表示すると、キャッシュにはエントリが含まれていません。プロデューサは、変更後の予定で新しいコンテンツを再生成するように連絡を受けます。
この方法は、非常に効率的にコンテンツをキャッシュできます。これは、コンテンツの生成元(つまり、プロデューサ)が連絡を受けるのは新しいコンテンツの生成が必要なときのみで、固定した再生成スケジュールに拘束されないためです。詳細は、19.2.6.2項「キャッシュのアクティブ化」および19.2.6.4項「無効化ベースのキャッシュの追加」を参照してください。
有効化ベースのキャッシュ: レンダリング・リクエストを受信したプロデューサは、そのレスポンスにバージョン識別子(または「E」タグ)のスタンプを付けます。この方法でもレスポンスはキャッシュされますが、キャッシュされたレスポンスをPPEが再利用する前に、キャッシュされたバージョンがまだ有効かどうかを判断する必要があります。そのために、キャシュされたコンテンツのバージョン識別子を含めたレンダリング・リクエストをプロデューサに送信します。プロデューサは、このバージョン識別子が有効であるかどうかを判断します。バージョン識別子が有効である場合、プロデューサはコンテンツを含まない軽量のレスポンスをPPEに即座に送信し、キャッシュされたバージョンを再利用できることを通知します。バージョン識別子が無効な場合、プロデューサは新しいバージョン識別子を含む新しいコンテンツを生成し、以前にキャッシュされたバージョンを置き換えます。このキャッシュ方法では、PPEは、常にプロデューサに対してコンテンツが最新かどうかを確認する必要があります。キャッシュされたコピーの有効性は、プロデューサのロジックによって判断されます。この方法では、固定期間に依存するのではなく、キャッシュされたコンテンツの使用をプロデューサが管理できるという利点があります。詳細は、19.2.6.2項「キャッシュのアクティブ化」および19.2.6.5項「有効化ベースのキャッシュの追加」を参照してください。
次の前提は、この後の項でタスクを実行するためのものです。
18.7項「Oracle JDevelopeを使用したPDK-Javaポートレットの構築」を読み終えて理解していること。
ウィザードで作成したポートレットがページに正常に追加されていること。
でキャッシュ機能をプロデューサで使用するには、最初に、中間層キャッシュをアクティブにする必要があります。このキャッシュは、mod_plsql(データベース・プロシージャおよびデータベース・プロデューサをHTTPでコールするOracle HTTP Serverプラグイン)で使用されるキャッシュと同じであるため、PL/SQLキャッシュと呼ばれます。
通常、キャッシュに関する構成詳細の責任は、OracleAS Portal管理者にあります。
無効化ベースのキャッシュの場合は、プロデューサの前にOracle Web Cacheを構成する必要があります。リモートのプロデューサにはOracle Web Cacheがインストールされていない場合が多いことに注意してください。Oracle Web Cacheの詳細は、『Oracle Application Server Web Cache管理者ガイド』を参照してください。
Oracle Web Cacheをインストールして構成した後は、Oracle Web Cache Managerについて次の点を確認してください。
プロデューサのホスト名とポートを指していること。
キャッシュ・ルールによってプロデューサのコンテンツのキャッシュが発生しないこと。コンテンツは、プロデューサがそのレスポンスで生成するSurrogate-Controlヘッダーに従ってキャッシュされる必要があります。
有効期限ベースのキャッシュは、実装が最も簡単なキャッシュ・スキームの1つで、XMLプロデューサ定義内で宣言によってアクティブにできます。使用するManagedRenderer
の出力には、出力のキャッシュ時間(分)をそのpageExpires
プロパティに設定することによって、有効期限を設定できます。たとえば、ポートレット出力を1分間キャッシュすると仮定します。有効期限ベースのキャッシュを追加する手順は、次のとおりです。
18.7項「Oracle JDeveloperを使用した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に送信されたすべてのリクエストがキャッシュされるわけではありません。コンテンツをキャッシュするには、OracleAS Web Cacheに対してコンテンツのキャッシュを指示するディレクティブがコンテンツに含まれている必要があります。通常、Oracle Web Cacheでは、リクエストに関連付けられたURLをキャッシュ・キーとして使用しますが、Surrogate-Controlヘッダーと呼ばれる特別なHTTPヘッダーをレスポンスに設定すると追加のキーを指定できます。
Javaポートレットを構成して無効化ベースのキャッシュを使用するには、次の処理を実行する必要があります。
Oracle Web Cacheを構成します。詳細は、『Oracle Application Server 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 Application Serverインストール・タイプを使用する場合は、Oracle Web Cacheの無効化設定がすでにMID_TIER_ORACLE_HOME/portal/conf/cache.xml
に事前構成されていることを確認する必要があります。事前構成されている場合、この項の説明は無視して19.2.6.4.3項「XMLプロデューサ定義の構成」に進んでください。そうでない場合は、Oracle Web Cacheの無効化ポートレットを構成する必要があります。
最初に必要なのは、アプリケーション・サーバーに関連付けられたOracle Web Cacheインスタンスの無効化ポートのユーザー名とパスワードです。これらを取得した後は、提供されているoracle.webdb.provider.v2.cache.Obfuscate
Javaユーティリティを使用して、このユーザー名とパスワードを、JAWC APIに必要な書式の不明瞭化された文字列に変換します。デフォルトのOracle Application Serverインストールでは、通常、無効化ポートのユーザー名はinvalidator
で、パスワードはアプリケーション・サーバー管理者のパスワードと同じです。たとえば、無効化ポートのユーザー名にinvalidator
を、パスワードにwelcome
を指定して、Oracle Application ServerをD:\as904
にインストールするとします。次のコマンドを実行します。
注意: 次に示すコマンドは、PDK-Javaのインストレーション・ガイドで指示されているように、pdkjava.jar およびjawc.jar がORACLE_HOME /j2ee/home/shared-lib/oracle.jpdk/1.0 に存在することを前提にしています。
スタンドアロンのOC4Jインストールを使用している場合は、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.http.configfile
を使用してこの構成ファイルを検索します。Oracle Application Serverインストール内のOC4Jインスタンスに対してこのシステム・プロパティを設定するには、PDK-Javaがインストールされている特定のインスタンスのoc4j.properties
ファイル(たとえば、MID_TIER_ORACLE_HOME/j2ee/OC4Jinstance/config/oc4j.properties
)に適切な行を追加して、そのインスタンスを再起動します。次に例を示します。
oracle.http.configfile=fully_qualified_filename
OC4Jをスタンドアロンで実行している場合は、起動するために使用するコマンドラインでオプションを指定できます。
java -Doracle.http.configfile=<fully_qualified_filename> -jar oc4j.jar
注意: キャッシュ構成ファイルの場所はシステム・プロパティとして定義されるため、サーバー・インスタンスごとに定義できるキャッシュは1つのみです。各Oracle Web Cache構成の背後に、2つの異なるプロデューサ・インスタンスを指定することはできません。 |
provider.xml
でタグの組合せを使用すると、ポートレット全体またはそのページの一部に対して自動無効化ベースのキャッシュをアクティブ化できます。自動無効化ベースのキャッシュをオンにするには、それを、次に示すように各ページまたはレンダラのレベルで宣言して、無効化ベースのキャッシュがすべてのページに対してアクティブ化されていることを示す必要があります。
<useInvalidationCaching>true</useInvalidationCaching>
ポートレットで(編集モードまたはデフォルト編集モードでの)パーソナライズをサポートしている場合は、レンダラに対しても<autoInvalidate>true</autoInvalidate>
を宣言できます。編集モードで「OK」または「適用」をクリックすると、この宣言によって、キャッシュされたポートレット・コンテンツがすべて無効化されます。したがって、パーソナライズされた設定に基づいて、新しいマークアップが生成されます。
ページをキャッシュに保持する最大時間は、次の時間についての最小時間となります。
キャッシュ・システムで定義された最大有効期間。
最大有効期間が指定されていない場合は、プロデューサのデフォルト(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つの形式のキャッシュは、相互に排他的です。無効化ベースのキャッシュは、プロデューサと同じ場所にあるOracle Web Cacheインスタンスで発生します。有効期限ベースのキャッシュを使用して格納されたページは、中間層にキャッシュされます。 |
provider.xml
の構文の詳細は、OTNでプロデューサのJavaDocを参照してください。
http://www.oracle.com/technology/products/ias/portal/html/javadoc/xml_tag_reference_v2.html
リクエストの処理、またはなんらかの情報の更新が行われたときに、ポートレットのキャッシュされたバージョンを無効化する必要が生じる場合があります。このような場合は、手動でキャッシュを無効化できます。
PDK-Javaに付属する無効化ベースのキャッシュのポートレット・サンプルには、コンテンツがキャッシュされた時刻、および無効化リクエストをトリガーするためのリンクを表示する単一のポートレットが含まれています。プロデューサに対するページ・リクエストがキャッシュを介して初めて行われたときは、そのレスポンスがキャッシュされます。ポートレットのコンテンツに対する後続のリクエストは、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
を更新する必要はありません。ポートレットを表示するには、ページをリフレッシュするか、ポートレットをページに追加してコンテンツを更新します。コンテンツが変更されている場合、ポートレットは新しいコンテンツを表示します。コンテンツが変更されていない場合は、キャッシュされたバージョンのポートレットが表示されます。
ポートレットのパーソナライズを実装した場合、「パーソナライズ」リンクは、認証されたユーザーのポートレットにのみ表示されます。したがって、ポートレットのパーソナライズ(「パーソナライズ」リンク」)をテストするには、ポートレットを使用するアプリケーションに対して、なんらかの形のセキュリティを実装しておく必要があります。テストのためには、最も基本的な認証を構成すれば済みます。詳細は、10.6項「ポートレット・パーソナライズをテストするための基本認証の構成」を参照してください。
この項では、WebCenterアプリケーションで使用するStrutsポートレットをOracle JDeveloperで作成するフレームワークについて説明します。Strutsタグ・ライブラリをOracle Application Server Portal Developer Kit(リリース9.0.4.0.2以上)からOracle JDeveloperに追加して既存のアプリケーションからStrutsポートレットを作成し、次にOracle PDK Javaポートレット・ウィザードを使用してJavaポートレットを作成する方法を説明します。この項では、次のタスクを説明します。
この項では、Apache Strutsの使用について説明します。Strutsは、Model-View-Controller(MVC)設計パターンの実装です。この項では、次のトピックについて説明します。
エンタープライズ・アプリケーションは、次のような複数の異なるタスクを実行します。
データ・アクセス
ビジネス・ロジックの実装
ユーザー・インタフェースの表示
ユーザーの相互作用
アプリケーション(ページ)フロー
Model-View-Controller(MVC)アーキテクチャは、データ表示などのアクティビティはデータ・アクセスから分離する必要があるという前提に基づいて、これらのタスクを区分する方法を提供します。このアーキテクチャによって、データソースをアプリケーションに簡単にプラグインでき、ユーザー・インタフェースをリライトする必要はありません。MVCでは、アプリケーションを論理的にモデル、ビューおよびコントローラの3つのレイヤーに区分できます。
モデル
モデルは、アプリケーション・データとビジネス・ロジック用のリポジトリです。モデルの目的の1つは、データベースからデータを取得し、データをデータベースに保持することです。また、モデルでは、ビューからデータにアクセス可能にするなどの方法でデータの公開を行い、ビューから入力されたデータの検証と消込みを行うためにビジネス・ロジック・レイヤーを実装します。アプリケーション・レベルでは、モデルは、ユーザー・インタフェースと表示されるビジネス・データの間で検証および抽象化のレイヤーとして機能します。データベース・サーバー自体は、モデルの永続的なレイヤーとして機能します。
ビュー
ビューは、JSPを使用して、モデルのデータをレンダリングします。ビューのコードには、ハードコーディングされたアプリケーションやナビゲーション・ロジックは含まれていませんが、ユーザー・ロールに基づいて条件付きデータを表示するなどのタスクを実行するロジックが含まれている場合があります。エンド・ユーザーが、ビューでレンダリングされたHTMLページ内で操作を実行すると、イベントがコントローラに送信されます。これによって、コントローラは次のステップを決定します。
コントローラ
コントローラはMVCパターンの重要な基軸です。ビューで実行されるすべてのユーザー操作は、コントローラを介して送信されます。コントローラは、ブラウザからのリクエストの内容に基づいて、次の操作を実行します。
コントローラを起動する方法はいくつかあります。たとえば、URL引数を使用して、リクエストを適切なコードにルーティングできます。MVCパターンでは、コントローラの機能を決定しますが、その動作は決定しません。
利点
MVCアーキテクチャによって、アプリケーションとその設計をモジュール単位で明確に表示できます。アプリケーション・ロジックの様々なコンポーネントとロールを区分することによって、開発者はアプリケーションを簡単で異なるコンポーネント(モデル、ビューおよびコントローラ)の集まりとして設計できます。このパターンは、保持や拡張が容易なアプリケーションの作成に役立ちます。たとえば、1つのビューを作成すると、同じビジネス・ロジックを使用して別のビューを簡単に作成できます。その使いやすさと再利用性のため、MVCパターンは、Webベースのアプリケーション開発で最も広く使用されているパターンです。
図19-7は、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」を参照してください。 |
OracleAS PDKには、パーソナライズやキャッシュなどOracleAS Portal APIの使用方法に関する多数の例やドキュメントが含まれています。ポートレットAPIでは、アプリケーション・ロジックとビジネス・ロジックを統合できません。一方、Strutsフレームワークを使用すると、MVCアーキテクチャを利用して、企業ポータル内でアプリケーションを作成および公開できます。
Oracle Strutsポートレット
Strutsフレームワークを使用したポートレットの作成、または既存のStrutsアプリケーションからポートレットの生成を行うには、すべてのコンポーネントをJ2EEコンテナにデプロイする必要があります。OracleAS Portalのコンテキストでは、StrutsアプリケーションはPPEによってコールされ、スタンドアロンのStrutsアプリケーションのようにブラウザではコールされません。図19-8に示すように、ポートレットの表示コールが送信されると、ページ・エンジンは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タグの拡張であるOracleAS Portal JSPタグを使用する必要があります。この開発プロセスは、スタンドアロンのStrutsアプリケーションを作成するプロセスに似ています。Strutsポートレットの作成方法は、19.4.2.1項「Strutsポートレットの作成」を参照してください。また、ポートレットとStrutsアプリケーションは同じサーブレット・コンテキスト内に存在する必要があるため、両方の要素を含む単一のWebアプリケーションを作成する必要があります。Oracle JDeveloperでこのようなWebアプリケーションを簡単に作成する方法は、次の19.4.2.1項「Strutsポートレットの作成」を参照してください。
Apache Strutsは、MVC設計パラダイムの明確で簡単な実装を提供しているため、MVCベースのJ2EEアプリケーションを開発するためのデフォルト標準になっています。このフレームワークによって、ポートレット開発者は、アプリケーションの様々なコンポーネントを区分し、Strutsコントローラを利用して既存のStrutsアプリケーションをOracleAS Portalに容易に公開できるため、既存のビジネス・ロジックをすべて変更する必要はありません。
注意: Oracle Application Server Portal Developer Kitの詳細は、Portal Center(http://www.oracle.com/technology/products/ias/portal/pdk.html )を参照してください。 |
OracleAS PDKには、Apache Strutsアプリケーションを統合するための新しい拡張機能が含まれています。この項では、既存のStrutsアプリケーションからポートレットを作成する方法を説明します。また、その作成手順に従うと、Model-View-Controllerパラダイムを使用するポートレットも作成できます。Apache Strutsフレームワークの詳細は、19.4.1項「Apache Strutsフレームワーク」を参照してください。この項で説明するPDK-Javaの拡張機能は、Apache Struts 1.1に準拠しています。
この項では、次の手順を説明します。
既存のStrutsアプリケーションの一部をポートレットとして公開するには、最初に、アプリケーションのPortalビューとして機能する新しいビューを作成することをお薦めします。このビューでは、既存のオブジェクト(Actions
、ActionForm
など)とともに新しいマッピングとJSPを使用します。
注意: アプリケーションのPortalビューを作成することをお薦めしますが、アプリケーションのStrutsタグをPDK-JavaのStrutsタグに置き換えることもできます。この方法を使用すると、アプリケーションをスタンドアロンStrutsとポートレットの両方として実行できます。 |
この例では、新しいエントリをWebロガー(Blog)に追加できるポートレットを作成します。図19-9および図19-10は、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ポートレット内でインラインのレンダリングを実行するには、OracleAS 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サイトのコンテキストで使用する場合は、プロデューサにインターネットから直接アクセスできることを確認する必要があります。これが不可能な場合は、OracleAS Portal中間層へイメージをデプロイし、Apache Strutsのイメージ・リンクを使用して関連リンク(アプリケーションではなくポータルに関連付けられたリンク)を生成できます。
注意: OracleAS 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ポートレット・ウィザードが開きます。ウィザードの開き方の詳細は、18.7項「Oracle JDeveloperを使用した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
ポートレットをコンシューマが使用する準備が完了すると、そのポートレットを登録してアクセス可能にする必要があります。PDK-Javaポートレットの登録方法の詳細は、18.10項「ポートレットの登録と表示」を参照してください。
Oracle Application Serverを使用すると、Oracle JDeveloperを使用してStrutsポートレットを容易に作成でき、既存のStrutsアプリケーション・ポートレットを公開できます。Oracle JDeveloper Javaポートレット・ウィザードの使用方法の詳細は、第18章「Javaポートレットの作成」を参照してください。
Strutsの場合と同様、Oracle ADFはMVCの設計パターンに準拠しています。Strutsコントローラを使用するOracle ADFアプリケーションは、Strutsアプリケーションの場合と同じように、ポートレットに変換してデプロイできます。19.4.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>
場合によっては、作成したOracle ADF Facesアプリケーションを利用して、ポートレットとして公開できます。そのようなポートレットは、JSFポートレット・ブリッジと呼ばれることがあり、Oracle ADF FacesページをJPS(JSR 168)ポートレットとして実行します。
注意: 特に言及がないかぎり、この項の内容は、JSF参照の実装にも同様に適用されます。 |
この項では、Oracle ADF FacesアプリケーションのJPSポートレットとしての公開について、次の情報を提供します。
既存のアプリケーションからJSFポートレットを作成する手順は、次のとおりです。
JSFアプリケーション・ワークスペースを開きます。アプリケーションをポートレット化するために最初に行う作業は、必要なJSFポートレット・ブリッジ・ライブラリをプロジェクトに追加することです。
ポートレットを作成するアプリケーションを含むプロジェクトを右クリックします。ポップアップ・メニューから「プロジェクト・プロパティ」を選択します。
左ペインで、「ライブラリ」をクリックします。
「ライブラリの追加」をクリックします。
ポートレット・フェース・ブリッジを選択します。
「OK」をクリックします。
「OK」をクリックします。ここで、アプリケーションをポートレット・プロデューサとしてデプロイできるポートレット・デプロイメント・ディスクリプタを作成する必要があります。
プロジェクトを右クリックし、ポップアップ・メニューから「新規」を選択します。
「フィルタ方法」リストから「すべてのテクノロジ」を選択します。
左側のペインから「General」カテゴリを選択します。
「Deployment Descriptors」をクリックします。
右側の「項目」リストからportlet.xml(ポートレット・デプロイメント・ディスクリプタ)を選択します。
「OK」をクリックします。
アプリケーション・ナビゲータの「Webコンテンツ」、「WEB-INF」の下にportlet.xml
が表示されます。portlet.xml
を開き、「ソース」タブに移動します。
特定のアプリケーション用のportlet.xml
で、必要なinit-param
を追加するか、変更します。たとえば、ADFバインディングを使用するOracle ADFアプリケーション用のportlet.xml
は、例19-13のようになります。非ADFバインディングの場合は、例19-14のようになります。
特に、太字のinit-param
に注意してください。パラメータは次のとおりです。
DefaultPage.view
パラメータは、ポートレットの表示モードとして使用する、アプリケーションのデフォルト・ページを指定します。その場所は、web-app-context-root
を基準とし、常に/
で始まります。
BridgeLifecycleListeners
パラメータは、使用するフィルタ・クラスを指定します。portlet.xml
ファイルが、web.xml
ファイルで指定されているフィルタと一致するように構成されていることを確認する必要があります。portlet.xml
で適切なクラスが定義されていない場合、クラスがないというエラーが発生します。portlet.xml
ファイルのBridgeLifecycleListeners
init-param
でクラスを指定します。
<init-param> <name>BridgeLifecycleListeners</name> <value>listener_class_n[,listener_class_n+1,...]</value> </init-param>
たとえば、アプリケーションで、そのweb.xml
ファイルにAdfFacesFilter
フィルタが含まれるとします。
<filter> <filter-name>adfFaces</filter-name> <filter-class>oracle.adf.view.faces.webapp.AdfFacesFilter</filter-class> </filter>
次のクラスをportlet.xml
に含める必要があります。
<init-param> <name>BridgeLifecycleListeners</name> <value>oracle.portlet.server.bridges.jsf.adf.ADFFacesBridgeLifecycleListener </value> </init-param>
同様に、ADFBindingFilter
フィルタが、web.xml
で次のように定義されているとします。
<filter> <filter-name>adfBindings</filter-name> <filter-class>oracle.adf.model.servlet.ADFBindingFilter</filter-class> </filter>
次のクラスをportlet.xml
に含める必要があります。
<init-param> <name>BridgeLifecycleListeners</name> <value>oracle.portlet.server.bridges.jsf.adf.ADFFacesBridgeLifecycleListener, oracle.portlet.server.bridges.jsf.adf.BindingFacesBridgeLifecycleListener </value> </init-param>
例19-13 JSFポートレット(ADFバインディング)用のportlet.xmlのサンプル
<?xml version="1.0" encoding="ISO-8859-1"?> <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"> <portlet> <description>ADF Faces Demo Portlet</description> <portlet-name>ADFFacesDemo</portlet-name> <display-name>ADF Faces Demo portlet</display-name> <portlet-class>oracle.portlet.server.bridges.jsf.FacesPortlet </portlet-class> <init-param> <name>DefaultPage.view</name> <value>/index.jspx</value> </init-param> <init-param> <name>BridgeLifecycleListeners</name> <value> oracle.portlet.server.bridges.jsf.adf.ADFFacesBridgeLifecycleListener, oracle.portlet.server.bridges.jsf.adf.BindingFacesBridgeLifecycleListener </value> </init-param> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <supported-locale>en</supported-locale> <portlet-info> <title>ADF Faces Demo Portlet</title> <short-title>ADFFacesDemo</short-title> </portlet-info> </portlet> </portlet-app>
例19-14 JSFポートレット(非ADFバインディング)用のportlet.xmlのサンプル
<?xml version="1.0" encoding="ISO-8859-1"?> <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"> <portlet> <description>ADF Faces Demo Portlet</description> <portlet-name>ADFFacesDemo</portlet-name> <display-name>ADF Faces Demo portlet</display-name> <portlet-class>oracle.portlet.server.bridges.jsf.FacesPortlet </portlet-class> <init-param> <name>DefaultPage.view</name> <value>/index.jspx</value> </init-param> <init-param> <name>BridgeLifecycleListeners</name> <value> oracle.portlet.server.bridges.jsf.adf.ADFFacesBridgeLifecycleListener </value> </init-param> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <supported-locale>en</supported-locale> <portlet-info> <title>ADF Faces Demo Portlet</title> <short-title>ADFFacesDemo</short-title> </portlet-info> </portlet> </portlet-app>
アプリケーションのweb.xml
を、web.xml
で次のように定義することにより、クライアント側の状態保存メソッドを使用するように変更します。
<context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param>
これで、アプリケーションをWebアプリケーションと同様にデプロイできます。18.9項「アプリケーション・サーバーへのポートレットのデプロイ」を参照してください。
アプリケーションのデプロイに成功すると、それを他の任意のアプリケーションにポートレット・プロデューサとして登録できます。4.3.1.1項「WSRPポートレット・プロデューサの登録」を参照してください。アプリケーションがデュアル・モードで実行されます。アプリケーションは、通常のWebアプリケーションとして引き続きアクセスすることも、ポートレット・プロデューサとして使用することもできます。
プロデューサをデプロイし、登録すると、自分のJSFアプリケーションのポートレットを他のポートレットと同じように使用できます。4.3.2項「ページへのポートレットの追加」を参照してください。
JSFポートレット・ブリッジと基礎となるJSFアプリケーションの間の通信を有効にすることができます。このためには、基礎となるアプリケーションにリクエスト・パラメータとしてWSRP 2.0ナビゲーション・パラメータを渡すように、ポートレット・ブリッジを構成します。この構成では、次の例に示すパラメータをナビゲーション・パラメータとしてoracle-portlet.xmlに追加する必要があります。
<navigation-parameters> <name>Parameter_01</name> <type>xsi:string</type> <label xml:lang="en">Parameter 1</label> <hint xml:lang="en">First parameter.</hint> </navigation-parameters>
例19-15、例19-16および例19-17に、JSFポートレット・ブリッジと、ポートレットを使用するアプリケーションの間でのパラメータの引渡しを有効にするために使用されるサンプル・コードを示します。重要な項目を太字で示しています。
例19-15 JSFページのサンプル・コード(JSFParameterForm.zip:JSFParamDisplay.jspx)
<f:view> <afh:html> <afh:head title="ParamForm"> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"/> </afh:head> <afh:body> <h:form> <af:outputLabel value="Parameter 1:"/><af:outputText value="#{param.ora _wsrp_navigparam_Parameter1}"/> </h:form> </afh:body> </afh:html> </f:view>
例19-16 oracle-portlet.xmlのサンプル・コード(JSFParameterForm.zip:oracle-portlet.xml)
<?xml version="1.0" encoding="ISO-8859-1"?>
<portlet-app-extension
xmlns="http://xmlns.oracle.com/portlet/oracle-portlet-app" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<portlet-extension>
<portlet-name>JSFParameterDisplay</portlet-name>
<navigation-parameters>
<name>ora_wsrp_navigparam_Parameter1</name>
<type>xsi:string</type>
<label xml:lang="en">First parameter</label>
<hint xml:lang="en">First parameter set by portlet</hint>
</navigation-parameters>
<portlet-id>1</portlet-id>
</portlet-extension>
</portlet-app-extension>
例19-17 コンシューマ・ページのページ定義ファイルのサンプル・コード(InterPortletComm.zip:PortletCommPageDef.xml)
<?xml version="1.0" encoding="UTF-8" ?> <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="10.1.3.40.66" id="PortletCommPageDef" Package="view.pageDefs"> <parameters/> <executables> <variableIterator id="variables"> <variable Name="ParameterFormPortlet1_1_ora_wsrp_navigparam_Parameter1" Type="java.lang.Object"/> </variableIterator> <portlet id="JSFParameterDisplayPortlet1_1" portletInstance="/oracle/adf/portlet/jsfParam_1178341548071/ap/E0default _5aa185c9_0112_1000_8005_8d90409dd9cb" class="oracle.adf.model.portlet.binding.PortletBinding" retainPortletHeader="false" xmlns="http://xmlns.oracle.com/portlet/bindings"> <parameters> <parameter name="ora_wsrp_navigparam_Parameter1" pageVariable="ParameterFormPortlet1_1_ora_wsrp_navigparam _Parameter1"/> </parameters> </portlet> </executables> </pageDefinition>
パラメータの引渡しの詳細は、4.5.1項「ページへのポートレットのリンク」を参照してください。
Oracle ADF Facesのページをポートレットとして公開するには、まずOracle ADF Facesのページを、JSR 168ポートレット・マークアップ・フラグメント・ルールに準拠するマークアップを発行するようにコーディングします。幸い、Oracle ADF Facesページのマークアップの大部分は、Oracle ADF Facesのコンポーネントからのもので、コンポーネントの大部分では、マークアップは当然ポートレットと互換性のあるスタイルでレンダリングされます。
ポートレット環境で問題を起こす可能性のあるコンポーネントについては、アプリケーション開発者は特に注意が必要です。一部のコンポーネントでは、ポートレット環境と競合するマークアップが生成されるため、その使用が制限されます。その他のコンポーネントでは、開発者がポートレット環境と競合する値を紹介できるプログラム制御(入力)を使用できます。この場合、開発者は、ページをポートレットとして公開する可能性について認識し、その結果、値を正しくエンコードする必要があります。
この後のガイドラインでは、ポートレットとして公開することになるOracle ADFページをコーディングするときに知っておく必要のある問題について説明します。
この後のガイドラインでは、ポートレットとして公開することになるOracle ADFページをコーディングするときに知っておく必要のある問題について説明します。
Oracle JDeveloperでJSFポートレットを作成する際、JSFを利用するWebアプリケーション・テンプレートの1つで、アプリケーションを作成する必要があります。
すでにポートレットを含んでいるアプリケーションをポートレット化することはできません。
Facesビューの状態を管理および保存するためのクライアントの使用はサポートされていません。そのため、この状態をサーバーによって管理するように、アプリケーションを構成する必要があります。Oracle ADF Facesのデフォルトはクライアントによる管理であるので、web.xml
で次のように定義することにより、サーバー側での状態管理を使用するように、アプリケーションを明示的に構成します。
<context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param>
ディープ・リンクは、直接サポートされません。WSRPでのJSR 168ポートレット・コンテナ実装の副産物として、セッションCookie管理は、クライアントではなく、ポートレットを使用するアプリケーションが代行します。完全サービスのアプリケーションまでのディープ・リンクが張られているポートレットは、通常、共有セッションの状態に依存しているため、現行のポートレット・コンテキストからの遷移が可能です。大部分のアプリケーションがCookieによるセッション・コンテキストの保持に依存しているため、現行のアーキテクチャでは、そのような状態の共有はできません。クライアントから、アプリケーションを起動するプロデューサ・サーバーに直接つながるディープ・リンクでは、コンシューマとプロデューサ間にセッションCookieが確立されないため、もう1つのセッションが確立されます。そのような状態の共有を必要とするアプリケーションでは、2つのコンテキスト間でデータを転送するための独自のスキームを実装する必要があります。共通実装とは、この状態を使用できる場所に書き込み、この状態に対する参照をディープ・リンクで渡しことです。
Java EEログインはサポートされません。Java EEアプリケーションは、いくつかの認証テクニック(BasicとDigestなど)により構成できます。ポートレットは、コンシューマのページに組み込まれたフラグメントであるので、一般には、クライアントとポートレット・プロデューサ間ではなく、クライアントとコンシューマ間で直接認証が行われることが予想されます。その結果、これらの認証テクニックは、JSR 168ではサポートされません。JSR 168の場合は、Java EE認証が、WS-Securityメカニズムを介して行われます。WS-Securityでは、Webサービスのコンシューマがプロデューサによって認証および検証され、ユーザー認証および認可用のユーザー・アイデンティティが伝播されます。公開されるOracle ADFアーチファクトには、Java EE認証を起動するログイン・リンクを含めないでください。
JSFポートレットのコンシューマがOracleAS Portalの場合、次のことが発生する可能性があります。
不具合(5526946)により、OC4Jのバウンスの後、あるいはポートレットがしばらくの間アイドルであった場合、ポートレットが最初のリクエストでレンダリングされません。次のメッセージが表示されます。
Error: The portlet could not be contacted.
このメッセージは、ページをリフレッシュすることで解決できます。
1つのページ上に複数のJSFポートレット・ブリッジがある場合、ナビゲーションが失敗する可能性があります。この失敗は、通常、HTML要素の識別子とJavaScript関数の名前が競合するために発生します。この問題を回避するには、アプリケーションで一意の識別子とJavaScript変数を使用していることを確認します。
ポートレットのガイドラインは次のとおりです。
リソースおよびリンクについては、web-app-context-root
を基準として場所を指定する必要があります。そうしないと、ポートレットがイメージやその他のリソースを見つけられません。相対パスの表記(../)を使用しないでください。Oracle WebCenter Frameworkのポートレットは、リモートで実行され、SOAPプロトコル(WSRP)を使用してアクセスされます。後者は、通常のWebアプリケーションのリクエスト・パスの概念が、JSR 168コンテナでは意味がないということです。JSR 168仕様では、すべてのリソースURLが絶対パスまたはコンテキスト相対パスのいずれかであることが規定されていることにこれが反映されています。
リクエストをJSP内でリダイレクトまたは転送しないでください。JSR 168では、reguestDispatcher.include()
のみがサポートされます。httpServletResponse.sendRedirect()
またはrequestDispatcher.forward()
を使用すると、例外やエラーが発生します。ポートレット環境で正常に作業を行うには、faces-config.xml
でナビゲーション・ルールを持つナビゲーションを実装する必要があります。
メモリー・サイズとリクエスト・スコープ・データの使用を最小限に抑えます。JSFポートレット・ブリッジでは、内部的にリクエスト・スコープ・データをセッション・スコープに格上げします。これは、ポートレットのアクション・フェーズとレンダリング・フェーズが、2つのリクエストにまたがることができるためです。さらに、JSF Webアプリケーションと異なり、ポートレットは、1つのアクションが実行された後、何度もレンダリングできます。それぞれの場合で、リクエスト・データの有効期間は、単一のhttpリクエストより長くなります。アプリケーションでの全体のメモリー消費を最小限に抑えるには、リクエスト・スコープに、うまくレンダリングできる最小限のデータのみを格納します。
Oracle ADF Facesのガイドラインは次のとおりです。
Oracle ADF Facesのクライアント側の実装はサポートされていません。JSR 168およびWSRP 1.0の弱点の1つは、ページの部分レンダリングに、クライアント側のプログラミング・テクニック(Ajaxまたは非表示のフレームなど)を使用するポートレットに対応していない点です。その結果、クライアント側のプログラミング・テクニックに依存するすべてのOracle ADF Facesの機能が働きません。これらの機能には、次のものがあります。
Oracle ADF Faces部分ページ・リフレッシュ(PPR)機能
Oracle ADF Facesのリッチ・クライアント・コンポーネントのクライアントによるレンダリング面
Oracle ADFポップアップ<af:popup>
(PPR機能に対する依存のために機能しない)
視覚支援ポップアップを使用するOracle ADF FacesのSelectText
、SelectDate
およびSelectColor
コンポーネント
既存のアプリケーションの破壊を避けるため、ポートレットとして公開されているOracle ADF Facesページで使用する際には、ポップアプは無効になります。したがって、機能的には、これらのコンポーネントはInputText
に相当します。
ファイル・アップロードはサポートされません。サポート・ファイルをアップロードするには、Oracle ADF FacesでJSR 168には存在しない機能が必要です。そのため、ファイル・アップロード・リクエストは機能しません。
objectMedia
コンポーネントは、ポートレットでサポートされません。
Oracle ADFのガイドラインは次のとおりです。
Oracle Metadata Servicesを使用するポートレット・カスタマイズはサポートされません。JSR 168プリファレンス・モデルは、自身のリポジトリで自身のカスタマイズを管理する環境(Oracle Metadata Servicesを使用するOracle ADFなど)と互換性がありません。
WebCenterアプリケーションでJSFポートレット・ブリッジを使用する場合、ポートレットは(標準のOracle ADFスタイルではなく)JSR 168ポートレット・スタイルのみを使用できます。これにより、忠実性が失われる結果になる場合があります。
prepareModel
を処理するOracle ADFコンポーネント/コードは冪等です。prepareModel
フェーズ中に実行されるコードは、基礎のデータまたはビジネス・ロジックに影響を与えずに、再実行可能であることが必要です。ポートレット環境での実行時に、prepareModel
は、完全なJSFライフ・サイクル中に2回コールされます。これに対して、通常のWebアプリケーション内で実行される場合、コールは1回です。
この違いは、JSFポートレット・ブリッジが、JSFを1つではなく2つのリクエストで実行するためです。JSFポートレット・ブリッジは、すべてのJSFリクエストがレンダリング・フェーズの前にリダイレクトされるかのように実装されます。この方法の結果、JSF restoreView
フェーズは、リクエストが最初に送信されるときと、レンダリングのリクエストが受信されるときの両方でコールされます。
ページ・パラメータ内を除き、モデル・コードからリクエスト・パラメータをアクセスまたは参照しないでください。よりきれいなMVC2実装であることに加えて、このガイドラインに従うことで、そのようなアーチファクトがポートレットとして公開された場合に問題を回避します。通常のJSFアーチファクトが1つのリクエストで全ライフサイクルを実行するのに対して、JSFポートレット・ブリッジは、すべてのJSFリクエストがレンダリング・フェーズの前にリダイレクトされるかのように、これらのアーチファクトを2つのリクエストで実行します。
この2フェーズ・モデルにより、レンダリングの前に、送信されたパラメータのクリアが可能になります。そのようなクリアは元のクライアントにまで伝えられるため、このリクエストにはブックマークを付けることができます。その結果、リクエスト・パラメータはレンダリング・フェーズ中には存在しません。先に説明したように、このレンダリング・フェーズでprepareModelが再び起動されます。したがって、このフェーズ・ハンドラでは、リクエスト・パラメータに対する参照は失敗します。次のフラグメントのようなコードは避けてください。
<invokeAction id="doExecuteWithParams" Binds="ExecuteWithParams" Refresh="prepareModel" RefreshCondition="${param.id != null}" /> <invokeAction id="doExecuteWithParams" Binds="ExecuteWithParams" Refresh="renderModel" RefreshCondition="${param.id != null}" />
prepareModel
フェーズで、ページ・パラメータを参照しないでください。この問題は、リクエスト・パラメータについて説明した同じ問題に関連しています。一般に、ページ・パラメータはリクエスト・パラメータによって決まり、restoreView
フェーズ中に評価されます。このフェーズが、ポートレットのレンダリング中にもう一度コールされ、リクエスト・パラメータがないと、失敗に終わります。かわりに、JSFの実行フェーズからレンダリング・フェーズへの遷移の前に、ページ・パラメータ値に対する依存性をモデルに移動します。