レベル: 中級 David Lection, Senior Programmer, FIT Team, IBM China Development Lab Varadarajan Ramamoorthy (varad@us.ibm.com), Programmer, FIT Team, IBM China Development Lab
2002年 8月 01日 このシリーズの
第1回では、WebSphere Portal V4.1ポートレットの構造とプログラミングについて紹介されています。
編集者注: この記事は、2002年3月に発表されたDavid Lection氏とVarad Ramamoorthy氏の記事の最新版です。該当記事は、
WebSphere Portalバージョン1.2および2.1 に関するものでした。改訂された本稿では、最新の後継製品であるWebSphere Portalバージョン4.1について説明し、バージョン4.1上でテスト済みの更新版ポートレット・ソース・コードも収録されています。
概要
Webサイトの開発者たちは、あらゆる類のユーザー指向コンテンツをシームレスかつ十分な設計のインターフェースに統合するという、ますます複雑化する作業に直面しています。ポータル・サーバーは、(ユーザーに強力な統合コンテンツを提供する)優れた環境を構築するためのフレームワークを提供します。
ポートレットは、高品質なポータルのビルディング・ブロックです。ダイナミックで反応性のよいポートレットは、ユーザーがポータル・ページを見るたびに新鮮な体験を与えてくれます。
WebSphere Portal V4.1は、IBMの旗艦ポータル・サーバー・ソフトウェアの最新リリースです。バージョン4.1は、次のような多くの新しい機能をサポートしています。
- J2EEに準拠
- Webサービス・ベースのポートレットのサポート
- 強力で新しいページ・カスタマイザー
- ページ・グループ
- ポータルの新規のルック・アンド・フィール (さらに多くの選択可能なテーマやスキンなど)
- ポートレットAPI機能拡張
ポータル・サーバーは、ポータル・プログラマーが強力なコンテンツをユーザーに提供できるように手助けをします。WebSphere Portalには、ポートレット・アプリケーション内のポートレットが、そのアプリケーション内の他のポートレットにメッセージを送信することによって通信できるようにする組み込みサポートが提供されています。
ポートレットは、メッセージに反応して、そのメッセージの更新を行います。そのため、ポータルはより生き生きとして、応答性のよいものになります。たとえば、ユーザーはあるポートレットでIBMの株価が下落したことを見ながら (これは単なる例であることをお忘れなく)、別のポートレットから「IBM株は買い」という情報を受け取るという具合です。具体的には、あるポートレットがデータを表示し、別のポートレットがアクションをユーザーに提案するわけです。このようなポートレットの運用は、より一層パーソナルな体験をユーザーに提供しますが、これを実現するのがポートレット・メッセージングです。
ポートレット・メッセージングの基本
協力関係にあるポートレットの集合にメッセージング機能を追加するのは単純な作業です。一般に、片方のポートレットがメッセージ送信側になり、もう一方がメッセージ受信側になります。送信側がある状態を検出すると、メッセージを構成して、それを受信側に送信します。すると、受信側のポートレットがメッセージ・イベント・ハンドラーからメッセージを受け取って、それを処理します。単一のポートレットで、メッセージの送受信を両方とも行うことができます。
ポートレット・メッセージングには、いくつかの基本的なルールがあります。まず、ポートレットは同一のポートレット・アプリケーションに属している必要があります。ポートレット・アプリケーションとは、同一のポートレット・アーカイブ、すなわちPARファイルにパッケージされている1つ以上のポートレットのことです。ポートレット間で送信されるメッセージ・オブジェクトは、一般にカスタムのアプリケーション固有のJavaオブジェクトです。WebSphere Portalでは、それぞれのポートレット・アプリケーション固有のクラス・ローダーを使用して、アプリケーション間における保護とセキュリティーを提供しています。メッセージング・ポートレットはJavaメッセージ・オブジェクトを共用しているので、それらは同一のクラス・ローダーによってロードされ、同一のポートレット・アプリケーション内に常駐している必要があります。
2番目のルールは、主としてパフォーマンス上の理由から、ポートレットは同一のポータル・ページに表示されている必要があることです。どの時点でも一度に見られるポータル・ページは1つだけなので、同一ページにないポートレットにメッセージを送信する必要はほとんどありません。
ポータル・イベントとメッセージ処理
あるポートレットがポータル・サーバーにイベントをサブミットすると、ポータルの集約処理が開始されます。基礎となるポータル・イベントとメッセージ処理を理解することが重要です。これらを理解すれば、適切なタイミングでメッセージを送信し、受信側ポートレットも適切なタイミングでメッセージを受信できるように、各ポートレットをインプリメントできます。
イベント処理と集約処理には、以下の4つのステップがあります。
- すべてのアクション・イベントの処理
クライアントからイベントを受信すると、ポータルはクライアントから送信されたアクションURIをデコードし、適切なポートレットにアクション・イベントを伝搬します。一般に、これは単一ポートレットに対する単一イベントです。アクション・イベントを処理するためにポートレットのアクション・リスナーが呼び出されたときが、ポートレット・メッセージの送信に適したタイミングです。
- すべてのメッセージ・イベントの処理
(一群の)ポートレットは複数のメッセージを送信できるので、この処理はすべてのメッセージ・イベントの処理が終了するまでループします。メッセージがポートレットに送信されると、ポートレットのメッセージ・リスナーが呼び出されます。ポートレットがメッセージを受信した結果としてメッセージを送信すると、2番目のメッセージも送信され、2番目ターゲット・ポートレットによって処理されます。保留メッセージ・イベントがなくなるまで、この処理が続けられます。
- すべてのウィンドウ・イベントの処理
ポートレットは、ユーザー側で最小化、最大化、あるいは通常のサイズに戻すことができます。また、ポートレットが特定のサイズを要求することもできます。サイズ変更の操作の結果、サイズが変更されるポートレットに一連のウィンドウ・イベントが送信される可能性があります。この処理は、すべてのウィンドウ・イベントが処理されるまで続けられます。
- ポートレット・レンダリング処理
すべてのイベントが上記の順序で処理されると、ポータル・アグリゲーターが各ポートレットの表示ページ上への呼び出しを開始し、それらのポートレットのコンテンツ情報をページ集約に戻させます。この集約処理が完了すると、完成したページがブラウザーに戻されます。
上記のイベントおよび集約処理のステップ4では、イベントの処理は行われません。ステップ4の間にポートレット内の表示メソッドからメッセージが送信されても、そのメッセージは送信および処理されません。したがって、コラボレーションの結果をポータル表示に反映させたい場合、ポートレットはイベントおよび集約処理のステップ1か2の間にメッセージを送信する必要があります。
サンプル・ポートレット
サンプル・ポートレットMessageSender および
MessageReceiver は、ポートレット間でのメッセージングのインプリメント方法を示しています。下の図1 は、ポートレットを示したサンプル画面です。
図1. メッセージング・ポートレット
最初に、左側のマップから都市を選択します。ポップアップ・メニューによって、店舗の場所または従業員数を選択するように促されます。これを選択すると、マップ (MessageSender) ポートレットによってメッセージが生成され、宛先の受信側 (MessageReceiver) ポートレット・インスタンスに送信されます。受信側ポートレットは、選択された都市のデータを表示します。
図1 の右側の2つのポートレットは、同一の
MessageReceiver ポートレットのインスタンスです。上のインスタンスはその都市の店舗の場所を示し、下のインスタンスは選択された店舗の従業員数を示しています。
次に、このサンプル・ポートレットについて1つ1つ説明していきましょう。
メッセージ送信ポートレット
このMessageSender ポートレットの構造は、標準のモデル・ビュー・コントローラー (MVC) デザイン・パターンに準拠しています。ポートレットのコンテンツの表示には、JavaServer Page(JSP) テクノロジーが使用されています。
MessageSenderPortletのサンプル・コード
public class MessageSenderPortlet extends AbstractPortlet
{
protected final static String viewJSP
= "/PORTLET-INF/MessageSender/html/MessageSenderView.jsp";
public final static String DEFAULT_ACTION = "SendMessage";
public final static String CITYNAME = "cityName";
public final static String MESSAGE_ID = "MessageSender";
public final static String PORTLETNAME = "portletname";
public void doView ( PortletRequest request, PortletResponse response )
throws PortletException, IOException
{
// Format the default action event URI
PortletURI baseURI = response.createReturnURI();
DefaultPortletAction action = new DefaultPortletAction(DEFAULT_ACTION);
baseURI.addAction(action);
request.setAttribute("BaseURI", baseURI.toString());
// Call the JSP to display the portlet output
getPortletConfig().getContext().include(viewJSP, request, response);
}
}
|
このポートレットは小さく単純なものです。ポートレットURIが1つ構成されています。このURIは、サブミット・アクションをポートレットのアクション・リスナーに戻すアクション・イベントを定義するものです。URIが構成されると、ポートレットのコンテンツは、レンダリングをMessageSenderView JSPページに代行させることによって表示されます。これは、上記のポートレット・コンテキストのincludeメソッドへの呼び出しの中で実行されます。ポートレットは、ノースカロライナ州の地図と、そのマップのガイドとなるいくつかの説明文を表示します。
ユーザーがある都市をクリックすると、MessageSenderView JSPページ内のJavaScriptの断片がポップアップ・コンテキスト・メニューを表示するので、そこから店舗の場所または従業員数を選択します。次に、このJavaScriptは都市名と要求されたデータ項目を両方とも保存し、それらをアクション・イベントとしてポータル・サーバーにサブミットします。
このイベントは、同じクラス内のactionPeformed メソッドに提示されます。この点は、元のバージョンのコードから少々変更されています。以前のバージョンのポータルでは、イベント処理メソッドは別のクラスに置かれていました。WebSphere Portal V4.1では、イベント・ハンドラーは基本ポートレット・クラスに直接追加されています。
MessageSenderActionListenerのactionPerformedメソッド
public void actionPerformed(ActionEvent event)
{
DefaultPortletAction action = (DefaultPortletAction)event.getAction();
if ( action != null )
{
AbstractPortlet portlet = (AbstractPortlet)event.getPortlet();
PortletRequest request = event.getRequest();
if(action.getName().equalsIgnoreCase
(MessageSenderPortlet.DEFAULT_ACTION))
{
String portletName = (String) request.getParameter(MessageSenderPortlet.PORTLETNAME);
try
{
String cityName
= (String) request.getParameter(MessageSenderPortlet.CITYNAME);
// Create a portlet message and add message parameters.
DefaultPortletMessage dpm = new DefaultPortletMessage(MessageSenderPortlet.MESSAGE_ID);
dpm.addParameter(MessageSenderPortlet.CITYNAME, cityName);
// Here you can specify the name of the portlet that you want to
// send the message to or you can specify "null", so // that the message
// will be sent to all the portlets on that page.
portlet.getPortletConfig().getContext().send
(portletName, dpm, request);
}
catch( AccessDeniedException ade )
{
PortletLog pLog = portlet.getPortletLog();
pLog.error
( "MessageSenderActionListener: error sending message to: "
+ portletName );
}
}
}
}
|
上記のコードのtryブロック内では、ポートレット・メッセージが
DefaultPortletMessage クラスのインスタンスとして構成され、ターゲット・ポートレットに送信されています。ターゲット・ポートレット名と都市名はどちらも、ポートレット要求の属性から抽出されます。都市名はaddParameter メソッドを使用して、パラメーターとしてポートレット・メッセージに追加され、ポートレット名はそのメッセージのターゲットとなるポートレットを判断するために送信メソッドで使用されます。メッセージの作成中または送信中にエラーが発生すると、catchブロックが呼び出され、ポートレット・メッセージ・ログにエラー・メッセージが書き込まれます。
メッセージ受信ポートレット
このMessageReceiver ポートレットの構造も、MVCデザイン・パターンに準拠しています。ポートレットは店舗の場所か従業員数のどちらかを表示できるので、そのポートレット表示用の特定のJSPページを選択する必要があります。このためには、portlet.xmlファイルの構成パラメーターで、そのJSPページを選択します。以下は、portlet.xmlファイルから抜き出したXMLフラグメントで、店舗の場所用のJSPページを指定するところを示しています。
<config-param>
<param-name>viewJSP</param-name>
<param-value>/PORTLET-INF/MessageReceiver/html/AcmePartsLocationView.jsp
</param-value>
</config-param>
|
Webアプリケーション・ディスクリプターのXML文書 (web.xml) におけるポートレットの宣言を示すために、MessageReceiverPortlet クラスのサーブレット定義をこのXMLの断片に含めています。このバージョンのポータルにおけるポートレット・アプリケーションには、ポートレット・アプリケーション・ディスクリプターのXMLファイル(portlet.xml) とWebアプリケーション・ディスクリプターが両方とも必要です。どちらのディスクリプター文書のサンプルも、この記事に収録されているソース・コード・アーカイブに含まれています (参考文献 を参照)。
MessageReceiver ポートレットには以下の2つのメソッドが含まれています。
- init メソッド - ポートレット・レンダリングに使用するJSPページを決定します。
- doView メソッド - ポートレット・コンテンツのレンダリングを担当します。選択された都市名の値は、以後のJSPページによる使用のためにポートレット要求オブジェクトに置かれます。
ポートレット・レンダリング処理を完了させるために、ポートレット・コンテキストのincludeメソッドが呼び出されます。
MessageReceiverPortletのサンプル・コード
public class MessageReceiverPortlet extends AbstractPortlet
{
protected String viewJSP = null;
public final static String VIEW_JSP_ATTRIBUTE = "viewJSP";
public void init(PortletConfig pConfig) throws UnavailableException
{
super.init( pConfig );
viewJSP = pConfig.getAttribute( VIEW_JSP_ATTRIBUTE );
if ( viewJSP == null || viewJSP.trim().equals("") )
{
throw new UnavailableException("MessageReceiver: Parm viewJSP not defined");
}
}
public void doView( PortletRequest request, PortletResponse response )
throws PortletException, IOException
{
PortletData portletPersistence = request.getData();
String cityName = (String) portletPersistence.getAttribute(MessageSenderPortlet.CITYNAME);
if ( cityName == null )
{
cityName = "";
}
// Store the fieldname value in the portlet request for the JSP
request.setAttribute(MessageSenderPortlet.CITYNAME, cityName);
// Call the JSP to display the portlet output
getPortletConfig().getContext().include( viewJSP, request, response );
}
}
|
2つのポートレット、ポートレット・アプリケーション・ディスクリプターportlet.xml、および関連したJSPページは、ポータル・サーバーへのインストール用にPARファイルにパッケージされています。
ポートレット・アプリケーションのビルド
ポートレットに変更や拡張を施した場合は、クラスを再コンパイルしてから、ポートレット・アプリケーションをWARファイルにパッケージする必要があります。ビルド処理は自動化されており、ソース・アーカイブには各ポートレットを別々にコンパイルするためのコマンド・ファイルが含まれています。以下のコマンド・ファイルは、両方のポートレットをコンパイルするものです。
echo off
cls
set bd=C:/MessagingPortlets
javac -d %bd%/WEB-INF/classes %bd%/WEB-INF/classes/com/ibm/wp/samples/messagingPortlets/Mes*.java
jar cvf0 MessagingPortlets.war images
jar uvf0 MessagingPortlets.war jsp
jar uvf0 MessagingPortlets.war WEB-INF
|
このsetステートメントは、ポートレット・アプリケーションのソース・コードのコピー先となる適切なディレクトリーを指定するように変更する必要があります。ポートレットのビルドを行う前に、Javaクラス・パスが、必要なポータルJARファイルを含むようにセットされていることを確認してください。
- portlet-api.jar
- wpsportlets.jar
- j2ee.jar
- wps.jar
- jlog-2.2.jar
WebSphere Portal Version 4.1は、Portal Toolkitも含んでいます。これは、WebSphere Studio Application Developerにプラグインされる強力な拡張で、ポートレットのビルドとデバッグ用にApplication Developerを拡張します。Application Developerにポートレット・アプリケーション・プロジェクトを作成して、ビルドとパッケージングのためにこれらのポートレットをそのプロジェクトにインポートすることができます。Application DeveloperにはJSPエディターの機能もあります。またPortal Toolkitには、ポートレット・アプリケーションに対するリモート・ポートレット・デバッグ機能が用意されています。
ポートレット・アプリケーションのビルドとテストが正常に完了したら、インストールのためにそのWARファイルをポータル・サーバーにコピーします。
メッセージング・ポートレット・アプリケーションのインストール
メッセージング・ポートレット・アプリケーションのインストールを開始するには、自分のポータル・ホーム・ページに移動して、管理者としてログインします。「管理 (Administration)」タブをクリックして「ポートレットの管理(Portlet Administration)」ページを表示します。「ポートレット・アプリケーションのインストール (Install Portlet Application)」ページを使用して、MessagePortlets.warファイルをインストールします。「インストール (Install)」をクリックして、ポートレット・アプリケーションをインポートします。一連の画面や確認が表示されます。
ポートレット・アプリケーションをインストールした後、ポータル・ページ・カスタマイザーを使用して、個々のポートレットをポータル・ページに追加する必要があります。ポートレットが機能するためには、それらを同一のポータル・ページにインストールする必要があります。
ポートレット間の相互作用を簡単に監視するには、ポータル・ページ上のマップ・ポートレット・インスタンスのすぐ右側または左側に2つの受信側ポートレット・インスタンスを置きます。都市の選択に応じて受信側ポートレット・インスタンスが変化した際、選択された都市は、ポートレットによって保持されるため、次回そのポートレットが表示されるときにも選択された状態になります。
この記事のサンプル・ポートレットは、Internet Explorerバージョン5.50と6.00、およびNetscape Navigatorバージョン4.72上で動作確認済みです。他のHTMLブラウザー上でこのポートレットのテストを行って、互換性がないことが判明した場合は、エラー症状の説明を添えてEメールで著者にご連絡ください。
結論
ここまでの内容は、メッセージングを使用してポートレットをコラボレーションさせることによってできることを、ごく一部説明したにすぎません。メッセージングの概念は簡単で単純なものですが、メッセージングを通じてポートレットがやり取りすることによって、強力で魅力的な結果が得られます。さあ、イマジネーションを駆り立てて、プログラミング・スキルを存分に発揮しましょう。
参考文献
ダウンロード | ファイル名 | サイズ | ダウンロード形式 |
|---|
| i-portal2v4.zip | | HTTP |
著者について  | 
|  | David B. Lection氏は、WebSphere Portalとその関連製品のシニア・プログラマー兼主任ツール設計者です。 |
 | 
|  | Varadarajan Ramamoorthy氏は、WebSphere Portalとその関連サービス・オファリングに携わる契約プログラマーです。 |
記事の評価
|