本文へジャンプ

ソフトウェア Lotus Lotus Developer Domain 製品別技術情報 WebSphere Portal > 
   
 

IBM WebSphere Application Server V6.1ポートレット・コンテナーの活用: 第2部. より高度な機能

アプリケーションの機能を拡張する

   
 
コンテンツ
はじめに
サンプルについて
複数のポートレットの集約
ポートレット情報へのアクセス
ポートレットのフィルタリングによる出力の変更
まとめ
ダウンロード
リソース
筆者について(原文のまま)
アンケートにご協力ください
Stephan Hesmer, Performance Chief Developer, IBM
Birga Rick, Portlet Runtime Technical Lead, IBM

レベル:中級
原文の掲載:2006年 7月19日
原文はこちら (US)

この連載記事では、IBM® WebSphere® Application Server V6.1で利用できるJSR 168ポートレット・コンテナーについて解説し、IBM WebSphere Portalとの使い方の違いを明らかにします。

第1部では、ポートレットのインストール方法、ポートレットへのアクセス方法、およびURLアドレス可能度(URL Addressability)の使用方法など、ポートレット・コンテナーの概要について紹介しました。

第2部では、コンテナーの拡張機能について説明します。ウィンドウ・フレーム内でのポートレットのレンダリング、複数のポートレットの表示、デプロイされたポートレットに関する情報の取得、およびポートレットのデフォルトの動作の変更などの方法を取り上げます。

サンプル・コードをダウンロードして使用することで、WebSphere Application Server V6.1ポートレット・コンテナーの特徴を知ることができます。

この連載は、すでにJava Portlet APIに習熟されているJava™ポートレット・プログラマーの方を対象としています。これらのスキルを得るための情報については、「リソース」セクションのリンクを参照してください。


はじめに

今日では、ポータル・ユーザーは「1つのページに複数のポートレットがあり、それぞれのポートレットの内容がウィンドウ・フレーム内に表示され、制御アイコンまたはリンクによってポートレット・モードやウィンドウ状態を変更する」という使い方に慣れています。WebSphere Application Server V6.1は拡張機能セットを提供します。これらの機能を使用すると、URLアドレス可能度を用いてポートレットをカスタマイズしたり、シンプルなポータル・フレームワークを作成できます。

カスタマイズされたポータル・フレームワークを設計するには、JSPを作成します。新しいJSPタグ・ライブラリーを参照することで、ポートレットを簡単に集約できます。この集約タグ・ライブラリーにより、ポートレットのコンテンツをウィンドウ・フレーム内にレンダリングしたり、複数のポートレットを1つのページに集約することが可能になります。

ポータル・フレームワークは、ポートレットを管理するために、システム内でどのポートレットが利用できるのかを認識する必要があります。WebSphere Application Server V6.1は、ポートレットおよびポートレット・アプリケーション用に新しいManaged Bean (MBean)を提供します。これらのMBeanを使用すると、任意のデプロイ済みポートレットのデプロイメント記述子の情報にアクセスできます。

ポートレットのURLアドレス可能度は、デフォルトでHTMLをサポートします。他のマークアップをサポートしたい場合は、異なるマークアップのサポートを簡単に追加できるPortletDocumentFilterを使用します。サーブレット・フィルターと同様に、PortletDocumentFiltersはポートレットの前に呼び出され、ポートレットの動作またはデフォルトの出力を変更します。

この記事では、集約タグ・ライブラリーを使用して独自のポータル・フレームワークを構築する方法、MBean APIの使い方、および追加のマークアップをサポートするためのポートレットのカスタマイズ方法を解説します。また、この記事では、これらの機能をWebSphere Portalの同様の機能と比較し、その違いを明らかにするとともに、それぞれの製品で同じ機能を実現する方法についても解説します。

上に戻る

サンプルについて

この記事で取り上げる例のサンプル・コードをダウンロードできます。記事を読む際の参考にしてください。これらの例は、第1部で紹介した世界時計(WorldClock)ポートレット・アプリケーションに基づいています。このポートレットは、以下のダウンロード・セクションに含まれています。世界時計ポートレットの詳細については、記事『Converting the WorldClock portlet from the IBM Portlet API to the JSR 168 portlet API』を参照してください(「リソース」参照)。


上に戻る

複数のポートレットの集約

ポータル・フレームワークは、ポータル・ページ上でポートレットのコンテンツを管理、分類、および編成することができます。WebSphere Application Serverは、URLアドレス可能度によって、アイコンまたはメニュー・リンクなしで1つのポートレットをポータル・ページに表示する最も単純な方法を提供します。新しいJava Server Pageタグ・ライブラリーを使用することで、この機能を容易に拡張できます。この集約ライブラリーによって、ポートレット・アクションを処理し、複数のポートレットをウィンドウ・フレームにレンダリングするシンプルでカスタマイズされたポータル・フレームワークを作成する方法が得られます。このウィンドウ・フレームには、ポートレットのタイトルと、ポートレット・モードまたはウィンドウ状態を変更する制御リンクを表示できます。

ライブラリーには、次に示す2つのカテゴリーのタグがあります。

  1. ポータル・タグ ポートレットが実行されるポータル・コンテキストを定義する。

    たとえば、このコンテキストは、ポートレットURLのURL形式とポートレット・プリファレンスの処理方法を定義します。サーブレットとは異なり、ポートレットは常にポータル・フレームワークのコンテキスト内でレンダリングされることが必要です。

    initタグは、ポートレットのURLがポータルを参照するようポータル・フレームワークのURLを指定します。また、追加の要求パラメーターをJSPポータルとともに使用することで、流れを制御できます。

    <init
    portletURLPrefix="<portal URL>"
    portletURLSuffix="<portal specific URL suffix>"
    portletURLQueryParams="<portal specific query parameters">

  2. ポートレット・タグ ポートレット・リンクを作成するURL作成タグおよびポートレットのコンテンツを取得するポートレット呼び出しタグで構成される。

    ポートレットにはポータル・コンテキストが必要なので、これらのポートレット・タグはポータルのinitタグ内に埋め込まなければなりません。

    • stateタグは、指定された状態のポートレットを参照するURL文字列を作成します。ポータル・フレームワークは、返されたURLを使用してポートレットの制御リンクを提供できます。それぞれのURLは、他のポートレット・モードまたはウィンドウ状態を定義することにより、新しいポートレット状態を参照できます。
      <state
      url="<portlet URL>"
      windowId="<portlet window identifier>"
      action="<whether this is an action URL: true|false>"
      portletMode="<portlet mode>"
      portletWindowState="<window state"
      var="<variable name for this portlet URL>"
      scope="<scope for var: page|request|session|application>">
      <urlParam name="<parameter name>" value="<parameter value>"/>
      </state>

    • insertタグは、ポートレットを呼び出し、ポートレットの状態に応じたポートレットのコンテンツを取得します。このタグを使用すると、レンダリング中にポートレットが動的に指定するポートレット・タイトルを取得できます。
      <insert
      url="<portlet URL>"
      windowId="<portlet window identifier>"
      contentVar="<variable name for this portlet content>"
      contentScope="<scope for contentVar:
      page|request|session|application>">
      titleVar="<variable name for the dynamic portlet title"/>
      titleScope="<scope for titleVar: page|request|session|application>">

      すべてのポートレット・タグには、ポートレットのコンテキストとポートレット名を指定するポートレットURL属性があります。追加属性を使用することにより、ウィンドウ識別子など、より詳細な指定が可能です。

      ポートレット・タグの一部の属性を使用すると、結果を出力ストリームに直接書き込む代わりに、変数に書き込むことができますが、この方法を用いると、コンテンツは一時的に文字列に保存されるので、バッファリングが発生します。バッファリングはパフォーマンスに影響するため、通常、この機能を使用することは推奨されません。

ポータル・フレームワークは、実際のポートレット出力の上に動的なポートレット・タイトルを表示するために、ポートレットのコンテンツ用に変数を指定することがしばしばあります。しかし、開発者は代わりの方法として、次の例に示すように、Javascriptを使用してください。

ポータルJSPの例を通じて、集約タグ・ライブラリーの使い方を説明しましょう。サンプル・コードをまだダウンロードされていない方は、ダウンロードして参照することにより、理解が深まります。

この例では、2つのポートレットをウィンドウ・フレーム内にレンダリングします。ウィンドウ・フレームには、各ポートレットのポートレット・モードを変更する制御リンクを表示します。

まず、JSPヘッダーで、集約タグ・ライブラリーを参照し、ネーム・スペース用のプレフィックスを定義します。

<%@ taglib uri="http://ibm.com/portlet/aggregation" prefix="portlet" %>

この宣言によって、タグ・ライブラリーがJSPに認識され、すべての集約タグが使えるようになります。

次に、initタグを使用して、集約フレームワークのポータル・コンテキストを定義します。portletURLPrefix属性で、ポータルJSPへのアクセスに使用するURLを宣言します。

<portlet:init portletURLPrefix="/sample/portal/">

通常、ポータル・フレームワークは、ポータルJSPも含めて1つのサーブレットで構成されますが、この例ではJSPだけを使用します。したがってこの例では、ポータルJSPを参照する有効なポータルURLを得るために、web.xmlでJSPを定義する必要があります。ポータルURLは、.jspなどで終わることはできません。

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
		http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>SamplePortal</display-name>
    …
    <servlet>
        <servlet-name>SamplePortal</servlet-name>
            <jsp-file>portal.jsp</jsp-file>
        </servlet>
    <servlet-mapping>
        <servlet-name>SamplePortal</servlet-name>
        <url-pattern>/portal/*</url-pattern>
    </servlet-mapping>
</web-app>

これで、ポータル・コンテキストを指定するinitタグ内で、いくつかのポートレット・タグを使用できるようになりました。

通常のJSPまたはHTML処理を使用して、ポートレット・リンクおよびポートレット・コンテンツのデザインを整えることができます。

ポートレット・リンクをページに配置するときは常に、集約タグ・ライブラリーのstateタグを使用して、対応するポートレットURLを作成できます。次のJSPスニペットは、世界時計ポートレットの表示モードへのリンクの作成方法を示します。

<a href="<portlet:state url='worldclock/StdWorldClock' windowId='birga'
 portletMode='view'/>">view</a>

windowIdは、このポートレットを固有にする識別子を提供します。これにより、異なるwindowIdを使用して、同じ世界時計ポートレットを1つのページ上に再び配置できます。上記のリンクは、異なるウィンドウ識別子を定義しているポートレットにはまったく影響しません。各ポートレット・ウィンドウは、それぞれ固有のリンクを提供しなければなりません。

<a href="<portlet:state url='worldclock/StdWorldClock' 
   windowId='stephan' portletMode='view'/>">view</a>

ウィンドウ・フレームと各ポートレット用のポートレット制御リンクを使用してページ・レイアウトを設計した後は、ポートレットURLおよびウィンドウ識別子を参照するinsertタグを使用して、ポートレットのコンテンツをページに挿入します。


<portlet:insert url="worldclock/StdWorldClock" windowId="birga" 
   titleVar="portlettitle_1"/> 

ポートレットによって設定される動的なタイトル用に変数を定義することにより、Javascriptを使用してタイトルをウィンドウ・フレームに埋め込むことができます。

完成したportal.jspをリスト1に示します。


リスト1. 集約タグ・ライブラリーを使用するportal.jsp
<%@ taglib uri="http://ibm.com/portlet/aggregation" prefix="portlet" %>
<%@ page isELIgnored ="false"%>
<portlet:init portletURLPrefix="/sample/portal/">
<!-- create portal table of two columns -->
<TABLE BORDER="5" WIDTH="100%">
 <TR BGCOLOR="BBBBFF">
  <TD>
   <!-- insert portlet title bar into left column -->
   <TABLE WIDTH="100%">
     <TR>
        <TD>
          <B><span id="title_1">Portlet 1</span></B>
        </TD>
          <TD ALIGN="right">
            <a href="<portlet:state url='worldclock/StdWorldClock' 
				windowId='birga' portletMode='view'/>">view</a>
            <a href="<portlet:state url='worldclock/StdWorldClock' 
				windowId='birga' portletMode='edit'/>">edit</a>
            <a href="<portlet:state url='worldclock/StdWorldClock' 
				windowId='birga' portletMode='help'/>">help</a>
        </TD>
      </TR>
   </TABLE>
  </TD>
  <TD>
   <!-- insert portlet title bar into right column -->
   <TABLE WIDTH="100%">
     <TR>
        <TD>
          <B><span id="title_2">Portlet 2</span></B>
        </TD>
          <TD ALIGN="right">
            <a href="<portlet:state url='worldclock/StdWorldClock' 
				windowId='stephan' portletMode='view'/>">view</a>
            <a href="<portlet:state url='worldclock/StdWorldClock' 
				windowId='stephan' portletMode='edit'/>">edit</a>
            <a href="<portlet:state url='worldclock/StdWorldClock' 
				windowId='stephan' portletMode='help'/>">help</a>
        </TD>
      </TR>
   </TABLE>
  </TD>
 </TR>
 <TR>
  <TD>
<!-- insert portlet into left column -->
    <portlet:insert url="worldclock/StdWorldClock" 
		windowId="birga" titleVar="portlettitle_1"/>
  </TD>
  <TD>
<!-- insert portlet into right column -->
    <portlet:insert url="worldclock/StdWorldClock" 
		windowId="stephan" titleVar="portlettitle_2"/>
  </TD>
 </TR>
</TABLE>
<!-- insert portlet title -->
<script type="text/javascript">
  document.getElementById("title_1").firstChild.nodeValue = "${portlettitle_1}";
  document.getElementById("title_2").firstChild.nodeValue = "${portlettitle_2}";
</script>
</portlet:init>

この例で作成したポータル・ページ(図1参照)を表示するには:

  • portal.jspをパッケージ化し、Webアプリケーション内にインストールします。
  • 次に、ブラウザーでURL「http://localhost:9080/sample/portal」を開くことにより、ポータル集約にアクセスします。

図1. ポータル集約JSPの出力例

WebSphere Portalとの比較

WebSphere Portalは、独自のテーマとスキンを使用してカスタマイズできる洗練された集約フレームワークを提供します。たとえば、WebSphere Portalでは、集約フレームワーク内で詳細なアクセス制御を適用することができます。

WebSphere Portalには、WebSphere Application Server V6.1ポートレット・コンテナーによって提供される集約タグ・ライブラリーに相当する機能はありません。集約タグ・ライブラリーを使用すると、複数のポートレットを1つのページ上に集約する非常に単純なポータル・フレームワークを作成できます。これは、ポートレット開発システムによって使用されることを目的としています。


上に戻る

ポートレット情報へのアクセス

ポートレット・コンテンツの周囲のウィンドウ・フレームを作成するポータル・フレームワークは、ポートレット・モードまたはウィンドウ状態の変更をサポートする追加アイコンを提供することがあります。正しいアイコンを表示するために、ポータル・フレームワークは、ポートレットがどのモードまたは状態をサポートするのかを知ることが必要です。たとえば、ポートレットの編集モードへのリンクが設定されたアイコンを表示するには、ポートレットが編集モードをサポートするかどうかをポータルが把握しなければなりません。各ポートレット・アプリケーションは、このような情報をポートレット・デプロイメント記述子を介して提供します。この情報は、MBeanからもアクセスできます。

一般に、すべてのMBeanはWebSphere Application ServerのAdminClientからアクセスできるようになっています。AdminClientの取得方法および一般的なMBeanの使用方法については、「WebSphere Application InfoCenter」の「管理クライアント・プログラムの開発」セクション(「リソース」に記載されています)を参照してください。

ポートレット・アプリケーションの起動時に、ポートレット固有の次のMBeanが作成されます。

  • ポートレット・デプロイメント記述子内で定義されたポートレット・アプリケーション用にPortletApplication型のMBeanが1つ

    このMBeanの名前は、ポートレット・アプリケーション・ファイルの名前に「_portletapplication」というサフィックスを連結したものになります。

    例: StdWorldClock.war_portletapplication

  • ポートレット・アプリケーションで定義された各ポートレットごとに、Portlet型のMBeanが1つ

    このMBeanの名前は、上記のPortletApplication MBeanの名前に、ポートレット名をサフィックスとして連結したものになります。

    例: StdWorldClock.war_portletapplication.StdWorldClock

Portlet MBeanおよびPortletApplication MBeanを説明するJavadocについては、「WebSphere Application Server InfoCenter」の「Mbean interfaces」セクション(「リソース」に記載されています)を参照してください。

MBean APIには、いくつかの使い方があります。一部の例を示します。

  • システムで利用できるすべてのポートレット・アプリケーションとポートレットへのアクセスを取得し、ポータルがこれらのリストを作成したり、ナビゲーション機能またはポートレット管理機能を提供できるようにする。
  • ポートレットのタイトルを取得し、ポートレット・コンテンツを含むウィンドウ・フレームで、ポータルがコンテンツの上部にタイトルを表示できるようにする。
  • ポートレットによって定義されたカスタムのウィンドウ状態を取得し、ポータルがこれらの状態をサポートできるようにする。
  • ポートレットによってサポートされているすべてのポートレット・モードを取得し、適切な制御リンクだけをポータルが表示できるようにする。

ポートレットにどの制御アイコンまたはリンクを表示すべきかを判断する必要があるポータル・フレームワークは、特定のコンテンツ・タイプに対し、サポートされているポートレット・モードのリストを取得できます。次のコード・スニペットは、StdWorldClockポートレットとtext/htmlコンテンツ・タイプに対し、これがどのように行われるのかを示したものです

ObjectName on = new 
ObjectName("WebSphere:name=StdWorldClock.war_portletapplication.StdWorldClock,*");
on = (ObjectName) adminService.queryNames(on, null).iterator().next();
HashMap contentTypes = (HashMap) adminService.getAttribute(on, "contentTypes");
List list = (List) contentTypes.get("text/html");

ポートレット・デプロイメント記述子によって提供されるすべての情報に加え、PortletApplication MBeanはNotificationListenerを登録することにより、ポータルがlistenすることができる通知定数を定義します。通知イベントの登録および処理方法については、「WebSphere Application InfoCenter」の「管理クライアント・プログラムの開発」セクション(「リソース」に記載されています)を参照してください。

この例では、ポートレット固有のMBeanを使用できるいくつかのシナリオを示します。このMBeanは、デプロイされているすべてのポートレットに関する情報を取得し、そのリストをポータル集約の一番上に表示します。ユーザーは、集約内に表示するポートレットをこのリストから選択できます。

システム内のすべてのMBeanへの汎用アクセスを得るために、AdminClientを取得します。

Properties p = new Properties();
p.put("port", "8880");
p.put("host", "localhost");
p.put("type", "SOAP");
AdminClient adminService = AdminClientFactory.createAdminClient(p);

すべてのポートレット・アプリケーションは、PortletApplication型の登録済みのMBeanを持ちます。このため、MBeanの型を指定するObjectNameパターンを作成します。これは、システム内で利用できるすべてのPortletApplication MBeanのリストを返します。


ObjectName paons = new ObjectName("WebSphere:type=PortletApplication,*");
Iterator iter = adminService.queryNames(paons, null) .iterator();
while (iter.hasNext()) {
    ObjectName paon = (ObjectName) iter.next();
    …
}

各ポートレット・アプリケーションは、MBeanのportletMBeanNames属性を使用して、そのポートレットのリストへのアクセスを提供します。MBeanへのアクセスを取得するには、Portlet MBean名を指定するObjectNameパターンを作成します。これは、その名前を持つ利用可能なすべてのMBeanのリストを返します。(リストが返されますが、このリストには複数のエントリーは含まれていません。)

Iterator innerIter =  ((List) adminService.getAttribute(paon, 
  "portletMBeanNames")).iterator();
while (innerIter.hasNext()) {
    String name = (String)innerIter.next();
    ObjectName pons = new ObjectName("WebSphere:name=" + name + ",*");
    ObjectName pon = (ObjectName) adminService.queryNames(pons, null).iterator().next();
    …
}

これでシステム内のすべてのポートレット・アプリケーションとポートレットへのアクセスを取得できたので、ポートレット選択用のドロップダウン・リストを提供するために必要な情報を検索できます。このリストには、利用可能な各ポートレットのポートレットURLが含まれます。

ポータルが集約タグ・ライブラリーを使用してポートレットを表示するときは、対応するポートレットURLを知る必要があります。このURLは、Webアプリケーション・コンテキストとポートレット名で構成されます。たとえば、worldclock/StdWorldClockとなります。

Webアプリケーション・コンテキストは1つのアプリケーション内のすべてのポートレットに共通であるため、PortletApplication MBeanの1つの属性として取得できます。

String context = (String) adminService.getAttribute(paon, "webApplicationContextRoot");

ポートレット名を得るために、Portlet MBeanのname属性にアクセスします。

String portletName = (String) adminService.getAttribute(on, "name");

最後に、ポータル集約を調整して、ユーザーがポートレットを選択できるよう、すべてのポートレットURLを含むリストを提供します。portal.jspはこの選択内容を使用して、ポートレットを集約内に呼び出します。

Mbeanを使用して集めたすべてのポートレットURLをBeanに格納するコードをリスト2に示します。


リスト2. リストへのポートレットURLの格納
PortletListBean bean = new PortletListBean();
// add all available portlet URLs to PortletListBean
try {
    Iterator iter = adminService.queryNames(paons, null).iterator();
    while (iter.hasNext()) {
      ObjectName paon = (ObjectName) iter.next();
      String context = (String)
              adminService.getAttribute(paon,
              "webApplicationContextRoot");
      Iterator innerIter = ((List)
              adminService.getAttribute(paon,
              "portletMBeanNames")).iterator();
        while (innerIter.hasNext()) {
          String name = (String)innerIter.next();
          ObjectName on = new ObjectName("WebSphere:name=" + name + ",*");
          on = (ObjectName) adminService.queryNames(on, null).iterator().next();
          String portletName = (String) adminService.getAttribute(on, "name");
          bean.addURL(context + "/" + portletName);
        }
    }
} catch (Exception e) {
   …
}

このBeanに基づき、利用可能なすべてのポートレットの選択リストを作成します。portal.jspの更新後、次のURLでポータル集約をインストールし、アクセスできます。 http://localhost:9080/sample/portal


図2. 利用可能なすべてのポートレットの選択リストがあるポータル集約

WebSphere Portalとの比較

ポートレット情報にアクセスするMBean APIは、WebSphere Application Server独自のものです。WebSphere Portalには、これに対応し、パブリックに利用できるポートレット・モデルへのアクセスはありません。

システムで利用できるポートレットに関する情報を取得する要求は、主にポータル・フレームワークによって実行されます。WebSphere Portalには、インストール済みのポートレットに関するすべての情報を保存およびアクセスする独自のポートレット・デプロイメントおよびオブジェクト・モデルが用意されています。このため、WebSphere Portalは、この目的でパブリックAPIを提供する必要がありません。


上に戻る

ポートレットのフィルタリングによる出力の変更

URLによってポートレットに直接アクセスするときは、フィルター・チェーンに埋め込まれたPortletDocumentFilterというフィルターによって、ポートレットの出力を変更できます。あらかじめ定義されたデフォルトのフィルターは、ポートレットのポートレット・フラグメント出力を有効な文書に変換します。この方法で、サーブレットのように、完全な文書としてポートレットをブラウザー内に表示できます。

デフォルトで提供されるDefaultFilterは、ポートレットのコンテンツを単純で有効なHTML文書に変換します。カスタマイズしたPortletDocumentFilterを使用することにより、この動作を置換または拡張できます。

PortletDocumentFiltersは、javax.servlet.Filterをインプリメントし、サーブレット・フィルター・チェーンのメカニズムに従う標準サーブレット・フィルターです。違いは、このフィルターを宣言およびデプロイする方法にあります。

web.xml内で直接フィルターを指定する代わりに、拡張ポイントによってPortletDocumentFilterをplugin.xmlに登録します。plugin.xmlは、PortletDocumentFilterを含むJARファイルのルート・ディレクトリにあります。

<extension point=
  "com.ibm.ws.portletcontainer.portlet-document-filter-config">
  <portlet-document-filter 
     class-name="sample.WindowFrameFilter" order="1200" />
</extension>

PortletDocumentFilterは、次の2つの方法でデプロイできます。

  1. フィルターのJARファイルをApplication Serverのlibディレクトリーに追加します。JARファイルの構造は、次のとおりです。
    • plugin.xmlがルート・ディレクトリーにある
    • フィルター・クラス・ファイルがJARファイル内の適切なパッケージ・ディレクトリーにある
  2. フィルターをosgiバンドルとしてApplication Serverのpluginsディレクトリー内に追加します。JARファイルの構造は、次のとおりです。
    • plugin.xmlがルート・ディレクトリーにある
    • フィルター・クラス・ファイルがJARファイル内の適切なパッケージ・ディレクトリーにある
    • バンドルの詳細を指定するMANIFEST.MFファイルがMETA-INFディレクトリーにある

標準サーブレット・フィルターの概念には、PortletDocumentFilterを作成したい開発者に対するポートレットのサポートはありません。このため、ポートレット特有のニーズを実装するために、次の2つのヘルパーがPortletDocumentFilter用に提供されています。

  • com.ibm.wsspi.portletcontainer.util.FilterRequestHelper
  • com.ibm.wsspi.portletcontainer.util.PortletURLHelper

FilterRequestHelperは、フィルターのフローを制御する簡単なアクセスを提供します。背後では、要求の属性がフロー情報を転送します。たとえば、isDocumentメソッドは、前のフィルターがフラグメントをすでに文書に変換したかどうかを検証します。これにともない、各フィルターは、setRedirectおよびsetDocumentmethodsを使用して特殊な要求を指定できます。

重要: システムはこれらのプロパティーを使用しません。各フィルターは、すでに変換されている文書を再び変換しないように、マークアップを変換する前にこれらのプロパティーをチェックする必要があります。

PortletURLHelperは、URLアドレス可能度パターンに応じてポートレット情報を識別するために、サーブレット要求URLを分析します。ヘルパーのこの方法により、フィルターは、ポートレット・アクションURLが要求されているかどうか、またはどのポートレット・モードが呼び出されているかを簡単に判断できます。

WMLなどの追加のマークアップをサポートするには、新しいPortletDocumentFilterを作成して登録し、デフォルトのHTMLフィルターよりも前にこれを呼び出します。新しいフィルターは、setDocumentメソッドをFilterRequestHelperに呼び出すことにより、文書の変換にマークを設定する必要があります。このマーカーにより、DefaultFilterがフラグメントをHTML文書に変換するのを防止できます。このような方法で、PortletDocumentFiltersを使用してマークアップのサポートを追加したり、文書の出力を変更できます。

通常、ポータルはポートレットのコンテンツをウィンドウ・フレーム内にレンダリングし、別のポートレット・モードまたはウィンドウ状態へのリンクを提供します。URLアドレス可能度を使用するときは、ポートレットのコンテンツを囲むウィンドウ・フレームは表示されません。この例では、カスタムのPortletDocumentFilterを使用して、シンプルなウィンドウ・フレームを追加する方法を説明します。

  1. まず、javax.servlet.Filterをインプリメントする新しいフィルター・クラスを作成し、これにWindowFrameFilterという名前を付けます。メイン・メソッドはdoFilterメソッドです。
    public class WindowFrameFilter implements Filter 
    {
    public void init(FilterConfig config) throws ServletException {}
    public void doFilter(ServletRequest request, 
    ServletResponse response, 
    FilterChain chain)
    throws IOException, ServletException {
    …
    }
    public void destroy() {}
    }

  2. doFilterで、URLを分析し、ウィンドウ・フレームを追加するために要求が対応する前提条件を満たしているかどうかを判断します。
    • 要求に、文書変換の完了を示すマークが設定されているかどうかを調べます。ポートレットのコンテンツを囲むウィンドウ・フレームを追加するには、有効な文書が必要です。このため、有効でない文書の場合は、要求は無視しなければなりません。
      // do nothing if document cannot be found 
      if (!FilterRequestHelper.isDocument(request))
      {
        chain.doFilter(request, response);
        return;
      }

    • システムで使用されている文書フィルターによっては、要求文書がHTML文書であるかどうかのチェックが必要です。
    • この要求を無視する必要があるかどうかを決めるために、要求URLがアクションURLであるかチェックします。このチェックには、PortletURLHelperを使用します。InvalidURLExceptionが発生する場合は、以下に示すように、フィルターはこの情報をHttpServletResponseに転送する必要があります。
      // analyze request url
      HttpServletRequest servletRequest = (HttpServletRequest) request;
      HttpServletResponse servletResponse = (HttpServletResponse) response;
      String portleturl = null;
      try {
        PortletURLHelper urlHelper = new PortletURLHelper("","",servletRequest.getPathInfo());
        // do nothing if action called
        if (urlHelper.isAction()) 
        {
           chain.doFilter(request, response);
           return;
        }
        portleturl = createPortletURL(servletRequest, urlHelper);
      }
      catch (InvalidURLException e) 
      {   
        servletResponse.sendError(
          e.getStatusCode(),
          e.getMessage());
        return; 
      }

  3. 要求がこれらの前提条件を満たす場合は、ポートレットのコンテンツをウィンドウ・フレーム内に埋め込むことができます。ポートレットのコンテンツの上にリンクの行を追加するために、単純なHTML表を作成します。
    PrintWriter writer = response.getWriter();
    writer.println("<TABLE BORDER='5'>");
    writer.println("<TR BGCOLOR='BBBBFF'><TD>");
    writer.println("<TABLE WIDTH='100%'>");
    writer.println("<TR><TD>");
    writer.println("<B><span id='portlet_title_1'>Portlet</span></B>");
    writer.println("</TD>");
    writer.println("<TD ALIGN='right'>");
    writer.println("<a href='" + portleturl + "/state=normal'>normal</a>");
    writer.println("<a href='" + portleturl + "/state=maximized'>maximized</a>");
    writer.println("<a href='" + portleturl + "/state=minimized'>minimized</a>");
    writer.println("</TD></TR>");
    writer.println("</TABLE>");   
    writer.println("</TD></TR><TR><TD>");
    chain.doFilter(request, response);
    writer.println("</TD></TR></TABLE>");

  4. これらのリンクは、ポートレットの異なるウィンドウ状態を参照します。ポートレットのURLリンクを作成するために、ポートレットを参照するベースURL Stringを使用して、URLアドレス可能度のパターンに沿ってすべての必要な情報を含めます。欠けているのは、各ウィンドウ状態の情報だけです。
    StringBuffer buffer = new StringBuffer();
    buffer.append(servletRequest.getScheme());
    buffer.append("://");
    buffer.append(servletRequest.getServerName());
    buffer.append(":");
    buffer.append(servletRequest.getServerPort());
    buffer.append(servletRequest.getContextPath());
    buffer.append(servletRequest.getServletPath());
    buffer.append("/");
    buffer.append(urlHelper.getPortletWindowId());
    buffer.append("/ver=");
    buffer.append(urlHelper.getVersion());
    String portleturl = buffer.toString();

  5. ポートレットのコンテンツを囲むウィンドウ・フレームを表示する前に、このWindowFrameFilter用のplugin.xmlを使用してJARファイルを作成します。このxmlは、フィルターの場所と順番を定義します。この例では、DefaultFilterの後に呼び出すために、フィルターの順番は1000よりも大きな値にしてください。ウィンドウ・フレームは、HTML文書への変換後でないと作成できません。
    <?xml version="1.0" encoding="UTF-8"?>
    <?eclipse version="3.0"?>
    <plugin id="portletwindowfilter" name="WS_Server" provider-name="IBM" version="1.0.0">
      <extension point="com.ibm.ws.portletcontainer.portlet-document-filter-config">
        <portlet-document-filter class-name="sample.WindowFrameFilter" order="1200" />
      </extension>
    </plugin>

  6. フィルターをデプロイするために、フィルターのJARファイルをApplication Serverのlibディレクトリーに配置し、サーバーを再起動します。
  7. このフィルターが適用された世界時計ポートレットにアクセスするには、ブラウザーでURL 「http://localhost:9080/worldclock/StdWorldClock」を開きます。

    図3に示す結果が得られます。


    図3. ポートレット・ウィンドウ・フレームを表示するためにフィルターが設定されたポートレット


WebSphere Portalとの比較

ポートレットのフラグメントは、WebSphere Application ServerのPortletDocumentFiltersによって変更できます。WebSphere Portalでこれに対応する機能はPortletFilterの概念です。

WebSphere Portalは、そのPortletFilterメカニズムに対し、独自のフィルター・メカニズムを提供します。PortletDocumentFilterは、サーブレット・フィルターに基づいています。PortletFilterは専用のフィルター・チェーンに埋め込まれ、PortletFilterインターフェースをインプリメントします。これにより、ポートレット特有のニーズに簡単にアクセスできます。これらのフィルターは、PortletDocumentFiltersと比較して、より高い柔軟性を持ちます。これらのフィルターにはサーバーの再起動が必要ないため、ポートレットごとに動的に有効にすることができます。


上に戻る

まとめ

この連載の第2部では、WebSphere Application Serverのポートレット・コンテナーについて詳しく見てきました。まず、シンプルなポータル・フレームワークの作成を補助する集約機能について説明しました。次に、URLでアドレス指定された際のポートレット出力の変更方法、およびポートレット情報の検索とアクセスの方法について説明しました。さらに、これらの機能をWebSphere Portalと比較し、ポートレットのアドレス指定での違いを明らかにしました。

次の第3部では、Application ServerでのJSR 168ポートレット・コンテナーのより高度な機能について解説します。wsadminおよび管理コンソールを使用してポートレットコンテナーとポートレットを管理する方法や、ポートレットのパフォーマンス測定に関する情報の取得方法を取り上げます。

上に戻る

ダウンロード

説明 ファイル名 サイズ ダウンロード方法
サンプル・コード Portlet-container-p2-ex.zip 30 KB HTTP(US)
World clock ポートレット StdWorldClock.war 75 KB HTTP(US)
ダウンロード方法について(US) Adobe® Reader®が必要

上に戻る

リソース


上に戻る

筆者について(原文のまま)

Stephan Hesmer is currently working as Performance Chief Developer. In his previous role he worked as Portlet Runtime architect in WebSphere Portal and WebSphere Application Server. He is responsible for integrating the JSR 168 portlet container into WebSphere Application Server. Stephan worked on the JSR 168 Java™ Portlet Specification, and designed and implemented the initial version of the JSR 168 Reference Implementation, Pluto. Stephan received a Diploma of Information Technology from the University of Cooperative Education Stuttgart, Germany, in 2000. After graduating, he joined the IBM Boblingen Development Laboratory to work in the WebSphere Portal Team.


Birga Rick is Technical Lead for WebSphere Application Server Portlet Runtime at the IBM Boeblingen Lab in Germany. In 2003, she was part of the team implementing the JSR168 Reference Implementation, Pluto. Following her work on JSR 168 within the WebSphere Portal development team, she integrated the Portlet Runtime into WebSphere Portal and WebSphere Application Server.



上に戻る


上に戻る