...

WebSphere Portal V6.0 標準ポートレット(JSR168)開発 ハンズオン資料

by user

on
Category: Documents
17

views

Report

Comments

Transcript

WebSphere Portal V6.0 標準ポートレット(JSR168)開発 ハンズオン資料
IBM Japan Systems Engineering
WebSphere Portal V6.0
標準ポートレット(JSR168)開発
ハンズオン資料
日本アイ・ビー・エム システムズ・エンジニアリング株式会社
1
IBM Japan Systems Engineering
1
2
3
4
5
ポートレット開発の流れ ............................................................................................... 5
1.1
ポートレット開発環境と開発のステップ ............................................................... 5
1.2
Portlet API............................................................................................................. 5
1.3
ポートレット開発環境............................................................................................ 5
1.4
ポートレット開発のステップ................................................................................. 6
1.5
演習環境 ................................................................................................................. 6
[演習1]ウィザードに従ってポートレットを自動作成 ............................................. 8
2.1
ポートレットプロジェクトおよびポートレットクラスの作成............................... 8
2.2
テスト環境による実行(サーバーにプロジェクトを追加) ................................ 12
2.3
サーバーの停止 .................................................................................................... 18
2.4
サーバーからポートレットプロジェクトを削除 .................................................. 19
[演習2]コアオブジェクトの使い方........................................................................ 21
3.1
プロジェクト情報................................................................................................. 21
3.2
JSP の呼び出し方 ................................................................................................ 21
3.3
コアオブジェクトについて .................................................................................. 22
3.4
ユーザーID の取得 ............................................................................................... 22
3.5
リソースバンドル(プロパティファイル)の作成............................................... 22
3.6
リソースバンドルからリソースの取得................................................................. 25
3.7
画像ファイルのインポート .................................................................................. 26
3.8
画像ファイルへのアクセス .................................................................................. 27
3.9
解答例................................................................................................................... 27
[演習3]アクション処理とウィンドウステートの切替を行うポートレット ........... 31
4.1
プロジェクト情報................................................................................................. 32
4.2
実行フェーズの概要 ............................................................................................. 32
4.3
PortletURL の概要................................................................................................ 32
4.4
レンダリングフェーズの PortletURL ................................................................... 33
4.5
ポートレットモードとウィンドウステート ......................................................... 34
4.6
イベント処理フェーズの PortletURL ................................................................... 34
4.7
JSP タグによるリクエストパラメータのセット ................................................... 35
4.8
processAction メソッドの実装 ............................................................................ 35
4.9
解答例................................................................................................................... 37
[演習4]編集モードとヘルプモードを使うポートレット........................................ 42
5.1
プロジェクト情報................................................................................................. 43
5.2
モードの定義........................................................................................................ 44
5.3
ヘルプモード........................................................................................................ 45
2
IBM Japan Systems Engineering
6
7
8
9
5.4
編集モード ........................................................................................................... 46
5.5
ユーザー設定値(プリファレンス) ......................................................................... 46
5.6
Validate 機能........................................................................................................ 47
5.7
解答例................................................................................................................... 48
[演習5]データベーステーブルを使用するポートレット........................................ 58
6.1
プロジェクトの情報 ............................................................................................. 58
6.2
データベース及びテーブルの作成........................................................................ 58
6.3
データソースの作成 ............................................................................................. 60
6.4
データソースとアプリケーションの関連付け...................................................... 64
6.5
編集モードの有効化と初期パラメータの設定...................................................... 67
6.6
初期パラメータとデータソースの取得................................................................. 67
6.7
doView メソッドの処理内容 ................................................................................ 68
6.8
doEdit メソッドの処理内容 ................................................................................. 69
6.9
processAction メソッドの処理内容 ..................................................................... 70
6.10
Derby Sample Connection の切断....................................................................... 71
6.11
解答例 ............................................................................................................... 71
[演習6]カスタム(Custom)モードを使うポートレット .......................................... 87
7.1
プロジェクトの情報 ............................................................................................. 88
7.2
カスタムモードの種類.......................................................................................... 88
7.3
編集共用設定(edit_defaults)モード .................................................................. 88
7.4
構成(config)モード ............................................................................................. 89
7.5
カスタムモードの定義.......................................................................................... 89
7.6
カスタムモードの切替.......................................................................................... 90
7.7
カスタムモードで読み書きするデータの初期値 .................................................. 91
7.8
カスタムモードの PortletURL............................................................................. 92
7.9
解答例................................................................................................................... 92
[演習7]サーブレット連携 .................................................................................... 101
8.1
プロジェクトの情報 ........................................................................................... 102
8.2
ポートレットセッションのスコープ .................................................................. 102
8.3
スコープの使い分け ........................................................................................... 103
8.4
オブジェクト ID の取得 ..................................................................................... 104
8.5
サーブレットの呼び出し .................................................................................... 104
8.6
サーブレット側の対応........................................................................................ 105
8.7
解答例................................................................................................................. 107
[演習8]ユーザーおよびグループの管理............................................................... 117
9.1
プロジェクトの情報 ........................................................................................... 118
3
IBM Japan Systems Engineering
9.2
Puma の概要 ...................................................................................................... 118
9.3
ホーム・インターフェースの検索...................................................................... 118
9.4
PumaProfile....................................................................................................... 119
9.5
PumaLocator ..................................................................................................... 121
9.6
PumaController................................................................................................. 122
9.7
解答例................................................................................................................. 124
10
[演習9]ポートレット間通信(連携ポートレット) ......................................... 136
10.1
プロジェクトの情報........................................................................................ 137
10.2
ポートレット間通信の概要............................................................................. 137
10.3
送信用ポートレットを新規作成...................................................................... 138
10.4
wsdl ファイルの追加.......................................................................................... 141
10.5
ポートレット・デプロイメント記述子に wsdl を登録 ................................... 142
10.6
データ・タイプ、メッセージ及びオペレーションの定義 .............................. 144
10.7
バインディング <binding> の概要................................................................ 146
10.8
メッセージ送信時のプログラム例 .................................................................. 149
10.9
メッセージ受信時のプログラム例 .................................................................. 154
10.10
ワイヤーの作成............................................................................................... 157
10.11
異なるページに対する通信............................................................................. 161
10.12
解答例 ............................................................................................................. 163
11
TIPS ...................................................................................................................... 174
11.1
ユーザー属性の取得........................................................................................ 174
11.2
名前衝突の回避............................................................................................... 175
11.3
ユーザー設定値の書き込みに関する補足 ....................................................... 176
12
12.1
その他 .................................................................................................................... 177
特殊互換モードについて ................................................................................ 177
4
IBM Japan Systems Engineering
1
ポートレット開発の流れ
1.1
ポートレット開発環境と開発のステップ
ポートレット・アプリケーションは、アプリケーションの種類によってパターンを分ける
ことができます。1 つはバックエンドに既存のアプリケーションが存在し、それと連携して
サービスを提供するポートレットアプリケーション、もう 1 つはアプリケーションロジッ
クもポートレット側で持ち、ポータルサーバーで完結できるポートレットアプリケー
ションです。
一般的に、1番目のパターンのポートレットは、バックエンド・アプリケーションのベン
ダーから提供されているものや、WebSphere Portal に付属のポートレット、ポートレット
ビルダーを適用します。当ハンズオンで取り上げる Java での開発をおこなうポートレット
は主に、2 番目のパターンのポートレットです。
1.2
Portlet API
WebSphere Portal V6.0 で稼動するポートレットを作成するには、従来の WebSphere Portal
で使用されてきた IBM Portlet API(IBM ポートレット)と Java Community Process で定
義された標準 API(JSR168 ポートレット)の 2 種類の API セットが使用できます。メッセー
ジング API に例えると、MQ Java API と JMS の関係と同じです。
当ハンズオン、JSR168 Portlet API を使用したポートレット開発について述べるものです
が、IBM Portlet API も引き続き WebSphere Portal ではサポートされますし、多くの
WebSphere Portal 上のポートレットプログラムも IBM Portlet API で実装されています。
また、それぞれの API セットで開発されたポートレットを同一ページ上に配置して稼動さ
せることも可能です。ポートレットは、WebSphere Portal 機能の 1 つである Portlet
Container 上で稼動しますが、従来の IBM Portlet API 用の Portlet Container と、新しい
JSR168 Portlet API 用の Portlet Container が並行して稼動しているのです。これにより、
ポータル管理者やポータルユーザーはどの API セットで作成されたポートレットかを意識
する必要はありません。
1.3
ポートレット開発環境
WebSphere Portal V6.0 のポートレット開発環境は、IBM Rational Application Developer
V7.0(以下 RAD と表記)のポータル開発用のプラグインである Portal Tools が提供されて
います。Portal Tools では、ポートレットや Web コンテンツの生成、テスト、デバッグ、
パッケージングがサポートされます。Portal Tools は、デフォルトではインストールされ
5
IBM Japan Systems Engineering
ていません。RAD のインストール時に、明示的に Portal Tools を選択してインストールす
る必要があります。
1.4
ポートレット開発のステップ
一般的なポートレット開発ステップは下図のような手順を踏みます。
RAD と Portal Tools を使用することで、ポートレットとポートレット・デプロイメント記
述子のスケルトンをウィザード形式で作成することができ、パッケージングやテスト時の
簡易デプロイもサポートされるため、容易な開発が期待できます。
1.5
演習環境
次章からは、実際に RAD と Portal Tools を使用したポートレット開発の演習を行います。
ここでは、演習を行うマシンの環境について記載します。
[OS]
Windows XP Professional + Service Pack 2
[WP 開発環境]
IBM Rational Application Developer(RAD) V7.0.0.1
6
IBM Japan Systems Engineering
IBM Installation Manager V1.0.0.2
DB2 Universal Database V8.1(演習5で必要)
[演習で利用するハンズオンセットのディレクトリ構成]
/LAB
/images ・・・・ 演習2で使用する画像ファイルの保存先
/nls
・・・・ 演習2で使用するプロパティファイルの保存先
/sql
・・・・ 演習5で使用する SQL を記載したファイルの保存先
/wsdl
・・・・ 演習9で使用する wsdl ファイルの保存先
/war
・・・・ 演習の内容を war 形式でエクスポートしたファイルの保存先
7
IBM Japan Systems Engineering
2
[演習1]ウィザードに従ってポートレットを自動作成
本演習では、RAD の基本的な使用方法と、RAD を利用したポートレット作成を行う手順を理
解します。
[目的]
z
RAD の基本操作の理解
2.1
ポートレットプロジェクトおよびポートレットクラスの作成
(1)メニューバーから[ファイル]→[新規]→[ポートレット・プロジェクト]を選択し
ます。
8
IBM Japan Systems Engineering
(2)プロジェクト名やポートレット API の種類を指定します。ここでは、プロジェクト名
「Lesson1」、EAR プロジェクト名「Lesson1EAR」、ポートレット API「JSR168 ポートレット」
とします。
「EAR にプロジェクトを追加」と「ポートレットの作成」が ON になっていること
を確認します。ポートレットのタイプは「基本ポートレット」を選択します。
「次へ」ボタン
を押下します。
(3)使用するコンテンツ・タイプ、ポートレットモードの選択、パッケージ名およびロケー
ルの設定を行います。ここでは、デフォルトの設定のままにしておきます。「次へ」ボタン
を押下します。
9
IBM Japan Systems Engineering
(4)アクションの設定を行います。フォームのボタン押下時などで発生するイベント処理
processAction のサンプルコードを生成します。ここでは、デフォルトの設定のままにして
おきます。「次へ」ボタンを押下します。
(5)その他の設定を行います。ここでは、デフォルトの設定のままにしておきます。「終了」
ボタンを押下します。
10
IBM Japan Systems Engineering
(6)ポートレットプロジェクトとポートレットクラスが作成されます。
11
IBM Japan Systems Engineering
2.2
テスト環境による実行(サーバーにプロジェクトを追加)
(1)ポートレットプロジェクト「Lesson1」のアイコンを右クリックしてメニューを表示し
ます。そして、[実行]→[サーバーで実行]を選択します。
(2)「既存のサーバーを選択」を選択して、サーバーの種類として、
「WebSphere Portal v6.0
Server @ localhost」を選択して、「次へ」ボタンを押下します。
12
IBM Japan Systems Engineering
(3)構成プロジェクト(右側の領域)に「Lesson1EAR」が表示されていることを確認します。
「次へ」ボタンを押下します。
(4)「終了」ボタンを押下します。
13
IBM Japan Systems Engineering
(5)サーバーが起動し始めます。起動には 10 分以上かかります。サーバーが起動すると、
ポートレットが起動します。ポートレットの実行には https 接続を行っているので、以下
のようなセキュリティ警告が表示されますが、気にせずに「はい」を選択します。
※テスト実行に使用するブラウザの種類は、RAD のメニューバーから[ウィンドウ]→[Web
ブラウザー]を選択することで変更できます。デフォルトは内部 Web ブラウザーです。
(6)全ての起動処理が完了すると、ポートレットが表示されます。
14
IBM Japan Systems Engineering
(7)ポートレットタイトルの右端にあるアイコンをクリックすると、メニューが表示されま
す。ポートレットのステートやモードを変更できます。例えば、「最小化」を選択してみま
す。
(8)ポートレットタイトルだけが表示されていることが分ります。ステートが「最小化」の
状態です。同じメニューから「復元」を選択すると、最小化状態から「通常」に戻ります。
15
IBM Japan Systems Engineering
(9)「最大化」を選択した場合の例です。この例だと分りづらいですが、該当ポートレット
を最大表示します。1つのページに複数のポートレットを配置している場合だと、その効
果がはっきりと分ります。
(10)パラメータの受け渡しの例を示します。テキストボックスに文字列を入力して、
「実行」
ボタンを押下します。
16
IBM Japan Systems Engineering
(11)ポートレット内に、入力した文字列が表示されます。ユーザーが入力した文字列をポー
トレットが受け取ったことが分ります。
17
IBM Japan Systems Engineering
2.3
サーバーの停止
サーバービューの「WebSphere Portal v6.0 Server @ localhost」を右クリックしてメニュー
を表示します。そして、
[停止]を選択します。
18
IBM Japan Systems Engineering
2.4
サーバーからポートレットプロジェクトを削除
(1)他のポートレットをテストしたい時など、該当ポートレットをテスト環境から外す方法
を説明します。サーバービューの「WebSphere Portal v6.0 Server @ localhost」を右ク
リックしてメニューを表示します。そして、[プロジェクトの追加および除去]を選択しま
す。
(2)構成プロジェクトから、「Lesson1EAR」を選択して、「除去」ボタンを押下します。
19
IBM Japan Systems Engineering
(3)「Lesson1EAR」が使用可能なプロジェクトに移動したことを確認して、「終了」ボタン
を押下します。
20
IBM Japan Systems Engineering
3
[演習2]コアオブジェクトの使い方
プロパティファイルから挨拶文を取得し、ユーザーID と挨拶文を表示します。
[目的]
z
コアオブジェクト RenderRequest/RenderResponse/PortletConfig の使用
z
リソースバンドルからのリソース取得(プロパティファイルの利用)
z
画像ファイル等のアクセス
z
ユーザーID の取得
[イメージ画像]
3.1
プロジェクト情報
プロジェクト名
Lesson2
エンタープライズ・アプリケーション・プロジェクト Lesson2EAR
名
ポートレット名
Lesson2
表示名
Lesson2
ポートレット・クラス
com.ibm.lesson2.Lesson2Portlet
3.2
JSP の呼び出し方
Java クラスから JSP を呼び出す方法を説明します。PortletRequestDispatcher クラスを用
いて JSP を呼び出します。プロジェクト内の"WebContent"が"/"(ルート)に相当します。
例を以下に示します。
response.setContentType(request.getResponseContentType());
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/_Lesson
21
IBM Japan Systems Engineering
2/jsp/html/Lesson2PortletView.jsp");
rd.include(request,response);
3.3
コアオブジェクトについて
ポートレットの基本的な機能は、コアオブジェクトで実現しています。一部のオブジェク
トは JSP 内でも使用できます。
JSP において<portlet:defineObjects/>タグを宣言すると、RenderRequest、RenderResponse、
および PortletConfig クラスが生成したオブジェクトへのアクセスが提供されます。
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
………
クラス名
JSP 内で使用するオブジェクト名
RenderRequest
renderRequest
RenderResponse
renderResponse
PortletConfig
portletConfig
3.4
ユーザーID の取得
RenderRequest クラスの getRemoteUser メソッドを使います。
//RenderRequest request
String lesson_user = request.getRemoteUser();
3.5
リソースバンドル(プロパティファイル)の作成
(1)クライアントの使用言語によって、表示する内容を変化させる為に、言語毎のリソース
バンドル(プロパティファイル)を用いることが出来ます。ここでは、日本語用のプロパ
ティファイルを作成します。テキストエディタを起動し、以下のように入力して保存しま
す。
ファイル名:Lesson2PortletResource_ja.txt
# Default Resource Bundle
#
# filename: Lesson2PortletResource.properties
# Portlet Info resource bundle example
javax.portlet.title=Lesson2
javax.portlet.short-title=Lesson2
javax.portlet.keywords=Lesson2
22
IBM Japan Systems Engineering
greeting1=こんにちは
greeting2=さん。
プロパティファイルの構文は”リソースバンドル・キー = 値”です。このファイルは、
プロパティファイルを作成する為のワーク用です。
(2)プロパティファイルの文字コードは UNICODE であるので、native2ascii.exe を使って
UNICODE 変換を行います。
native2ascii.exe は、<RAD のインストールディレクトリ>/jdk/bin に存在します。
デフォルトでは以下の場所になります。
C:\Program Files\IBM\SDP70\jdk\bin
Lesson2PortletResource_ja.txt を native2ascii.exe と同じフォルダーにコピーしておき
ます。コマンドプロンプトを開き、native2ascii.exe を実行します。
native2ascii の構文は以下の通りです。(△は半角スペース)
native2ascii.exe△<変換前ファイル>△<変換後ファイル>
この例では、以下のように実行しています。
native2ascii.exe Lesson2PortletResource_ja.txt Lesson2PortletResource_ja.properties
UNICODE 変換したプロパティファイル Lesson2PortletResource_ja.properties が作成され
ます。
※UNICODE 変換後のプロパティファイル Lesson2PortletResource_ja.properties はハンズ
オンセットの以下の場所に用意してあります。これをそのまま使っても構いません。
/Lab/nls
23
IBM Japan Systems Engineering
(3)Lesson2PortletResource_ja.properties を、
RAD の/Lesson2/Java リソース:src/com.ibm.lesson2.nl
にインポートします。(ドラッグでコピーされます)
¾
オプション
余力のある人は、英語用のプロパティファイルを作成して、英語のメッセージが表示され
ることも確認してください。英語用のプロパティファイルは native2ascii.exe を使って変
換する必要はありません。テキストエディタで作成して、そのままプロジェクトにインポー
トしてください。
ファイル名:Lesson2PortletResource_en.properties
# Default Resource Bundle
#
# filename: Lesson2PortletResource.properties
# Portlet Info resource bundle example
javax.portlet.title=Lesson2
javax.portlet.short-title=Lesson2
javax.portlet.keywords=Lesson2
greeting1=Hello
24
IBM Japan Systems Engineering
greeting2=.
3.6
リソースバンドルからリソースの取得
ポートレット・デプロイメント・記述子(portlet.xml)の<resource-bundle>に、実行時に
アクセスできるリソースバンドルを定義します。
<portlet-app>
<portlet>
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson2.nl.Lesson2PortletResource</resource-bundle>
・・・・・(省略)
リテラルリソース(プロパティファイルの値)の取得例を示します。
・Java コードの場合
ResourceBundle bundle =
getPortletConfig().getResourceBundle(request.getLocale());
String moji = bundle.getString("greeting1");
・JSP の場合
ResourceBundle bundle =
portletConfig.getResourceBundle(renderRequest.getLocale());
String moji = bundle.getString("greeting1");
取得したリテラルリソースの文字コードは、UNICODE となっています。よって、JSP タグ
<%@page%>の属性を pageEncoding="UTF-8" と指定します。ただし、JSP に直接日本語文字
列を記述することは出来なくなります。
※ただし、ファイルそのものを UTF-8 形式で保存するならば可能
<%@page session="false" contentType="text/html" pageEncoding="UTF-8" import="java.ut
il.*" %>
pageEncoding="Shift_JIS"と指定した場合は、リソースバンドルを使用することが出来な
くなりますが、JSP に直接、日本語文字列を記述することが可能となります。
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="jav
a.util.*" %>
こ の 演 習 ( 演 習 2 ) で は 、 pageEncoding="UTF-8" を 利 用 し ま す が 、 演 習 3 以 降 は 、
pageEncoding="Shift_JIS"を利用します。
25
IBM Japan Systems Engineering
3.7
画像ファイルのインポート
プロジェクト・エクスプローラー内の/Lesson2/WebContent を右クリックしてメニューを表
示します。そして、[新規]→[フォルダー]を選択します。
フォルダー名に「images」と入力して、「終了ボタン」を押下します。
フ ォ ル ダ ー 「 images 」 が 作 成 さ れ ま す 。 プ ロ ジ ェ ク ト ・ エ ク ス プ ロ ー ラ ー 内 の
/Lesson2/WebContent/images に画像ファイル wps.gif をインポートします(ドラッグで、
26
IBM Japan Systems Engineering
コピーされます)。
※画像ファイル wps.gif はハンズオンセットの以下の場所にあります。
/Lab/images
3.8
画像ファイルへのアクセス
リソースに正確にアクセスさせるために、RenderResponse クラスの encodeURL メソッドを
使用してエンコードします。
・JSP の例
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
・・・・・
(省略)
<img src='<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/images/wps.g
if")%>' />
3.9
解答例
日本語用プロパティファイルのメッセージが表示できます。オプションで英語用のプロパ
ティファイルを作成している場合は、ブラウザの言語設定を英語にすることで、英語のメッ
セージを確認できます。
27
IBM Japan Systems Engineering
<< Lesson2Portlet.java >>
package com.ibm.lesson2;
import java.io.*;
import javax.portlet.*;
/**
* A sample portlet based on GenericPortlet
*/
public class Lesson2Portlet extends GenericPortlet {
public static final String VIEW_JSP = "/_Lesson2/jsp/html/Lesson2PortletView.jsp
";
public void doView(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
// Invoke the JSP to render
PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(VIEW_JSP);
rd.include(request,response);
}
}
<< Lesson2PortletView.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="UTF-8" import="java.ut
il.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<%
ResourceBundle bundle =
portletConfig.getResourceBundle(renderRequest.getLocale());
String lesson_user = renderRequest.getRemoteUser();
28
IBM Japan Systems Engineering
%>
<%=bundle.getString("greeting1") %>,<%=lesson_user%><%=bundle.getString("greeting2")
%>
<br><br><br>
<img src='<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/images/wps.
gif")%>' />
<br>
<< portlet.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<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/p
ortlet-app_1_0.xsd" id="com.ibm.lesson2.Lesson2Portlet.8be1afb601">
<portlet>
<portlet-name>Lesson2</portlet-name>
<display-name>Lesson2</display-name>
<display-name xml:lang="ja">Lesson2</display-name>
<portlet-class>com.ibm.lesson2.Lesson2Portlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson2.nl.Lesson2PortletResource</resource-bundle>
<portlet-info>
<title>Lesson2</title>
<short-title>Lesson2</short-title>
<keywords>Lesson2</keywords>
29
IBM Japan Systems Engineering
</portlet-info>
</portlet>
</portlet-app>
<< web.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:x
si="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.co
m/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>
Lesson2</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
30
IBM Japan Systems Engineering
4
[演習3]アクション処理とウィンドウステートの切替を行うポートレット
アクション処理のイベントによって、ウィンドウステートの切り替えを実施します(通常
→最大化/最大化→通常)。また、ユーザーがテキストボックスに入力した文字列をポート
レットに渡します。
[目的]
z
PortletURL の生成
z
ウィンドウステートの切替
z
アクションの利用
[イメージ画像]
・通常→最大化/最大化→通常
通常
最大化
・アクション処理
31
IBM Japan Systems Engineering
4.1
プロジェクト情報
プロジェクト名
Lesson3
エンタープライズ・アプリケーション・プロジェクト名
Lesson3EAR
ポートレット名
Lesson3
表示名
Lesson3
ポートレット・クラス
com.ibm.lesson3.Lesson3Portlet
4.2
実行フェーズの概要
ポートレットの実行フェーズはイベント処理とレンダリングの 2 フェーズから構成されて
います。
前回の演習で説明した doView メソッド等がレンダリングフェーズとなります。イベント処
理フェーズは、ポートレット内のボタンを押下した場合等で発生します。その際、呼ばれ
るのが、processAction メソッドです。
4.3
PortletURL の概要
ポータル上には複数のポートレットが存在する可能性があり、ユーザーからのリクエスト
を正確にポートレットに伝達させるためにポートレット専用の URL が必要です。
ポートレッ
トには、ポートレット・インスタンスを指す URL をカプセル化したオブジェクトとして、
PortletURL が提供されています。この URL は、パラメータの付加やアクションの付加が可
32
IBM Japan Systems Engineering
能であり、ポートレットコンテナーが processAction メソッドをコールし、アクション処
理が実行されます。同一ポートレット内に複数のアクションが存在する場合には action の
名前で識別します。
レンダリングフェーズの URL とイベント処理フェーズの URL は RenderResponse クラスから
取得できます。
・Java コード
z
RenderResponse.createRenderURL()
//レンダリングフェーズの URL
z
RenderResponse.createActionURL()
//イベント処理フェーズの URL
・JSP タグ
z
<portlet:renderURL/>
//レンダリングフェーズの URL
z
<portlet:actionURL/>
//イベント処理フェーズの URL
PortletURL.toString()の例
/wps/myportal/!ut/p/_s.7_0_A/7_0_9D/.cmd/ad/.ar/sa.save/.c/6_0_69/.ce/7_0_IQ/.p/
5_0_FL/.d/0#7_0_IQ
4.4
レンダリングフェーズの PortletURL
JSP タグで使用できる PortletURL のパラメータはあらかじめ決まっています。
・ポートレットモードで指定できる値
<portlet:renderURL portletMode="view" />
//View モード
<portlet:renderURL portletMode="edit" />
//Edit モード
<portlet:renderURL portletMode="help" />
//Help モード
・ウィンドウステートで指定できる値
<portlet:renderURL windowState="normal" />
//通常
<portlet:renderURL windowState="maximized" />
//最大化
<portlet:renderURL windowState="minimized" />
//最小化
ポートレットモードとウィンドウステートの両方を同時に指定することも可能です。JSP
において、View モード+通常ステートとして表示する PortletURL の生成例を示します。
<a href="<portlet:renderURL portletMode="view" windowState="normal"/>">click</a>
尚、Java コードで同様の記述を行う場合の例も示しておきます。
33
IBM Japan Systems Engineering
try{
PortletURL portletUrl = response.createRenderURL();
portletUrl.setPortletMode(PortletMode.VIEW);
portletUrl.setWindowState(WindowState.NORMAL);
}catch(PortletModeException e1){
//エラー処理
}catch(WindowStateException e2){
//エラー処理
}
4.5
ポートレットモードとウィンドウステート
前節で説明した PortletURL クラスにセットするポートレットモードとウィンドウステート
の値を以下に示します。
クラス
javax.portlet.PortletMode
javax.portlet.WindowState
4.6
フィールド名
説明
VIEW
表示モード
EDIT
編集モード
HELP
ヘルプモード
NORMAL
通常
MAXIMIZED
最大化
MINIMIZED
最小化
イベント処理フェーズの PortletURL
JSP におけるアクション用 PortletURL の生成例を示します。processAction メソッドが呼ば
れます。
<FORM method="POST" action="<portlet:actionURL/>">
<INPUT name="<%=Lesson3Portlet.FORM_TEXT%>" type="text"/>
<INPUT name="<%=Lesson3Portlet.FORM_SUBMIT%>" type="submit" value=“push"/>
</FORM>
尚、Java コードで同様の記述を行う場合の例も示しておきます。
try{
PortletURL portletUrl = response.createActionURL();
portletUrl.setParameter(FORM_TEXT,"hello");
portletUrl.setParameter(FORM_SUBMIT,"submit");
//portletUrl によるアクションの呼び出し
・・・・・(省略)
34
IBM Japan Systems Engineering
}catch(PortletModeException e1){
//エラー処理
}catch(WindowStateException e2){
//エラー処理
}
4.7
JSP タグによるリクエストパラメータのセット
PortletURL 生成時に、JSP タグを使ってリクエストパラメータをセットすることも出来ま
す。例を以下に示します。
<portlet:actionURL portletMode="view">
<portlet:param name="greeting" value="hello"/>
</portlet:actionURL>
4.8
processAction メソッドの実装
processAction メソッドでは、ActionRequest オブジェクトと ActionResponse オブジェク
トが利用できます。レンダリングフェーズにおける、RenderRequest オブジェクトと
RenderResponse オブジェクトに相当します。
ActionRequest オブジェクトの getParameter メソッドを用いてリクエストパラメータを取
得出来ます。ただし、アクションイベント時のパラメータは RenderRequest オブジェクト
からは取得できません。よって、レンダリングフェーズ(JSP を含む)で、このパラメータを
取得したい場合は、次に示す ActionResponse オブジェクトの setRenderParameter メソッド
を使って再設定する必要があります。この設定をしたパラメータに限って、(レンダリング
フェーズ時に)RenderRequest オブジェクトの getParameter メソッドで取得出来ます。
public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
if(request.getParameter(FORM_SUBMIT) != null){
response.setRenderParameter(FORM_TEXT, request.getParameter(FORM_TEXT));
}
}
もう一つの方法として、ポートレットセッション(PortletSession)を使う方法があります。
そのまま文字列をセットすることも可能ですが、一般的には、JavaBeans クラスを定義しま
す。該当パラメータを、生成した JavaBeans にセットし、JavaBeans 自体をポートレットセッ
ションにセットします。RAD が自動生成するソースではこちらの方法が採用されています。
以下に例を示します。
35
IBM Japan Systems Engineering
public void processAction(ActionRequest request, ActionResponse response) throws P
ortletException, java.io.IOException {
if(request.getParameter(FORM_SUBMIT) != null){
Lesson3PortletSessionBean sessionBean = getSessionBean(request);
if(sessionBean != null){
//session オブジェクトにセット
sessionBean.setFormText(request.getParameter(FORM_TEXT));
}
}
}
//session オブジェクトを取得・生成
private static Lesson3PortletSessionBean getSessionBean(PortletRequest request) {
PortletSession session = request.getPortletSession();
if(session == null){
return null;
}
Lesson3PortletSessionBean sessionBean = (Lesson3PortletSessionBean)session.get
Attribute(SESSION_BEAN);
if(sessionBean == null){
sessionBean = new Lesson3PortletSessionBean();
session.setAttribute(SESSION_BEAN,sessionBean);
}
return sessionBean;
}
ポートレットセッションから値を取得する JSP の例を示します。
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="j
ava.util.*,javax.portlet.*,com.ibm.lesson3.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<%
Lesson3PortletSessionBean sessionBean = (Lesson3PortletSessionBean)renderReque
st.getPortletSession(false).getAttribute(Lesson3Portlet.SESSION_BEAN);
36
IBM Japan Systems Engineering
%>
<H3 style="margin-bottom: 3px"><%=sessionBean.getFormText()%></H3>
解答例
4.9
<< Lesson3Portlet.java >>
package com.ibm.lesson3;
import java.io.*;
import javax.portlet.*;
/**
* A sample portlet based on GenericPortlet
*/
public class Lesson3Portlet extends GenericPortlet {
public static final String VIEW_JSP
= "/_Lesson3/jsp/html/Lesson3PortletVie
w.jsp";
public static final String SESSION_BEAN = "Lesson3PortletSessionBean";
public static final String FORM_ACTION
= "Lesson3PortletFormSubmit";
public static final String FORM_MESSAGE = "Lesson3PortletFormText";
public void init() throws PortletException{
super.init();
}
public void doView(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
// Check if portlet session exists
Lesson3PortletSessionBean sessionBean = getSessionBean(request);
if( sessionBean==null ) {
response.getWriter().println("<b>NO PORTLET SESSION YET</b>");
return;
}
37
IBM Japan Systems Engineering
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(VIEW_
JSP);
rd.include(request,response);
}
public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
if( request.getParameter(FORM_ACTION) != null ) {
// Set form text in the session bean
Lesson3PortletSessionBean sessionBean = getSessionBean(request);
if( sessionBean != null )
sessionBean.setFormText(request.getParameter(FORM_MESSAGE));
}
}
private static Lesson3PortletSessionBean getSessionBean(PortletRequest request)
{
PortletSession session = request.getPortletSession();
if( session == null )
return null;
Lesson3PortletSessionBean sessionBean = (Lesson3PortletSessionBean)session.g
etAttribute(SESSION_BEAN);
if( sessionBean == null ) {
sessionBean = new Lesson3PortletSessionBean();
session.setAttribute(SESSION_BEAN,sessionBean);
}
return sessionBean;
}
}
<< Lesson3PortletSessionBean.java >>
package com.ibm.lesson3;
38
IBM Japan Systems Engineering
public class Lesson3PortletSessionBean {
private String formText = "";
public void setFormText(String formText) {
this.formText = formText;
}
public String getFormText() {
return this.formText;
}
}
<< Lesson3PortletView.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="java
x.portlet.*,com.ibm.lesson3.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<%
Lesson3PortletSessionBean sessionBean = (Lesson3PortletSessionBean)renderReques
t.getPortletSession(false).getAttribute(Lesson3Portlet.SESSION_BEAN);
%>
<DIV style="margin: 12px; margin-bottom: 36px">
<H3 style="margin-bottom: 3px"><%=sessionBean.getFormText()%></H3>
<br>
<br>
<FORM method="POST" action="<portlet:actionURL/>">
<LABEL for="<%=Lesson3Portlet.FORM_MESSAGE%>">好きな言葉を入力してください:</LAB
EL><br>
<INPUT name="<%=Lesson3Portlet.FORM_MESSAGE%>" type="text"/>
<INPUT name="<%=Lesson3Portlet.FORM_ACTION%>" type="submit" value="決定"/>
</FORM>
<br>
39
IBM Japan Systems Engineering
<br>
<%
if (WindowState.NORMAL.equals(renderRequest.getWindowState())){
%>
通常表示です。<br><br>
<a href="<portlet:renderURL windowState="maximized"/>">最大化する</a><br><br>
<%
} else if (WindowState.MAXIMIZED.equals(renderRequest.getWindowState())){
%>
最大表示です。<br><br>
<a href="<portlet:renderURL windowState="normal"/>">通常に戻す</a><br><br>
<%
}
%>
</DIV>
<< portlet.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<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/p
ortlet-app_1_0.xsd" id="com.ibm.lesson3.Lesson3Portlet.388863c601">
<portlet>
<portlet-name>Lesson3</portlet-name>
<display-name>Lesson3</display-name>
<display-name xml:lang="ja">Lesson3</display-name>
<portlet-class>com.ibm.lesson3.Lesson3Portlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
40
IBM Japan Systems Engineering
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson3.nl.Lesson3PortletResource</resource-bundle>
<portlet-info>
<title>Lesson3</title>
<short-title>Lesson3</short-title>
<keywords>Lesson3</keywords>
</portlet-info>
</portlet>
</portlet-app>
<< web.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:x
si="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.co
m/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>
Lesson3</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
41
IBM Japan Systems Engineering
5
[演習4]編集モードとヘルプモードを使うポートレット
簡易版ブックマークポートレットを作成します。編集モードにおいてブックマーク先を登
録します。
[目的]
z
モードの切替
z
構成パラメータの保管
z
Validate 機能の利用
[イメージ画像]
・ブックマーク先を表示
新規ウィンドウ表示
表示モード
・編集モードに切替
表示モード
編集モード
42
IBM Japan Systems Engineering
・ヘルプモードの表示
表示モード
5.1
新規ウィンドウ表示
プロジェクト情報
プロジェクト名
Lesson4
エンタープライズ・アプリケーション・プロジェクト名
Lesson4EAR
ポートレット名
Lesson4
表示名
Lesson4
ポートレット・クラス
com.ibm.lesson4.Lesson4Portlet
ウィザードに従ってポートレットプロジェクトを作成する際、モードの定義のところで、
「編集」と「ヘルプ」を ON にしておくと、該当ファイルの雛形が自動的に作成されます。
43
IBM Japan Systems Engineering
ウィザードに従ってポートレットプロジェクトを作成する際、アクション設定のところで、
「設定バリデーターの追加」を ON にしておくと、該当ファイルの雛形が自動的に作成され
ます。
5.2
モードの定義
使用するモードをポートレット・デプロイメント記述子(portlet.xml)の<portlet-mode>エ
レメントで指定する必要があります。
<portlet-app>
<portlet>
・・・・・(省略)
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode>
</supports>
44
IBM Japan Systems Engineering
1.アイコンをクリックすると、
ポートレットメニューが表示
2.個別設定(編集モード)、
ヘルプ(ヘルプモード)が追加
5.3
ヘルプモード
ポートレットメニューから「ヘルプ」を選択すると、GenericPortlet クラスの doHelp メソッ
ドが呼ばれます。doHelp メソッドにおいて PortletRequestDispatcher.include()を実行す
ると、新しくウィンドウ(ブラウザ)が起動してその中にヘルプ用 JSP の内容を表示しま
す。
//Lesson4Portlet.doHelp()
PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher
("/_Lesson4/jsp/html/Lesson4PortletHelp.jsp");
rd.include(request,response);
新規ウィンドウ
45
IBM Japan Systems Engineering
5.4
編集モード
ポートレットメニューから「個別設定」を選択すると、GenericPortlet クラスの doEdit メ
ソッドが呼ばれます。doEdit メソッドにおいて PortletRequestDispatcher.include()を実
行すると、ポートレットのモードが切り替わり、編集用 JSP の内容を表示します。
//Lesson4Portlet. doEdit()
PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher
("/_Lesson4/jsp/html/Lesson4PortletEdit.jsp");
rd.include(request,response);
画面切替
5.5
ユーザー設定値(プリファレンス)
ユーザーが設定した値をポートレットで保管することが出来ます。ユーザー設定値は
PortletPreferences オブジェクトを使用して保管、設定、および取得されます。初期値を、
ポートレット・デプロイメント記述子の <preference/> エレメントで設定可能です。読み
取り専用以外であれば、任意のポートレット・モードで読み書き出来ます。読み取り専用
の場合、管理特権を持つユーザーのみが構成モードを使用して変更できます。読み取り専
用の方法は、演習6のカスタムモード(構成モード)の説明時に詳しく述べます。
portlet.xml の例
<portlet-preferences>
<preference>
<name>url.IBM</name>
<value>http://www.ibm.co.jp</value>
</preference>
<preference>
・・・・・(省略)
</portlet-preferences>
(a)ユーザー設定値の取得
ポートレットは、PortletRequest オブジェクトの getPreferences メソッドを呼び出して、
46
IBM Japan Systems Engineering
PortletPreferences のインスタンスへの参照を取得します。ユーザー設定値を取得する場
合、PortletPreferences.getValue メソッドを使います。
PortletPreferences prefs = renderRequest.getPreferences();
String value = prefs.getValue("url.IBM","<undefined>");
※getValue メソッドの 2 番目の引数は、値を取得できなかった場合の代替値です。
(b)ユーザー設定値の書き込み
ユーザー設定値を、新しい値で書き込む場合、PortletPreferences.setValue メソッドを使
います。値は PortletPreferences.store メソッドによって、リポジトリデータベースに保
管(コミット)されます。
PortletPreferences prefs = request.getPreferences();
prefs.setValue("url.IBM", "http://www.ibm.co.jp");
prefs.store();
(c)ユーザー設定値の削除
ユーザー設定値を削除する場合、PortletPreferences.reset メソッドを使います。値は
PortletPreferences.store メソッドによって、リポジトリデータベースから削除(コミッ
ト)されます。
PortletPreferences prefs = request.getPreferences();
PortletPreferences.reset("url.IBM");
prefs.store();
5.6
Validate 機能
ユーザー設定値のコミット時、値が適切かどうかを判断する機能を持ったクラスを呼び出
すことが可能です。この機能を Validate と言います。Validate 機能を利用するには、
Validate クラスをポートレット・デプロイメント記述子の<preferences-validator>エレ
メントで定義しておく必要があります。
portlet.xml の例
<portlet-preferences>
・・・・・(省略)
<preferences-validator>com.ibm.lesson4.Lesson4PortletPreferencesValidator</preference
s-validator>
</portlet-preferences>
ユーザー設定値のコミット時に PreferencesValidator クラスの validate メソッドが呼ば
れます。
47
IBM Japan Systems Engineering
・Java コードの例
try {
prefs.setValue("url.IBM", "http://www.ibm.co.jp");
prefs.store(); //PreferencesValidator オブジェクトが呼び出される
・・・・・(省略)
}
PreferencesValidator クラスの validate メソッドを実装します。以下の例では、ユーザー
設定値の先頭が"http:"か"https"以外ならエラーとしています。また、エラー時には、
ValidatorException オブジェクトを throw することで、ポートレット側で、妥当性のエラー
判定が可能になります。
public class Lesson4PortletPreferencesValidator implements PreferencesValidator {
public void validate(PortletPreferences preferences) throws ValidatorException {
Collection failedKeys = new ArrayList();
for( Enumeration names=preferences.getNames(); names.hasMoreElements(); ) {
String name = names.nextElement().toString();
if( !name.startsWith("url.") ) continue;
String value = preferences.getValue(name, "");
if(!value.equalsIgnoreCase(value.trim()) ||
!(value.startsWith("http:")||value.startsWith("https:")) ) {
failedKeys.add(name);
}
}
if( !failedKeys.isEmpty() ) {
throw new ValidatorException("妥当性チェックにおいて入力値がエラーと判定されま
した。その為、プリファレンスに登録できません。",failedKeys);
}
}
}
5.7
解答例
<< Lesson4Portlet.java >>
package com.ibm.lesson4;
import java.io.*;
import java.util.*;
48
IBM Japan Systems Engineering
import javax.portlet.*;
/**
* A sample portlet based on GenericPortlet
*/
public class Lesson4Portlet extends GenericPortlet {
public static final String VIEW_JSP = "/_Lesson4/jsp/html/Lesson4PortletView.jsp";
public static final String EDIT_JSP = "/_Lesson4/jsp/html/Lesson4PortletEdit.jsp";
public static final String HELP_JSP = "/_Lesson4/jsp/html/Lesson4PortletHelp.jsp";
public static final String PREF_SET
= "Lesson4PortletPrefSet";
public static final String PREF_RESET
= "Lesson4PortletPrefReset";
public static final String PREF_NAME
= "Lesson4PortletPrefName";
public static final String PREF_VALUE
= "Lesson4PortletPrefValue";
public static final String ERROR_MESSAGE = "Lesson4PortletErrorMessage";
public static final String ERROR_KEYS
= "Lesson4PortletErrorKeys";
public void init() throws PortletException{
super.init();
}
public void doView(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(VIEW_
JSP);
rd.include(request,response);
}
public void doEdit(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
49
IBM Japan Systems Engineering
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(EDIT_
JSP);
rd.include(request,response);
}
protected void doHelp(RenderRequest request, RenderResponse response) throws Por
tletException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(HELP_
JSP);
rd.include(request,response);
}
public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
if( request.getParameter(PREF_RESET) != null ) {
// Reset or remove a portlet preference
PortletPreferences prefs = request.getPreferences();
prefs.reset(request.getParameter(PREF_RESET));
prefs.store();
}
else if( request.getParameter(PREF_SET) != null ) {
// Set a portlet preference
PortletPreferences prefs = request.getPreferences();
String prefName = request.getParameter(PREF_NAME);
if( "".equals(prefName) ) prefName = "(no name)";
prefName = "url." + prefName;
try {
prefs.setValue(prefName,request.getParameter(PREF_VALUE));
prefs.store();
}
catch( ReadOnlyException roe ) {
50
IBM Japan Systems Engineering
response.setRenderParameter(ERROR_MESSAGE,"Read-only portlet prefere
nce '"+prefName+"' cannot be changed. Use configure mode to change it.");
}
catch( ValidatorException ve ) {
// Show validation error messages
response.setRenderParameter(ERROR_MESSAGE,ve.getMessage());
Enumeration failedKeys = ve.getFailedKeys();
if( failedKeys != null && failedKeys.hasMoreElements() ) {
Vector errors = new Vector();
while( failedKeys.hasMoreElements() )
errors.add(failedKeys.nextElement());
response.setRenderParameter(ERROR_KEYS,(String[])errors.toArray
(new String[errors.size()]));
}
}
}
}
}
<< Lesson4PortletPreferencesValidator.java >>
package com.ibm.lesson4;
import java.util.*;
import javax.portlet.*;
/**
*
* A sample portlet preferences validator
*
*/
public class Lesson4PortletPreferencesValidator implements PreferencesValidator {
public void validate(PortletPreferences preferences) throws ValidatorException {
Collection failedKeys = new ArrayList();
for( Enumeration names=preferences.getNames(); names.hasMoreElements(); ) {
String name = names.nextElement().toString();
51
IBM Japan Systems Engineering
if( !name.startsWith("url.") ) continue;
String value = preferences.getValue(name, "");
//validates that the preferences start with http: or https:
if( !value.equalsIgnoreCase(value.trim()) || !(value.startsWith("http:
")||value.startsWith("https:")) ) {
failedKeys.add(name);
}
}
if( !failedKeys.isEmpty() ) {
throw new ValidatorException("妥当性チェックにおいて入力値がエラーと判定
されました。その為、プリファレンスに登録できません。",failedKeys);
}
}
}
<< Lesson4PortletView.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="jav
a.util.*,javax.portlet.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<DIV style="margin: 6px">
<H3 style="margin-bottom: 3px">ブックマーク一覧</H3>
<DIV style="margin: 12px; margin-bottom: 36px">
<%
PortletPreferences prefs = renderRequest.getPreferences();
Enumeration prefNames = prefs.getNames();
if (!prefNames.hasMoreElements()) { // no bookmarks
%>
ブックマークを付けられません。 ブックマークの追加には編集モードを使用してくだ
さい。<BR>
<%
}
else {
52
IBM Japan Systems Engineering
while( prefNames.hasMoreElements() ) {
String name = prefNames.nextElement().toString();
if( !name.startsWith("url.") ) continue;
%>
<A TARGET="_blank" HREF='<%=prefs.getValue(name,"<undefined>")%>'>
<%=name.substring(4)%></A><BR>
<%
}
%>
<BR>
<%
}
%>
</DIV>
</DIV>
<< Lesson4PortletEdit.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="jav
a.util.*,javax.portlet.*"%>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<H3 style="margin-bottom: 3px">ブックマーク登録・削除</H3>
<DIV style="margin: 12px; margin-bottom: 36px">
<FORM ACTION="<portlet:actionURL/>" METHOD="POST">
<TABLE CELLPADDING=0 CELLSPACING=4>
<TBODY>
<TR>
<TH><B>Name</B></TH>
<TH><B>URL</B></TH>
<TH></TH>
</TR>
<%
PortletPreferences prefs = renderRequest.getPreferences();
53
IBM Japan Systems Engineering
for( Enumeration prefNames=prefs.getNames(); prefNames.hasMoreElements(); )
{
String name = prefNames.nextElement().toString();
if( !name.startsWith("url.") ) continue;
%>
<TR>
<TD><%=name.substring(4)%></TD>
<TD><%=prefs.getValue(name,"<undefined>")%></TD>
<TD><A HREF ='<portlet:actionURL><portlet:param name="<%=com.ibm.le
sson4.Lesson4Portlet.PREF_RESET%>" value="<%=name%>"/></portlet:actionURL>'>削除</A>
</TD>
</TR>
<%
}
%>
<TR>
<TD><INPUT NAME="<%=com.ibm.lesson4.Lesson4Portlet.PREF_NAME%>" TYPE="te
xt"></TD>
<TD><INPUT NAME="<%=com.ibm.lesson4.Lesson4Portlet.PREF_VALUE%>" TYPE="t
ext"></TD>
<TD><INPUT NAME="<%=com.ibm.lesson4.Lesson4Portlet.PREF_SET%>" TYPE="sub
mit" value="登録"></TD>
</TR>
</TBODY>
</TABLE>
</FORM>
<%
String errorMessage = renderRequest.getParameter(com.ibm.lesson4.Lesson4Portlet.
ERROR_MESSAGE);
if( errorMessage != null ) {
%>
<B><%=errorMessage%></B><BR>
<%
String errorKeys[] = renderRequest.getParameterValues(com.ibm.lesson4.Lesson
4Portlet.ERROR_KEYS);
54
IBM Japan Systems Engineering
if( errorKeys != null && errorKeys.length > 0 ) {
%>
<UL>
<%
for( int i=0; i<errorKeys.length; i++ ) {
%>
<LI><%=errorKeys[i]%></LI>
<%
}
%>
</UL>
<%
}
}
%>
</DIV>
<FORM ACTION='<portlet:renderURL portletMode="view"/>' METHOD="POST">
<INPUT NAME="back" TYPE="submit" VALUE="表示モードに戻る">
</FORM>
<< Lesson4PortletHelp.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<DIV style="margin: 6px">
<H3 style="margin-bottom: 3px">ようこそ!</H3>
ヘルプ・モード ページのサンプルです。 このページを編集して自分用にカスタマイズしてく
ださい。<BR>
</DIV>
<< portlet.xml >>
55
IBM Japan Systems Engineering
<?xml version="1.0" encoding="UTF-8"?>
<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/p
ortlet-app_1_0.xsd" id="com.ibm.lesson4.Lesson4Portlet.865266c601">
<portlet>
<portlet-name>Lesson4</portlet-name>
<display-name>Lesson4</display-name>
<display-name xml:lang="ja">Lesson4</display-name>
<portlet-class>com.ibm.lesson4.Lesson4Portlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode>
</supports>
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson4.nl.Lesson4PortletResource</resource-bundle>
<portlet-info>
<title>Lesson4</title>
<short-title>Lesson4</short-title>
<keywords>Lesson4</keywords>
</portlet-info>
<portlet-preferences>
<preference>
<name>url.google</name>
<value>http://www.google.co.jp</value>
</preference>
<preference>
<name>url.yahoo</name>
<value>http://www.yahoo.co.jp</value>
56
IBM Japan Systems Engineering
</preference>
<preferences-validator>com.ibm.lesson4.Lesson4PortletPreferencesValidat
or</preferences-validator>
</portlet-preferences>
</portlet>
</portlet-app>
<< web.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:x
si="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.co
m/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>
Lesson4</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
57
IBM Japan Systems Engineering
6
[演習5]データベーステーブルを使用するポートレット
IFrame を使用して外部サイトを表示するポートレットを作成します。編集画面を作成し、
編集画面内で、表示する URL、IFrame のサイズ(縦、横)が登録出来るようにし、独自の
テーブルに保存します。
※この演習では、トランザクション機能は省いています。よって、テーブル更新時にコミッ
トやロールバックは行いません。
[目的]
z
DataSource を使ったデータベーステーブルの操作
[イメージ画像]
表示モード
6.1
編集モード
プロジェクトの情報
プロジェクト名
Lesson5
エンタープライズ・アプリケーション・プロジェクト名
Lesson5EAR
ポートレット名
Lesson5
表示名
Lesson5
ポートレット・クラス
com.ibm.lesson5.Lesson5Portlet
6.2
データベース及びテーブルの作成
この演習では、設定情報をデータベースのテーブルに保存します。その為、事前に演習を
行うPCにデータベースをインストールしておく必要があります。ここでは、「DB2
Universal Database V8.1」をインストールしているものとして説明します。
【環境】
¾
データベースの製品名: DB2 Universal Database V8.1
58
IBM Japan Systems Engineering
¾
データベース管理者 ID: db2admin
¾
データベース管理者パスワード: pass
¾
作成するデータベース名: TESTDB
¾
作成するテーブル名: WORKSHOP1
テーブルの内容
カラム名
データ・タイプ
説明
NULL 可能
USERID
VARCHAR(50)
ユーザーID
×
URL
VARCHAR(100)
ユーザーが設定した URL
×
WIDTH
VARCHAR(10)
ユーザーが設定した Window の幅
×
HEIGHT
VARCHAR(10)
ユーザーが設定した Window の高さ
×
(1)テーブルを作成する為、DB2 の「コマンドウィンドウ」を開きます。
[スタートメニュー] → [すべてのプログラム] → [IBM DB2] → [コマンド行ツール] →
[コマンド・ウィンドウ]
(2)コマンド・ウィンドウから、db2 コマンドを使用して、データベース「TESTDB」を作成
します。
db2 CREATE DATABASE TESTDB ON C: ALIAS testdb USING CODESET UTF-8 TERRITORY JP COLLA
TE USING SYSTEM
※改行しないで、1 行で入力してください。
(3)db2 コマンドを使用して、データベース「TESTDB」に接続します。
db2 connect to TESTDB user db2admin using pass
(4)db2 コマンドを使用して、テーブル「WORKSHOP1」を作成します。
db2 CREATE TABLE WORKSHOP1(USERID VARCHAR(50) NOT NULL, URL VARCHAR(100) NOT NULL,WI
DTH VARCHAR(10) NOT NULL, HEIGHT VARCHAR(10) NOT NULL, PRIMARY KEY(USERID))
※改行しないで、1 行で入力してください。
(5)db2 コマンドを使用して、データベース「TESTDB」から切断します。
db2 connect reset
59
IBM Japan Systems Engineering
6.3
データソースの作成
(1)メニューバーから[ウィンドウ]→[ビューの表示]→[その他]を選択します。
(2)ビューの一覧から[データ]→[データベース・エクスプローラー]を選択し、「OK」
ボタンを押下します。
(3)「データベース・エクスプローラー」が表示されます。
60
IBM Japan Systems Engineering
(4)「データベース・エクスプローラー」の接続アイコンを右クリックしてメニューを出し、
[新規接続]を選択します。
(5)各接続パラメータを設定して、「次へ」ボタンを押下します。
【設定内容】
¾
デフォルトの命名規則を使用: OFF
¾
接続名: TESTDB
¾
データベース・マネージャーの選択: DB2 UDB V8.1
¾
JDBC ドライバー: IBM DB2 Universal
61
IBM Japan Systems Engineering
¾
データベース: TESTDB
¾
ホスト: localhost
¾
ポート番号: 50000
¾
クライアント認証の使用: OFF
¾
ユーザーID: db2admin
¾
パスワード: pass
(6)設定内容が正しければ、接続テストに成功します。「OK」ボタンを押下します。
(7)「フィルターを使用不可にする」が ON になっていることを確認して、「終了」ボタンを
押下します。
62
IBM Japan Systems Engineering
(8)「データベース・エクスプローラー」において、データベース「TESTDB」のテーブル
「WORKSHOP1」が表示できることを確認します。これで、データソース名「jdbc/TESTDB」
が作成されました。
63
IBM Japan Systems Engineering
6.4
データソースとアプリケーションの関連付け
J2EE のリソースアクセス仕様(今回の場合で言えば、データソースの事)として、アプリ
ケーションで直接 lookup するグローバル参照と、デプロイメント記述子(web.xml)を用い
て間接的に lookup するリソース参照が存在します。グローバル参照は、現行の J2EE では
非推奨です。リソース参照を利用してください。各設定ファイルの関連図を以下に示しま
す。
war ファイル
ポータル
プログラム
<<jdbc/resTESTDB>>
デプロイメント記述子
<<jdbc/resTESTDB>>
データソース
<<jdbc/TESTDB>>
DB2
ibm-web-bnd.xmi
<<jdbc/TESTDB>>
データベース
【設定内容】
¾
データソース: jdbc/TESTDB
¾
リソース参照名: jdbc/resTESTDB
(1)「デプロイメント記述子(web.xml)」を開きます。「参照」タブを選択して、「追加」ボ
タンを押下します。
64
IBM Japan Systems Engineering
(2)「リソース参照」を選択して、「次へ」ボタンを押下します。
(3)各パラメータを設定して、「終了」ボタンを押下します。
【設定内容】
¾
名前: jdbc/resTESTDB
¾
タイプ: javax.sql.DataSource
¾
認証: Application
¾
共用スコープ: Unshareable
<<=== リソース参照名を指定
(4)リソース「ResourceRef jdbc/resTESTDB」を選択して、「JNDI 名」にデータソース名の
「jdbc/TESTDB」を入力します。最後に、デプロイメント記述子(web.xml)を保存します。
65
IBM Japan Systems Engineering
(設定例)
【Lesson5Portlet.java】
Context ctx = new InitialContext();
db_datasource = (DataSource)ctx.lookup("java:comp/env/jdbc/resTESTDB");
【デプロイメント記述子(web.xml)】
<resource-ref id="ResourceRef_1172653021890">
<description>
</description>
<res-ref-name>jdbc/resTESTDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Unshareable</res-sharing-scope>
</resource-ref>
【ibm-web-bnd.xmi】
<resRefBindings xmi:id="ResourceRefBinding_1172653021890" jndiName="jdbc/TESTDB">
<bindingResourceRef href="WEB-INF/web.xml#ResourceRef_1172653021890"/>
</resRefBindings>
66
IBM Japan Systems Engineering
6.5
編集モードの有効化と初期パラメータの設定
ポートレット・デプロイメント記述子(portlet.xml)において、編集モードの有効化と初期
パラメータを設定します。
編集モードの有効化を行います。
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
</supports>
DB アクセスに必要な情報を<init-param>タグに設定します。
名前
値
db.name
TESTDB
db.user
db2admin
db.pass
pass
<init-param>
<name>db.name</name>
<value>TESTDB</value>
</init-param>
<init-param>
<name>db.user</name>
<value>db2admin</value>
</init-param>
<init-param>
<name>db.pass</name>
<value>pass</value>
</init-param>
6.6
初期パラメータとデータソースの取得
ポートレット(Lesson5Portlet.java)の init メソッド内で初期パラメータとデータソース
の取得を行います。
ロード済み PortletConfig オブジェクトを取得し、そのオブジェクトの getInitParameter
67
IBM Japan Systems Engineering
メソッドを用いて、初期パラメータを取得します。
// 初期パラメータより DB 接続ユーザ名を取得
String db_user = getPortletConfig().getInitParameter("db.user");
また、Context オブジェクトの lookup メソッドを用いて、データソースを取得します。
// 初期コンテキストの構築
Context ctx = new InitialContext();
DataSource db_datasource = (DataSource)ctx.lookup("java:comp/env/jdbc/resTESTDB");
※lookup に用いる JNDI 名は、"java:comp/env/" + 「リソース参照名」です。
6.7
doView メソッドの処理内容
自ユーザーID に対応するデータをテーブルから取得し、取得した値を SessionBean に設定
し、JSP を表示します。
¾
DB のコネクションを取得
init メソッドで取得した DataSource からコネクションを取得します。
//DataSource db_datasource
Connection conn = db_datasource.getConnection("db2admin", "pass");
¾
テーブル「WORKSHOP1」から、自ユーザーのデータを参照する SQL を作成
テーブルから取得するカラムと条件
取得するカラム
URL、ウィンドウの幅、ウィンドウの高さ
条件
自ユーザーID とテーブル内の USERID が一致
SELECT URL, WIDTH, HEIGHT FROM WORKSHOP1 WHERE USERID=?
※'?'は自ユーザーID です。
¾
ステートメントオブジェクトを作成&実行
DB アクセスを行う為のステートメントオブジェクトを作成して、実行します。下記の例で
は、ステートメントオブジェクトに「PreparedStatement」を用いています。これは、パラ
メータの設定が可能なステートメントオブジェクトです。
//Connection dbConn
String SE_SQL = "SELECT URL, WIDTH, HEIGHT FROM WORKSHOP1 WHERE USERID=?";
PreparedStatement stmt = dbConn.prepareStatement(SE_SQL);
stmt.setString(1, request.getRemoteUser());
ResultSet rs = stmt.executeQuery();
68
IBM Japan Systems Engineering
¾
SQL の実行結果を参照
SQL の実行結果を参照して、自ユーザーの登録情報の有無を確認します。自ユーザー情報が
存在する場合、実行結果(ResultSet)から、URL、ウィンドウの幅、ウィンドウの高さを取得
して、SessionBean に設定します。
//Lesson5PortletSessionBean sessionBean
String value = rs.getString("URL")
sessionBean.setSrcURL(value);
¾
ステートメント、コネクションをクローズ
finally 節の中でステートメント、コネクションのクローズを行います。
try {
・・・・・(省略)
} catch(SQLException e) {
・・・・・(省略)
} finally {
if(stmt != null) {
// ステートメントのクローズ
try {
stmt.close();
} catch(Exception e) {}
}
if(dbConn != null) {
// コネクションのクローズ
try {
dbConn.close();
} catch(Exception e) {}
}
}
6.8
doEdit メソッドの処理内容
doView メソッドと同様に、自ユーザーID に対応するデータをテーブルから取得し、取得し
た値を SessionBean に設定し、JSP を表示します。テーブルに該当データが存在しない場合
は、空の文字列("")を設定します。
69
IBM Japan Systems Engineering
6.9
processAction メソッドの処理内容
編集モードにおいて、ユーザーが入力したサイトの URL、ウィンドウの幅、ウィンドウの高
さをテーブルに保存します。自ユーザーの情報が登録されている場合は、テーブルを更新
し、登録されていなければテーブルに挿入します。
¾
リクエストオブジェクトからユーザーが入力したサイトの URL を取得します。null(ヌ
ル)または空の文字列("")であった場合、無効とします。
¾
自ユーザーの情報が既に登録されているかチェックします。ここでは、件数が 0 件な
らば登録されていない、0 以外ならば登録されていると判断します。
// WORKSHOP1 テーブルから、現在ログインしているユーザ ID に対応するデータがあるか
// チェックする為、件数をカウントする
String SE_SQL = "SELECT COUNT(*) FROM WORKSHOP1 WHERE USERID=?";
stmt = dbConn.prepareStatement(SE_SQL);
stmt.setString(1, request.getRemoteUser());
rs = stmt.executeQuery();
※'?'は自ユーザーID です。
¾
登録されていなければ、テーブルに挿入します。
String IN_SQL = "INSERT INTO WORKSHOP1(USERID,URL,WIDTH,HEIGHT) VALUES(?,?,?,?)";
// ステートメントに設定するパラメータはユーザ ID、URL、ウインドウ幅、ウインドウ高さ
stmt = dbConn.prepareStatement(IN_SQL);
stmt.setString(1, request.getRemoteUser());
stmt.setString(2, request.getParameter(EDIT_URL));
stmt.setString(3, request.getParameter(EDIT_WIDTH));
stmt.setString(4, request.getParameter(EDIT_HEIGHT));
// ステートメント実行
stmt.executeUpdate();
¾
登録されている場合は、テーブルを更新します
String UP_SQL = "UPDATE WORKSHOP1 SET URL=?,WIDTH=?,HEIGHT=? WHERE USERID=?";
stmt = dbConn.prepareStatement(UP_SQL);
stmt.setString(1, request.getParameter(EDIT_URL));
stmt.setString(2, request.getParameter(EDIT_WIDTH));
stmt.setString(3, request.getParameter(EDIT_HEIGHT));
stmt.setString(4, request.getRemoteUser());
70
IBM Japan Systems Engineering
// ステートメント実行
stmt.executeUpdate();
¾
ステートメント、コネクションのクローズを忘れずに実行してください。
6.10 Derby Sample Connection の切断
このポートレットを RAD から実行する際、以下のような確認画面が表示されることがあり
ます。そのまま、「終了」ボタンを押下します。引き続きサーバーの実行が開始します。
6.11 解答例
<< Lesson5Portlet.java >>
package com.ibm.lesson5;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
71
IBM Japan Systems Engineering
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.sql.DataSource;
/**
* A sample portlet based on GenericPortlet
*/
public class Lesson5Portlet extends GenericPortlet {
public static final String VIEW_JSP
= "/_Lesson5/jsp/html/Lesson5PortletVie
w.jsp";
public static final String EDIT_JSP
= "/_Lesson5/jsp/html/Lesson5PortletEdi
t.jsp";
public static final String SESSION_BEAN = "Lesson5PortletSessionBean";
public static final String EDIT_SUBMIT
public static final String EDIT_URL
= "Lesson5PortletEditSubmit";
= "Lesson5PortletEditUrl";
public static final String EDIT_WIDTH
= "Lesson5PortletEditWidth";
public static final String EDIT_HEIGHT
= "Lesson5PortletEditHeight";
public static final String DB_NAME
= "db.name";
public static final String DB_USER
= "db.user";
public static final String DB_PASSWORD = "db.pass";
private DataSource db_datasource = null;
private String db_user = "";
private String db_password = "";
public void init() throws PortletException{
super.init();
72
IBM Japan Systems Engineering
try {
// 初期コンテキストの構築
Context ctx = new InitialContext();
db_datasource = (DataSource)ctx.lookup("java:comp/env/jdbc/res" + getPo
rtletConfig().getInitParameter(DB_NAME));
// 初期パラメータより DB 接続ユーザ名を取得
db_user = getPortletConfig().getInitParameter(DB_USER);
// 初期パラメータより DB 接続ユーザのパスワードを取得
db_password = getPortletConfig().getInitParameter(DB_PASSWORD);
} catch(NamingException e) {
e.printStackTrace();
}
}
public void doView(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
Connection dbConn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
// WORKSHOP1 テーブルから URL、ウインドウ幅、ウインドウ高さを取り出す
// 条件は、現在ログインしているユーザ ID と、テーブル内の USERID が一致する事
String SE_SQL = "SELECT URL, WIDTH, HEIGHT FROM WORKSHOP1 WHERE USERID=?";
// Check if portlet session exists
Lesson5PortletSessionBean sessionBean = getSessionBean(request);
if( sessionBean==null ) {
response.getWriter().println("<b>NO PORTLET SESSION YET</b>");
return;
}
73
IBM Japan Systems Engineering
try {
// DB コネクションを取得
dbConn = getConn();
// ステートメントオブジェクトの作成とユーザ ID をステートメントに設定
stmt = dbConn.prepareStatement(SE_SQL);
stmt.setString(1, request.getRemoteUser());
// SQL の実行
rs = stmt.executeQuery();
if(rs.next()) {
// URL を取得し、Bean へ設定
sessionBean.setSrcURL(rs.getString("URL"));
// 幅を取得し、Bean へ設定
sessionBean.setWidth(rs.getString("WIDTH"));
// 高さを取得し、Bean へ設定
sessionBean.setHeight(rs.getString("HEIGHT"));
}
} catch(SQLException e) {
e.printStackTrace();
} finally {
if(stmt != null) {
// ステートメントのクローズ
try {
stmt.close();
} catch(Exception e) {}
}
if(dbConn != null) {
// コネクションのクローズ
try {
closeConn(dbConn);
} catch(Exception e) {}
}
}
74
IBM Japan Systems Engineering
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(VIEW_
JSP);
rd.include(request,response);
}
public void doEdit(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
Connection dbConn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
// WORKSHOP1 テーブルから URL、ウインドウ幅、ウインドウ高さを取り出す
// 条件は、現在ログインしているユーザ ID と、テーブル内の USERID が一致する事
String SE_SQL = "SELECT URL, WIDTH, HEIGHT FROM WORKSHOP1 WHERE USERID=?";
// Check if portlet session exists
Lesson5PortletSessionBean sessionBean = getSessionBean(request);
if( sessionBean==null ) {
response.getWriter().println("<b>NO PORTLET SESSION YET</b>");
return;
}
try {
// DB コネクションを取得
dbConn = getConn();
// ステートメントオブジェクトの作成とユーザ ID をステートメントに設定
stmt = dbConn.prepareStatement(SE_SQL);
stmt.setString(1, request.getRemoteUser());
// SQL の実行
75
IBM Japan Systems Engineering
rs = stmt.executeQuery();
if(rs.next()) {
// URL を取得し、Bean へ設定
sessionBean.setSrcURL(rs.getString("URL"));
// 幅を取得し、Bean へ設定
sessionBean.setWidth(rs.getString("WIDTH"));
// 高さを取得し、Bean へ設定
sessionBean.setHeight(rs.getString("HEIGHT"));
} else {
sessionBean.setSrcURL("");
sessionBean.setWidth("");
sessionBean.setHeight("");
}
} catch(SQLException e) {
e.printStackTrace();
} finally {
if(stmt != null) {
// ステートメントのクローズ
try {
stmt.close();
} catch(Exception e) {}
}
if(dbConn != null) {
// コネクションのクローズ
try {
closeConn(dbConn);
} catch(Exception e) {}
}
}
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(EDIT_
JSP);
rd.include(request,response);
76
IBM Japan Systems Engineering
}
public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
if( request.getParameter(EDIT_SUBMIT) != null ) {
Connection dbConn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
// WORKSHOP1 テーブルから、現在ログインしているユーザ ID に対応するデータ
があるかチェックする為、件数をカウントする
String SE_SQL = "SELECT COUNT(*) FROM WORKSHOP1 WHERE USERID=?";
// 新規登録
String IN_SQL = "INSERT INTO WORKSHOP1(USERID,URL,WIDTH,HEIGHT) VALUES
(?,?,?,?)";
// データ更新
// 条件は、現在ログインしているユーザ ID と、テーブル内の USERID が一致する
事
String UP_SQL = "UPDATE WORKSHOP1 SET URL=?,WIDTH=?,HEIGHT=? WHERE USERI
D=?";
try {
String sParam = request.getParameter(EDIT_URL);
if(sParam != null && !sParam.equals("" )) {
dbConn = getConn();
stmt = dbConn.prepareStatement(SE_SQL);
stmt.setString(1, request.getRemoteUser());
rs = stmt.executeQuery();
rs.next();
int count = rs.getInt(1);
// ステートメント、リザルトセットのクローズ
if(stmt != null) stmt.close();
77
IBM Japan Systems Engineering
if(rs != null) rs.close();
if(count == 0) {
// 新規にテーブルに書き込む
// ユーザが入力したパラメータを取り出し、ステートメントに設
定
// ステートメントに設定するパラメータはユーザ ID、URL、ウイン
ドウ幅、ウインドウ高さ
stmt = dbConn.prepareStatement(IN_SQL);
stmt.setString(1, request.getRemoteUser());
stmt.setString(2, request.getParameter(EDIT_URL));
stmt.setString(3, request.getParameter(EDIT_WIDTH));
stmt.setString(4, request.getParameter(EDIT_HEIGHT));
} else {
// 既に存在するので更新する
stmt = dbConn.prepareStatement(UP_SQL);
stmt.setString(1, request.getParameter(EDIT_URL));
stmt.setString(2, request.getParameter(EDIT_WIDTH));
stmt.setString(3, request.getParameter(EDIT_HEIGHT));
stmt.setString(4, request.getRemoteUser());
}
// ステートメント実行
stmt.executeUpdate();
}
} catch(SQLException e) {
e.printStackTrace();
} finally {
if(stmt != null) {
// ステートメントのクローズ
try {
stmt.close();
} catch(Exception e) {e.printStackTrace();}
}
if(dbConn != null) {
// コネクションのクローズ
78
IBM Japan Systems Engineering
try {
closeConn(dbConn);
} catch(Exception e) {e.printStackTrace();}
}
}
}
}
private static Lesson5PortletSessionBean getSessionBean(PortletRequest request)
{
PortletSession session = request.getPortletSession();
if( session == null )
return null;
Lesson5PortletSessionBean sessionBean = (Lesson5PortletSessionBean)session.g
etAttribute(SESSION_BEAN);
if( sessionBean == null ) {
sessionBean = new Lesson5PortletSessionBean();
session.setAttribute(SESSION_BEAN,sessionBean);
}
return sessionBean;
}
/*
* コネクションの取得処理
*/
private Connection getConn() throws SQLException {
Connection conn =
db_datasource.getConnection(db_user, db_password);
return(conn);
}
/*
* コネクションのクローズ処理
*/
private void closeConn(Connection conn) throws SQLException {
conn.close();
}
79
IBM Japan Systems Engineering
}
<< Lesson5PortletSessionBean.java >>
package com.ibm.lesson5;
/**
*
* A sample Java bean that stores portlet instance data in portlet session.
*
*/
public class Lesson5PortletSessionBean {
private String srcURL;
private String height;
private String width;
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public String getSrcURL() {
return srcURL;
}
public void setSrcURL(String srcURL) {
this.srcURL = srcURL;
}
public String getWidth() {
return width;
}
80
IBM Japan Systems Engineering
public void setWidth(String width) {
this.width = width;
}
}
<< Lesson5PortletView.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="com.
ibm.lesson5.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<%
Lesson5PortletSessionBean sessionBean = (Lesson5PortletSessionBean)renderReques
t.getPortletSession().getAttribute(com.ibm.lesson5.Lesson5Portlet.SESSION_BEAN);
String sUrl = sessionBean.getSrcURL();
String sWidth = sessionBean.getWidth();
String sHeight = sessionBean.getHeight();
if(sUrl == null){
sUrl = "";
}
if(sWidth == null){
sWidth = "";
}
if(sHeight == null){
sHeight = "";
}
if(!sUrl.equals("")) {
%>
<DIV style="margin: 6px">
<IFRAME src="<%=sUrl%>" WIDTH="<%=sWidth%>" HEIGHT="<%=sHeight%>">
81
IBM Japan Systems Engineering
<BR><H2>ifram 非対応ブラウザの為、表示出来ません</H2><BR>
</IFRAME>
<%
} else { %>
表示するサイトを登録して下さい。
<%
} %>
</DIV>
<< Lesson5PortletEdit.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="com.
ibm.lesson5.*"%>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<%
Lesson5PortletSessionBean sessionBean = (Lesson5PortletSessionBean)renderReques
t.getPortletSession().getAttribute(Lesson5Portlet.SESSION_BEAN);
String sUrl = sessionBean.getSrcURL();
String sWidth = sessionBean.getWidth();
String sHeight = sessionBean.getHeight();
if(sUrl == null){
sUrl = "";
}
if(sWidth == null){
sWidth = "";
}
if(sHeight == null){
sHeight = "";
}
%>
<DIV style="margin: 6px">
<DIV style="margin: 12px; margin-bottom: 36px">
82
IBM Japan Systems Engineering
<FORM ACTION="<portlet:actionURL/>" METHOD="POST">
<TABLE class="Portlet" width="100%" border="0" cellspacing="0" cellpadding="0">
<TR><TD><B>サイトを指定して下さい。<BR></B></TD></TR>
<TR><TD width="100%" align="left">URL:<BR></TD></TR>
<TR><TD width="100%" align="left">
<INPUT TYPE="text" NAME="<%=Lesson5Portlet.EDIT_URL%>" SIZE="50" value="<%=s
Url%>"><BR>
</TD></TR>
<TR><TD width="100%" align="left">ウィンドウ幅:<BR></TD></TR>
<TR><TD width="100%" align="left">
<INPUT TYPE="text" NAME="<%=Lesson5Portlet.EDIT_WIDTH%>" SIZE="5" value="<%=
sWidth%>"><BR>
</TD></TR>
<TR><TD width="100%" align="left">ウィンドウ高さ:<BR></TD></TR>
<TR><TD width="100%" align="left">
<INPUT TYPE="text" NAME="<%=Lesson5Portlet.EDIT_HEIGHT%>" SIZE="5" value="<%
=sHeight%>"><BR>
</TD></TR>
<TR><TD>
<BR>
<INPUT name="<%=Lesson5Portlet.EDIT_SUBMIT%>" value="保管" type="submit"/>
</TD></TR>
</TABLE>
</FORM>
<hr/>
<FORM ACTION='<portlet:renderURL portletMode="view"/>' METHOD="POST">
<INPUT NAME="back" TYPE="submit" VALUE="表示モードに戻る">
</FORM>
</DIV>
</DIV>
<< portlet.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" version="
83
IBM Japan Systems Engineering
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/p
ortlet-app_1_0.xsd" id="com.ibm.lesson5.Lesson5Portlet.aed25f5011">
<portlet>
<portlet-name>Lesson5</portlet-name>
<display-name>Lesson5</display-name>
<display-name xml:lang="ja">Lesson5</display-name>
<portlet-class>com.ibm.lesson5.Lesson5Portlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<init-param>
<name>db.name</name>
<value>TESTDB</value>
</init-param>
<init-param>
<name>db.user</name>
<value>db2admin</value>
</init-param>
<init-param>
<name>db.pass</name>
<value>pass</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
</supports>
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson5.nl.Lesson5PortletResource</resource-bundle>
<portlet-info>
<title>Lesson5</title>
<short-title>Lesson5</short-title>
<keywords>Lesson5</keywords>
84
IBM Japan Systems Engineering
</portlet-info>
</portlet>
</portlet-app>
<< web.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:x
si="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.co
m/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>
Lesson5</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
</jsp-config>
<resource-ref id="ResourceRef_1172653021890">
<description>
</description>
<res-ref-name>jdbc/resTESTDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Unshareable</res-sharing-scope>
</resource-ref>
</web-app>
85
IBM Japan Systems Engineering
<< ibm-web-bnd.xmi >>
<?xml version="1.0" encoding="UTF-8"?>
<webappbnd:WebAppBinding xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:w
ebappbnd="webappbnd.xmi" xmi:id="WebAppBinding_1172626025672" virtualHostName="defaul
t_host">
<webapp href="WEB-INF/web.xml#WebApp_ID"/>
<resRefBindings xmi:id="ResourceRefBinding_1172653021890" jndiName="jdbc/TESTDB">
<bindingResourceRef href="WEB-INF/web.xml#ResourceRef_1172653021890"/>
</resRefBindings>
</webappbnd:WebAppBinding>
<< ibm-web-ext.xmi >>
<?xml version="1.0" encoding="UTF-8"?>
<webappext:WebAppExtension xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmln
s:webappext="webappext.xmi" xmi:id="WebAppExtension_1172626025672" reloadInterval="3"
reloadingEnabled="true" additionalClassPath="" fileServingEnabled="true" directoryBr
owsingEnabled="false" serveServletsByClassnameEnabled="true">
<webApp href="WEB-INF/web.xml#WebApp_ID"/>
</webappext:WebAppExtension>
86
IBM Japan Systems Engineering
7
[演習6]カスタム(Custom)モードを使うポートレット
ポートレットモードには、表示モード、編集モード、HELP モードの 3 種類の他に、オプショ
ナルのモードとして、「カスタムモード」が存在します。この演習では、カスタムモードの
1 つである編集共用設定(edit_defaults)モードと構成(config)モードを作成します。
[目的]
z
カスタムモードの定義
z
カスタムモードの切替
[イメージ画像]
・表示モード
・編集共用設定(edit_defaults)モード
87
IBM Japan Systems Engineering
・構成(config)モード
7.1
プロジェクトの情報
プロジェクト名
Lesson6
エンタープライズ・アプリケーション・プロジェクト名
Lesson6EAR
ポートレット名
Lesson6
表示名
Lesson6
ポートレット・クラス
com.ibm.lesson6.Lesson6Portlet
7.2
カスタムモードの種類
JSR168 の仕様として、カスタムモードは以下の 5 種類を定義しています。
¾
About
¾
Config
¾
Edit_defaults
¾
Preview
¾
Print
現在 WebSphere Portal でサポートするのは Config モードと Edit_defaults モードのみで
す。
7.3
編集共用設定(edit_defaults)モード
編集(edit)モードと編集共用設定(edit_defaults)モードの違いについて説明します。
編集(edit)モードにおける PortletPreferences への書き込みは、あるページの 1 つのポー
トレットのインスタンスにアクセスしているそのユーザーのみに適用されます。
88
IBM Japan Systems Engineering
編集共用設定(edit_defaults)モードにおける PortletPreferences への書き込みは、1 つの
ページの 1 つのポートレットの特定のインスタンスに影響し、そのページのポートレット
のインスタンスを表示するすべてのユーザーに適用されます。
つまり、ページに配置したあるポートレットに対して、ユーザー毎にデータを保持したい
場合は、編集モードを使い、全ユーザーで共通のデータを保持したい場合は、編集共用設
定モードを使うということになります。
7.4
構成(config)モード
構成(config)モードにおける PortletPreferences への書き込みは、すべてのユーザーのす
べてのページのすべてのポートレットに影響します。また、PortletPreferences における
読み取り専用(read only)データの場合でも、更新することが可能です。
つまり、ページに同じポートレットを複数配置しても、同じデータを使います。基本的に
管理者(アドミニストレーター)が実行するモードです。
7.5
カスタムモードの定義
ポートレット・デプロイメント記述子(portlet.xml)において、新規ポートレット・モード
config と edit_defaults を宣言します。
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>config</portlet-mode>
<portlet-mode>edit_defaults</portlet-mode>
</supports>
また、ポートレット・デプロイメント記述子(portlet.xml)内の最後の<portlet>タグの後
に、新規モードをカスタム・ポートレット・モードとして宣言する必要があります。
・・・・・(省略)
</portlet>
<custom-portlet-mode>
<portlet-mode>config</portlet-mode>
</custom-portlet-mode>
<custom-portlet-mode>
<portlet-mode>edit_defaults</portlet-mode>
89
IBM Japan Systems Engineering
</custom-portlet-mode>
</portlet-app>
ポートレットクラス(Lesson6Portlet.java)のフィールド変数として、新規モードのオブ
ジェクトを作成します。
public class Lesson6Portlet extends GenericPortlet {
・・・・・(省略)
private static final PortletMode CUSTOM_CONFIG_MODE = new PortletMode("config");
private static final PortletMode CUSTOM_EDIT_DEFAULTS_MODE = new PortletMode("ed
it_defaults");
・・・・・(省略)
カスタムモードの切替
7.6
ポートレットクラス(Lesson6Portlet.java)において、doDispatch メソッドを実装します。
このメソッド内で、切り替えるポートレットモードを取得して、適切な各モード用メソッ
ドを呼び出します。このメソッドの最後に必ず、親クラス(GenericPortlet)の doDispatch
メソッドを呼ぶ必要があります。つまり、Lesson6Portlet において、カスタムモードの判
定を行い、GenericPortlet において、標準モード(表示モード、編集モード、HELP モード)
の判定を行っている訳です。
以下の例では、構成モードの場合には、doCustomConfigure メソッドを呼び、編集共用設定
モードの場合には、doCustomEditDefaults メソッドを呼んでいます。doCustomConfigure
メソッドと doCustomEditDefaults メソッドは、他のモードと同様に、任意の処理を実装し
ます。
protected void doDispatch(RenderRequest request, RenderResponse response) throws Por
tletException, IOException {
if (!WindowState.MINIMIZED.equals(request.getWindowState())){
PortletMode mode = request.getPortletMode();
if (CUSTOM_CONFIG_MODE.equals(mode)) {
doCustomConfigure(request, response);
return;
}
else if (CUSTOM_EDIT_DEFAULTS_MODE.equals(mode)) {
doCustomEditDefaults(request, response);
return;
}
90
IBM Japan Systems Engineering
}
super.doDispatch(request, response);
}
protected void doCustomConfigure(RenderRequest request, RenderResponse response) thr
ows PortletException, IOException {
・・・・・(省略)
}
protected void doCustomEditDefaults(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
・・・・・(省略)
}
7.7
カスタムモードで読み書きするデータの初期値
カスタムモードで読み書きするデータに初期値を設定しておく為、ポートレット・デプロ
イメント記述子(portlet.xml)にあらかじめ値を定義しておきます(初期値を設定する必要
がなければ、定義する必要はありません)。また、構成モードで使用するデータは読み取り
専用(read only)にして下さい。こうしておけば、構成モード以外でデータが更新されるこ
とはありません。
・・・・・(省略)
<portlet-preferences>
<preference>
<name>ConfigKey</name>
構成モード用
<value>config data</value>
<read-only>true</read-only>
</preference>
<preference>
<name>EditDefaultsKey</name>
編集共用設定モード用
<value>editdefaults data</value>
</preference>
</portlet-preferences>
</portlet>
・・・・・(省略)
91
IBM Japan Systems Engineering
7.8
カスタムモードの PortletURL
JSP タグで使用できる PortletURL のパラメータはカスタムモードとして定義した文字列
です。
<portlet:renderURL portletMode="edit_defaults"/>
//編集共用設定モード
<portlet:renderURL portletMode="config"/>
//構成モード
7.9
解答例
<< Lesson6Portlet.java >>
package com.ibm.lesson6;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.ReadOnlyException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ValidatorException;
import javax.portlet.WindowState;
/**
* A sample portlet based on GenericPortlet
*/
public class Lesson6Portlet extends GenericPortlet {
public static final String VIEW_JSP
= "/_Lesson6/jsp/html/Lesson6PortletVie
w.jsp";
public static final String CONFIG_JSP
= "/_Lesson6/jsp/html/Lesson6PortletCon
fig.jsp";
public static final String EDIT_DEFAULTS_JSP
= "/_Lesson6/jsp/html/Lesson6Por
tletEditDefaults.jsp";
public static final String CONFIG_SUBMIT = "Lesson6PortletConfigSubmit";
92
IBM Japan Systems Engineering
public static final String CONFIG_TEXT
= "Lesson6PortletConfigText";
public static final String CONFIG_KEY
= "ConfigKey";
public static final String EDIT_DEFAULTS_SUBMIT = "Lesson6PortletEditDefaultsSub
mit";
public static final String EDIT_DEFAULTS_TEXT
= "Lesson6PortletEditDefaultsTex
public static final String EDIT_DEFAULTS_KEY
= "EditDefaultsKey";
t";
private static final PortletMode CUSTOM_CONFIG_MODE = new PortletMode("config");
private static final PortletMode CUSTOM_EDIT_DEFAULTS_MODE = new PortletMode("ed
it_defaults");
public void init() throws PortletException{
super.init();
}
public void doView(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(VIEW_
JSP);
rd.include(request,response);
}
protected void doCustomConfigure(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(CONFI
G_JSP);
rd.include(request,response);
93
IBM Japan Systems Engineering
}
protected void doCustomEditDefaults(RenderRequest request, RenderResponse respon
se) throws PortletException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(EDIT_
DEFAULTS_JSP);
rd.include(request,response);
}
protected void doDispatch(RenderRequest request, RenderResponse response) throws
PortletException, IOException {
if (!WindowState.MINIMIZED.equals(request.getWindowState())){
PortletMode mode = request.getPortletMode();
if (CUSTOM_CONFIG_MODE.equals(mode)) {
doCustomConfigure(request, response);
return;
}
else if (CUSTOM_EDIT_DEFAULTS_MODE.equals(mode)) {
doCustomEditDefaults(request, response);
return;
}
}
super.doDispatch(request, response);
}
public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
if( request.getParameter(CONFIG_SUBMIT) != null ) {
PortletPreferences prefs = request.getPreferences();
try {
prefs.setValue(CONFIG_KEY,request.getParameter(CONFIG_TEXT));
prefs.store();
94
IBM Japan Systems Engineering
}
catch( ReadOnlyException roe ) {
}
catch( ValidatorException ve ) {
}
}
if( request.getParameter(EDIT_DEFAULTS_SUBMIT) != null ) {
PortletPreferences prefs = request.getPreferences();
try {
prefs.setValue(EDIT_DEFAULTS_KEY,request.getParameter(EDIT_DEFAULTS_
TEXT));
prefs.store();
}
catch( ReadOnlyException roe ) {
}
catch( ValidatorException ve ) {
}
}
}
}
<< Lesson6PortletView.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="java
x.portlet.*,com.ibm.lesson6.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<DIV style="margin: 6px">
<H3 style="margin-bottom: 3px">表示モード</H3>
<BR>
<%
PortletPreferences preferences = renderRequest.getPreferences();
if( preferences!=null ) {
95
IBM Japan Systems Engineering
String config_value = (String)preferences.getValue(Lesson6Portlet.CONFIG_KEY,"");
String edit_defaults_value = (String)preferences.getValue(Lesson6Portlet.EDIT_DEF
AULTS_KEY,"");
%>
編集共用設定モードで保存した値:<%=edit_defaults_value%><BR><BR>
構成モードで保存した値:<%=config_value%><BR><BR>
<%
}
else {
%>エラー: ポートレット設定は NULL です。<%
}
%>
<FORM ACTION='<portlet:renderURL portletMode="edit_defaults"/>' METHOD="POST">
<INPUT NAME="edit_defaults" TYPE="submit" VALUE="編集共用設定モードにする">
</FORM>
<FORM ACTION='<portlet:renderURL portletMode="config"/>' METHOD="POST">
<INPUT NAME="config" TYPE="submit" VALUE="構成モードにする">
</FORM>
</DIV>
<< Lesson6PortletConfig.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="java
x.portlet.*,com.ibm.lesson6.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<DIV style="margin: 6px">
<H3 style="margin-bottom: 3px">構成モード</H3>
ポートレットが 構成モード に入っている時のポートレット設定を変更する方法のデモ用サン
プル書式です。
<DIV style="margin: 12px; margin-bottom: 36px">
<%
96
IBM Japan Systems Engineering
PortletPreferences preferences = renderRequest.getPreferences();
if( preferences!=null ) {
String value = (String)preferences.getValue(Lesson6Portlet.CONFIG_KEY,"");
%>
<FORM ACTION="<portlet:actionURL/>" METHOD="POST">
<LABEL for="<%=Lesson6Portlet.CONFIG_TEXT%>">新規の値</LABEL><BR>
<INPUT name="<%=Lesson6Portlet.CONFIG_TEXT%>" value="<%=value%>" type="text"/><BR
>
<INPUT name="<%=Lesson6Portlet.CONFIG_SUBMIT%>" value="保管" type="submit"/>
</FORM>
<%
}
else {
%>エラー: ポートレット設定は NULL です。<%
}
%>
</DIV>
<FORM ACTION='<portlet:renderURL portletMode="view"/>' METHOD="POST">
<INPUT NAME="back" TYPE="submit" VALUE="表示モードに戻る">
</FORM>
</DIV>
<< Lesson6PortletEditDefaults.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="java
x.portlet.*,com.ibm.lesson6.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<DIV style="margin: 6px">
<H3 style="margin-bottom: 3px">編集共用設定モード</H3>
ポートレットが 編集共用設定モード に入っている時のポートレット設定を変更する方法のデ
モ用サンプル書式です。
変更を確認するには、一度ログ・アウトしてから別のユーザーとして再度ログインしてください。
97
IBM Japan Systems Engineering
<DIV style="margin: 12px; margin-bottom: 36px">
<%
PortletPreferences preferences = renderRequest.getPreferences();
if (preferences != null) {
String value = (String)preferences.getValue(Lesson6Portlet.EDIT_DEFAULTS_KEY, "
");
%>
<FORM ACTION="<portlet:actionURL/>" METHOD="POST">
<LABEL for="<%=Lesson6Portlet.EDIT_DEFAULTS_TEXT%>">新規の値</LABEL><BR>
<INPUT name="<%=Lesson6Portlet.EDIT_DEFAULTS_TEXT%>" value="<%=value%>" type="tex
t"/><BR>
<INPUT name="<%=Lesson6Portlet.EDIT_DEFAULTS_SUBMIT%>" value="保管" type="submit"
/>
</FORM>
<%
} else {
%>エラー: ポートレット設定は NULL です。<%
}
%>
</DIV>
<FORM ACTION='<portlet:renderURL portletMode="view"/>' METHOD="POST">
<INPUT NAME="back" TYPE="submit" VALUE="表示モードに戻る">
</FORM>
</DIV>
<< portlet.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<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/p
ortlet-app_1_0.xsd" id="com.ibm.lesson6.Lesson6Portlet.0fdeb76211">
<portlet>
<portlet-name>Lesson6</portlet-name>
<display-name>Lesson6</display-name>
98
IBM Japan Systems Engineering
<display-name xml:lang="ja">Lesson6</display-name>
<portlet-class>com.ibm.lesson6.Lesson6Portlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>config</portlet-mode>
<portlet-mode>edit_defaults</portlet-mode>
</supports>
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson6.nl.Lesson6PortletResource</resource-bundle>
<portlet-info>
<title>Lesson6</title>
<short-title>Lesson6</short-title>
<keywords>Lesson6</keywords>
</portlet-info>
<portlet-preferences>
<preference>
<name>ConfigKey</name>
<value>config data</value>
<read-only>true</read-only>
</preference>
<preference>
<name>EditDefaultsKey</name>
<value>editdefaults data</value>
</preference>
</portlet-preferences>
</portlet>
<custom-portlet-mode>
<portlet-mode>config</portlet-mode>
</custom-portlet-mode>
<custom-portlet-mode>
99
IBM Japan Systems Engineering
<portlet-mode>edit_defaults</portlet-mode>
</custom-portlet-mode>
</portlet-app>
<< web.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:x
si="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.co
m/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>
Lesson6</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
100
IBM Japan Systems Engineering
8
[演習7]サーブレット連携
ポートレットから、サーブレットを呼び出します。その際、セッションを使って情報の受
け渡しを行います。これは、サーブレットが直接呼ばれたか、もしくは、ポートレット経
由で呼ばれたかを判定する為です。
[目的]
z
ポートレットセッションにおけるスコープの設定
z
セッション情報の属性名におけるネーミングルールの理解
z
サーブレット側でセッション情報を取得
[イメージ画像]
・呼び出し元:ポートレット
・呼び出し先:サーブレット
101
IBM Japan Systems Engineering
8.1
プロジェクトの情報
プロジェクト名
Lesson7
エンタープライズ・アプリケーション・プロジェクト名
Lesson7EAR
ポートレット名
Lesson7
表示名
Lesson7
ポートレット・クラス
com.ibm.lesson7.Lesson6Portlet
8.2
ポートレットセッションのスコープ
ポ ー ト レ ッ ト セ ッ シ ョ ン の 有 効 範 囲 を 示 す ス コ ー プ に は 、 PORTLET_SCOPE と
APPLICATION_SCOPE の 2 種類定義されています。
【ポートレットセッションのスコープ】
¾
PORTLET_SCOPE
対象ポートレットインスタンスの中でのみセッション情報が有効
¾
APPLICATION_SCOPE
他のアプリケーションとセッション情報を共有
PortletSession オブジェクトの setAttribute メソッドの第 3 引数で、スコープを指定しま
す。スコープの指定は省略することも可能で、その場合、PORTLET_SCOPE を指定したことに
なります。
PortletSession session = request.getPortletSession();
String url = "http://www.foo.com";
session.setAttribute("data1.url", url, PortletSession.PORTLET_SCOPE);
session.setAttribute("data2.url", url, PortletSession.APPLICATION_SCOPE);
スコープが PORTLET_SCOPE の場合、セッション情報の属性名(Attribute Name)にインスタン
スオブジェクトを識別する文字列が付加されます。インスタンスオブジェクトを識別する
文字列書式は以下の通りです。
javax.portlet.p.<オブジェクト ID>?<属性名>
先程の例で説明すると、Java コードを、
session.setAttribute("data1.url", url, PortletSession.PORTLET_SCOPE);
と記述し、該当ポートレットのオブジェクト ID が"7_8000CB1A0G00002HCGPG1U10G1"であっ
たとすると、属性名は、
javax.portlet.p.7_8000CB1A0G00002HCGPG1U10G1?data1.url
102
IBM Japan Systems Engineering
となります。
スコープが APPLICATION_SCOPE の場合は、付加する文字列は一切ありません。先程の例で
説明すると、Java コードを、
session.setAttribute("data2.url", url, PortletSession.APPLICATION_SCOPE);
と記述した場合の属性名は、
data2.url
となります。
以下のように、文字列だけでなく、他のオブジェクト(この場合は SessionTestBean)もセッ
ト出来ます。
PortletSession session = request.getPortletSession();
SessionTestBean sessionBean = new SessionTestBean();
session.setAttribute(SESSION_BEAN_PORTLET_SCOPE, sessionBean, PortletSession.PORTLET
_SCOPE);
8.3
スコープの使い分け
一般に、セッション情報をセットしたポートレット内だけでセッション情報を使用する場
合、スコープ PORTLET_SCOPE を使います。ポートレット内でセッション情報を取得する際、
PortletSession オブジェクトの getAttribute メソッドを使用しますが、getAttribute メ
ソッドは、セッションの属性名に、ポートレットのオブジェクト ID を自動的に付加して検
索しています。ゆえにスコープ PORTLET_SCOPE を使う必要がある訳です。
しかし、スコープ PORTLET_SCOPE において、サーブレットとセッション情報を共有する場
合、属性名(正確にはオブジェクト ID)が不明の為、そのままでは使用できません。そこ
でセッション情報を共有する方法として 2 種類考えられます。
一つは、スコープ APPLICATION_SCOPE を使用する方法です。しかし、この方法は、ページ
に同じポートレットを複数配置すると、セッション情報をお互いに上書きしてしまいます。
上書きしても問題ないアプリケーションであれば大丈夫ですが、呼び出し元のポートレッ
ト毎にセッション情報を保持したい場合には、利用できません。
もう一つの方法は、スコープ PORTLET_SCOPE を使い、サーブレットにオブジェクト ID を引
数として渡します。属性名にはポートレットのオブジェクト ID が付加されているので、サー
ブレット側で、オブジェクト ID が判明していれば、当然、正確な属性名が導けます。また、
呼び出し元のポートレット毎にセッション情報を保持出来ます。
103
IBM Japan Systems Engineering
8.4
オブジェクト ID の取得
前節で、スコープ PORTLET_SCOPE を使用する場合、ポートレットのオブジェクト ID が必要
であることを説明しました。そこで、そのオブジェクト ID を取得する方法を説明します。
各ポートレットインスタンスが一意に識別できるように、名前空間(ネームスペース)が
用意されています。名前空間は、RenderResponse オブジェクトの getNamespace メソッドで
取得できます。
※ネームスペース・エンコーディングとも言います。
名前空間は、"PC_x_yyyyy_"のような文字列を生成します。ここで、"x_yyyyy"にあたる部
分がオブジェクト ID です。つまり、名前空間の文字列を加工して、オブジェクト ID を抽
出します。
String val1 = response.getNamespace();
String NS_PREFIX = "PC_";
PC_7_8000CB1A0G00002HCGPG1U10G1_
String NS_SUFFIX = "_";
String oid = "";
if(val1.startsWith(NS_PREFIX) && val1.endsWith(NS_SUFFIX)){
oid = val1.substring(NS_PREFIX.length(), val1.length() - NS_SUFFIX.length());
7_8000CB1A0G00002HCGPG1U10G1
・・・・・(省略)
request.setAttribute(PARAM_OBJECTID, oid);
}
8.5
サーブレットの呼び出し
サーブレットを新規ブラウザで呼び出すように JSP に記述します。また、パラメータの引
数としてオブジェクト ID を指定します。
・Lesson7PortletView.jsp
<%
String oid = (String)renderRequest.getAttribute(Lesson7Portlet.PARAM_OBJECTID);
String url = renderResponse.encodeURL(renderRequest.getContextPath() + "/Session
TestServlet");
String param = "oid=" + oid;
%>
104
IBM Japan Systems Engineering
・・・・・(省略)
<a target="_blank" href="<%=url%>?<%=param%>">サーブレット呼び出し</a><BR><BR>
サーブレットを"/SessionTestServlet"で呼べるように、デプロイメント記述子(web.xml)
にサーブレットを登録します。
・web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>
Lesson7</display-name>
<servlet>
<description>
</description>
<display-name>
SessionTestServlet</display-name>
<servlet-name>SessionTestServlet</servlet-name>
<servlet-class>
com.ibm.lesson7.SessionTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionTestServlet</servlet-name>
<url-pattern>/SessionTestServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
・・・・・(省略)
</web-app>
8.6
サーブレット側の対応
セッションは、HttpServletRequest オブジェクトの getSession メソッドで取得します。
getSession メソッドの引数には false を指定します。ポートレットからではなく、直接サー
ブレットが呼ばれた場合、セッションが生成されては困るからです。
HttpSession w_session = request.getSession(false);
ポートレットのオブジェクト ID は、HttpServletRequest オブジェクトの getParameter メ
105
IBM Japan Systems Engineering
ソッドで取得します。
String oid = (String)request.getParameter("oid");
セッション情報の属性名の一覧を取得すれば、PORTLET_SCOPE と APPLICATION_SCOPE におけ
る属性名の違いを見ることが出来ます。
//サーブレット
out.println("[セッションに保持している KEY 名の一覧]");
out.println("<br>");
Enumeration w_enum = w_session.getAttributeNames();
String key;
while(w_enum.hasMoreElements()){
key = (String)w_enum.nextElement();
out.println("KEY 名=" + key);
out.println("<br>");
}
out.println("<br>");
APPLICATION_SCOPE
//出力結果の例
PORTLET_SCOPE
[セッションに保持している KEY 名の一覧]
KEY 名=SessionTestBeanApplicationScope
KEY 名=javax.portlet.p.7_8000CB1A0G00002HCGPG1U10G1?SessionTestBeanPortletScope
スコープ PORTLET_SCOPE のセッション情報を取得する為、オブジェクト ID から属性名を生
成します。セッション情報は HttpSession オブジェクトの getAttribute メソッドで取得し
ます。
private static final String SESSION_BEAN_PORTLET_SCOPE = "SessionTestBeanPortletScope
";
private static final String PARAM_OBJECTID = "oid";
private static final String SESSION_PREFIX = "javax.portlet.p.";
・・・・・(省略)
String oid = (String)request.getParameter(PARAM_OBJECTID);
String keyname_s = SESSION_PREFIX + oid + "?" + SESSION_BEAN_PORTLET_SCOPE;
SessionTestBean bean_s = (SessionTestBean)w_session.getAttribute(keyname_s);
106
IBM Japan Systems Engineering
8.7
解答例
<< Lesson7Portlet.java >>
package com.ibm.lesson7;
import java.io.IOException;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
/**
* A sample portlet based on GenericPortlet
*/
public class Lesson7Portlet extends GenericPortlet {
public static final String VIEW_JSP
= "/_Lesson7/jsp/html/Lesson7PortletVie
w.jsp";
public static final String SESSION_BEAN_PORTLET_SCOPE
= "SessionTestBeanPort
letScope";
public static final String SESSION_BEAN_APPLICATION_SCOPE = "SessionTestBeanAppl
icationScope";
public static final String PARAM_OBJECTID = "oid";
public void init() throws PortletException{
super.init();
}
public void doView(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
//PortletScope 用
107
IBM Japan Systems Engineering
SessionTestBean bean_p = getSessionBeanPortletScope(request);
if( bean_p==null ) {
response.getWriter().println("<b>NO PORTLET SESSION YET</b>");
return;
}
//ApplicationScope 用
SessionTestBean bean_a = getSessionBeanApplicationScope(request);
if( bean_a==null ) {
response.getWriter().println("<b>NO PORTLET SESSION YET</b>");
return;
}
//ユーザーID 取得
String w_user = request.getRemoteUser();
if(w_user != null && !w_user.equals("")){
bean_p.setUserid(w_user);
bean_a.setUserid(w_user);
}
//PortletScope ではオブジェクト ID が必要になる
// ネームスペース: PC_x_yyyyy_
// オブジェクト ID: x_yyyyy
String val1 = response.getNamespace();
String NS_PREFIX = "PC_";
String NS_SUFFIX = "_";
String oid = "";
if(val1.startsWith(NS_PREFIX) && val1.endsWith(NS_SUFFIX)){
oid = val1.substring(NS_PREFIX.length(), val1.length() - NS_SUFFIX.leng
th());
request.setAttribute(PARAM_OBJECTID, oid);
}
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(VIEW_
JSP);
108
IBM Japan Systems Engineering
rd.include(request,response);
}
private static SessionTestBean getSessionBeanPortletScope(PortletRequest reques
t) {
PortletSession session = request.getPortletSession();
if( session == null )
return null;
SessionTestBean sessionBean = (SessionTestBean)session.getAttribute(SESSION_
BEAN_PORTLET_SCOPE);
if( sessionBean == null ) {
sessionBean = new SessionTestBean();
session.setAttribute(SESSION_BEAN_PORTLET_SCOPE, sessionBean, PortletSe
ssion.PORTLET_SCOPE);
}
return sessionBean;
}
private static SessionTestBean getSessionBeanApplicationScope(PortletRequest req
uest) {
PortletSession session = request.getPortletSession();
if( session == null )
return null;
SessionTestBean sessionBean = (SessionTestBean)session.getAttribute(SESSION_
BEAN_APPLICATION_SCOPE);
if( sessionBean == null ) {
sessionBean = new SessionTestBean();
session.setAttribute(SESSION_BEAN_APPLICATION_SCOPE, sessionBean, Portl
etSession.APPLICATION_SCOPE);
}
return sessionBean;
}
}
109
IBM Japan Systems Engineering
<< SessionTestBean.java >>
package com.ibm.lesson7;
public class SessionTestBean {
String userid = null;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
}
<< SessionTestServlet.java >>
package com.ibm.lesson7;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class for Servlet: SessionTestServlet
*
*/
public class SessionTestServlet extends HttpServlet {
110
IBM Japan Systems Engineering
private static final long serialVersionUID = 7757912924497945648L;
private static final String SESSION_BEAN_PORTLET_SCOPE
= "SessionTestBeanPort
letScope";
private static final String SESSION_BEAN_APPLICATION_SCOPE = "SessionTestBeanAppl
icationScope";
private static final String PARAM_OBJECTID = "oid";
private static final String SESSION_PREFIX = "javax.portlet.p.";
public SessionTestServlet() {
super();
}
public void init() throws ServletException {
super.init();
}
public void destroy() {
super.destroy();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) t
hrows ServletException, IOException {
execute(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
execute(request, response);
}
protected void execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=Shift_JIS");
PrintWriter out = response.getWriter();
111
IBM Japan Systems Engineering
out.println("<html>");
out.println("<head>");
out.println("<title>セッションテスト From ポートレット</title>");
out.println("<meta http-equiv=\"Pragma\" content=\"no-cache\">");
out.println("<meta http-equiv=\"Cache-Control\" content=\"no-cache\">");
out.println("<meta http-equiv=\"Expires\" content=\"-1\">");
out.println("</head>");
out.println("<body>");
HttpSession w_session = request.getSession(false);
if(w_session == null){
out.println("sessionId is null");
out.println("<br>");
out.println("</body>");
out.println("</html>");
return;
}
out.println("セッション ID=" + w_session.getId());
out.println("<br>");
String oid = (String)request.getParameter(PARAM_OBJECTID);
out.println("オブジェクト ID=" + oid);
out.println("<br>");
out.println("<br>");
out.println("[セッションに保持している KEY 名の一覧]");
out.println("<br>");
Enumeration w_enum = w_session.getAttributeNames();
String key;
while(w_enum.hasMoreElements()){
key = (String)w_enum.nextElement();
out.println("KEY 名=" + key);
out.println("<br>");
}
out.println("<br>");
112
IBM Japan Systems Engineering
String keyname_s = SESSION_PREFIX + oid + "?" + SESSION_BEAN_PORTLET_SCOPE;
SessionTestBean bean_s = (SessionTestBean)w_session.getAttribute(keyname_
s);
out.println("[PORTLET_SCOPE]");
out.println("<br>");
out.println("userid=" + bean_s.getUserid());
out.println("<br>");
out.println("<br>");
String keyname_a = SESSION_BEAN_APPLICATION_SCOPE;
SessionTestBean bean_a = (SessionTestBean)w_session.getAttribute(keyname_
a);
out.println("[APPLICATION_SCOPE]");
out.println("<br>");
out.println("userid=" + bean_a.getUserid());
out.println("<br>");
out.println("<br>");
out.println("</body>");
out.println("</html>");
}
}
<< Lesson7PortletView.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="com.
ibm.lesson7.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<%
String oid = (String)renderRequest.getAttribute(Lesson7Portlet.PARAM_OBJECTID);
String sid = renderRequest.getRequestedSessionId();
String url = renderResponse.encodeURL(renderRequest.getContextPath() + "/Session
TestServlet");
113
IBM Japan Systems Engineering
String param = Lesson7Portlet.PARAM_OBJECTID + "=" + oid;
%>
<DIV style="margin: 6px">
<H3 style="margin-bottom: 3px">表示モード</H3>
<BR>
ネームスペース=<portlet:namespace/>
<BR><BR>
オブジェクト ID=<%=oid%>
<BR><BR>
セッション ID=<%=sid%>
<BR><BR>
<a target="_blank" href="<%=url%>?<%=param%>">サーブレット呼び出し</a><BR><BR>
</DIV>
<< portlet.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<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/p
ortlet-app_1_0.xsd" id="com.ibm.lesson7.Lesson7Portlet.2d9473f211">
<portlet>
<portlet-name>Lesson7</portlet-name>
<display-name>Lesson7</display-name>
<display-name xml:lang="ja">Lesson7</display-name>
<portlet-class>com.ibm.lesson7.Lesson7Portlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
114
IBM Japan Systems Engineering
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson7.nl.Lesson7PortletResource</resource-bundle>
<portlet-info>
<title>Lesson7</title>
<short-title>Lesson7</short-title>
<keywords>Lesson7</keywords>
</portlet-info>
</portlet>
</portlet-app>
<< web.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:x
si="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.co
m/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>
Lesson7</display-name>
<servlet>
<description>
</description>
<display-name>
SessionTestServlet</display-name>
<servlet-name>SessionTestServlet</servlet-name>
<servlet-class>
com.ibm.lesson7.SessionTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionTestServlet</servlet-name>
<url-pattern>/SessionTestServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
115
IBM Japan Systems Engineering
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
116
IBM Japan Systems Engineering
9
[演習8]ユーザーおよびグループの管理
ポータル・ユーザー管理アーキテクチャー(PUMA)システム・プログラミング・インター
フェース(SPI)は、ポータルの User または Group のプロファイルにアクセスするためのイン
ターフェースを提供します。これらを用いて、属性をキーにしたユーザー検索を行います。
[目的]
z
Puma の概念を理解
z
Puma を用いたユーザー検索
[イメージ画像]
・属性を指定して検索
・検索結果を表示
117
IBM Japan Systems Engineering
9.1
プロジェクトの情報
プロジェクト名
Lesson8
エンタープライズ・アプリケーション・プロジェクト名
Lesson8EAR
ポートレット名
Lesson8
表示名
Lesson8
ポートレット・クラス
com.ibm.lesson8.Lesson6Portlet
9.2
Puma の概要
Puma は、ユーザーおよびグループの検索、作成、変更および削除に使用されます。また、
現在ログインしているユーザーに関するプロファイル情報も検索できます。SPI により戻さ
れ る User お よ び Group の 各 イ ン タ ー フ ェ ー ス は 、 SPI モ デ ル の
com.ibm.portal.Identifiable インターフェースから getObjectID メソッドを継承します。
このメソッドは、リソース(この場合、ポータルのユーザー・レジストリーのユーザーまた
はグループ)を一意的に識別する ObjectID の取得に使用されます。以下のプロバイダーの
オブジェクトが、User および Group の各オブジェクトへのアクセスに使用されます。
¾
PumaProfile
User および Group の各属性と ID へのアクセス(読み取り専用)を提供するメソッドが含まれ
ます。このインターフェースは、現行ユーザーの User オブジェクトの取得に使用されます。
¾
PumaLocator
User および Group の各オブジェクトの検索のためのメソッドが含まれます。このインター
フェースは、現行ユーザーがメンバーである、すべてのグループの Group オブジェクトの
List の取得に使用されます。
¾
PumaController
ユーザーおよびグループを作成したり削除したりするメソッド、User および Group の各プ
ロファイルとメンバーシップを変更するメソッドが含まれます。
9.3
ホーム・インターフェースの検索
ポートレットが上記のプロバイダー・オブジェクトを使用するには、事前に適切なホーム・
インターフェースをアプリケーションのタイプに応じて検索しておく必要があります。
¾
標準ポートレット
com.ibm.portal.um.portletservice.PumaHome
¾
IBM ポートレット
com.ibm.portal.um.portletservice.legacy.PumaHome
118
IBM Japan Systems Engineering
¾
ポータル・アプリケーション (テーマやスキンなど)
com.ibm.portal.um.PumaHome
Context オブジェクトの lookup メソッドを用いて、ホーム・インターフェースを取得しま
す。標準ポートレット用のホーム・インターフェースを取得する例を示します。
PortletServiceHome psh;
try{
javax.naming.Context ctx = new javax.naming.InitialContext();
psh = (PortletServiceHome)ctx.lookup("portletservice/com.ibm.portal.um.portletse
rvice.PumaHome");
if (psh != null){
PumaHome service = (PumaHome) psh.getPortletService(PumaHome.class);
・・・・・(省略)
}
} catch(NameNotFoundException e1) {
e1.printStackTrace();
・・・・・(省略)
} catch(NamingException e2) {
e2.printStackTrace();
・・・・・(省略)
}
※lookup に用いる JNDI 名は、"portletservice/" + 「パッケージ名」 + 「ホーム・イン
ターフェース名」です。
9.4
PumaProfile
ログインしているユーザーの基本情報を取得出来ます。PumaHome オブジェクトから、
PumaProfile オブジェクトを取得します。
getCurrentUser メソッドと getIdentifier メソッドを利用して、ログインユーザーの ID を
String として取得する例を示します。
//PortletServiceHome psh;
try{
if (psh != null){
PumaHome service = (PumaHome) psh.getPortletService(PumaHome.class);
PumaProfile pp = service.getProfile(request);
119
IBM Japan Systems Engineering
User user = pp.getCurrentUser();
String user_objid = pp.getIdentifier(user);
System.out.println(user_objid);
}
} catch (PumaException pe){
【中身の例】
pe.printStackTrace();
uid=wpsadmin,o=default organization
・・・・・(省略)
}
ポータルサーバーがユーザー用として定義している属性の名前一覧について、
getDefinedUserAttributeNames メソッド利用して、取得する例を示します。
//PortletServiceHome psh;
try{
if (psh != null){
PumaHome service = (PumaHome) psh.getPortletService(PumaHome.class);
PumaProfile pp = service.getProfile(request);
List user_attr_names = pp.getDefinedUserAttributeNames();
Iterator attr_iter = user_attr_names.iterator();
while(attr_iter.hasNext()){
System.out.println(attr_iter.next().toString());
【中身の例】
・・・・・(省略)
ibm-hobby
}
seeAlso
}
uid
} catch (PumaException pe){
cn
pe.printStackTrace();
・・・(省略)
・・・・・(省略)
}
getAttributes メソッド利用して、ログインユーザーに実際に定義している属性の名前と値
を取得する例を示します。
//PortletServiceHome psh;
try{
if (psh != null){
PumaHome service = (PumaHome) psh.getPortletService(PumaHome.class);
120
IBM Japan Systems Engineering
PumaProfile pp = service.getProfile(request);
User user1 = pp.getCurrentUser();
List list1 = pp.getDefinedUserAttributeNames();
【中身の例】
Map map1 = pp.getAttributes(user1, list1);
uid=wpsadmin
Object obj1;
cn=wpsadmin
Iterator iter1 = map1.keySet().iterator();
while(iter1.hasNext()){
obj1 = iter1.next();
System.out.println(obj1 + "=" + map1.get(obj1).toString());
}
}
} catch (PumaException pe){
pe.printStackTrace();
・・・・・(省略)
}
9.5
PumaLocator
ユーザーおよびグループの検索が出来ます。PumaHome オブジェクトから、PumaLocator オ
ブジェクトを取得します。
findUsersByAttribute メソッドを利用して、属性名と値をキーとしたユーザー検索を行う
例を示します。属性名には"uid"等を指定します。値には、ワイルドカード(*)が利用でき
ます。"wps*"の場合は、ID が wps から始まるユーザーを全て検索します。
//PortletServiceHome psh;
try{
if (psh != null){
PumaHome service = (PumaHome) psh.getPortletService(PumaHome.class);
PumaProfile pp = service.getProfile(request);
PumaLocator pl = service.getLocator(request);
List list1 = pl.findUsersByAttribute("uid", "wps*");
Iterator iter1 = list1.iterator();
User user1;
String user_objid;
while(iter1.hasNext()){
121
IBM Japan Systems Engineering
user1 = (User)iter1.next();
user_objid = pp.getIdentifier(user1);
System.out.println(user_objid);
・・・・・(省略)
}
}
} catch (PumaException pe){
pe.printStackTrace();
・・・・・(省略)
}
グループ検索の場合は、findGroupsByAttribute メソッドを利用します。
List list1 = pl.findGroupsByAttribute("cn", "*");
尚、デフォルトの検索キーを使って検索することが出来ます。ユーザー検索の場合は、"uid"
をキーとして、グループ検索の場合は、"cn"をキーとします。findUsersByDefaultAttribute
メソッドもしくは findGroupsByDefaultAttribute を使用します。
List list1 = pl.findUsersByDefaultAttribute("wps*"); //ユーザー検索(デフォルト)
List list2 = pl.findGroupsByDefaultAttribute("wps*"); //グループ検索(デフォルト)
【補足】
管理者ユーザー(wpsadmin)は全ての操作が行えますが、一般ユーザーで操作する場合は、
仮想リソースによるそれぞれの権限を付与する必要があります。例えば、操作するユーザー
が、仮想リソース「ユーザー」の編集権限を持っていれば、ユーザーの検索が実行できま
す。
9.6
PumaController
ユーザーおよびグループを作成したり削除したり出来ます。メンバーシップ(ユーザーの
グループ所属)を変更することも出来ます。PumaHome オブジェクトから、PumaController
オブジェクトを取得します。
createUser メソッドを利用して、ユーザーを作成する例を示します。
//PortletServiceHome psh;
try{
if (psh != null){
PumaHome service = (PumaHome) psh.getPortletService(PumaHome.class);
122
IBM Japan Systems Engineering
PumaController pc = service.getController(request);
HashMap map1 = new HashMap();
map1.put("uid", "user1");
map1.put("givenName", "firstname1");
map1.put("sn", "lastname1");
map1.put("cn", "firstname1 lastname1");
map1.put("userPassword", "password");
map1.put("ibm-primaryEmail", "[email protected]");
map1.put("preferredLanguage", "ja");
pc.createUser("user1", null, map1);
}
} catch (PumaException pe){
pe.printStackTrace();
・・・・・(省略)
}
グループ作成の場合は、createGroup メソッドを利用します。
HashMap map1 = new HashMap();
map1.put("cn", "group1");
pc.createGroup("group1", null, map1);
ユーザーの属性変更および削除を行う場合、PumaLocator を使って、User オブジェクトを
検索して、setAttributes メソッドや deleteUser メソッドを呼び出します。
User user;
pc.setAttributes(user, map);
pc.deleteUser(user);
グループの属性変更および削除を行う場合、PumaLocator を使って、Group オブジェクトを
検索して、setAttributes メソッドや deleteGroup メソッドを呼び出します。
Group group;
pc.setAttributes(group, map);
pc.deleteGroup(group);
addToGroup メソッドを利用して、ユーザーをグループに所属させます。ID が"user"で始ま
る全ユーザーを、グループ"group1"に所属させる例を示します。
123
IBM Japan Systems Engineering
try{
if (psh != null){
PumaHome service = (PumaHome) psh.getPortletService(PumaHome.class);
PumaLocator pl = service.getLocator(request);
PumaController pc = service.getController(request);
List list1 = pl.findGroupsByDefaultAttribute("group1");
if(list1.size() != 1){
System.out.println("該当グループが存在しない、もしくは複数存在します");
・・・・・(省略)
} else {
Iterator iter1 = list1.iterator();
Group group1 = (Group)iter1.next();
List list2 = pl.findUsersByDefaultAttribute("user*");
pc.addToGroup(group1, list2);
・・・・・(省略)
}
}
} catch (PumaException pe){
pe.printStackTrace();
・・・・・(省略)
}
ユーザーをグループの所属から外す場合は、removeFromGroup メソッドを利用します。
Group group;
List users;
pc.removeFromGroup(group, users);
【補足】
管理者ユーザー(wpsadmin)は全ての操作が行えますが、一般ユーザーで操作する場合は、
仮想リソースによるそれぞれの権限を付与する必要があります。例えば、操作するユーザー
が、仮想リソース「ユーザーグループ」の編集権限を持っていれば、グループを作成出来
ます。
9.7
解答例
<< Lesson8Portlet.java >>
124
IBM Japan Systems Engineering
package com.ibm.lesson8;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import com.ibm.portal.portlet.service.PortletServiceHome;
import com.ibm.portal.um.PumaLocator;
import com.ibm.portal.um.PumaProfile;
import com.ibm.portal.um.User;
import com.ibm.portal.um.exceptions.PumaException;
import com.ibm.portal.um.portletservice.PumaHome;
/**
* A sample portlet based on GenericPortlet
*/
public class Lesson8Portlet extends GenericPortlet {
public static final String VIEW_JSP
= "/_Lesson8/jsp/html/Lesson8PortletVie
w.jsp";
public static final String SESSION_BEAN = "Lesson8PortletSessionBean";
public static final String FORM_FIND_USERS_BY_ATTRIBUTE = "findUsersByAttribute
";
public static final String FORM_TEXT_FIND_USERS_BY_ATTRIBUTE_KEY = "TextFindUser
sByAttributeKey";
125
IBM Japan Systems Engineering
public static final String FORM_TEXT_FIND_USERS_BY_ATTRIBUTE_VALUE = "TextFindUs
ersByAttributeValue";
private PortletServiceHome psh;
public void init() throws PortletException{
super.init();
try{
javax.naming.Context ctx = new javax.naming.InitialContext();
psh = (PortletServiceHome)ctx.lookup("portletservice/com.ibm.portal.um.
portletservice.PumaHome");
} catch(javax.naming.NameNotFoundException ex) {
ex.printStackTrace();
} catch(javax.naming.NamingException ex) {
ex.printStackTrace();
}
}
public void doView(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
// Check if portlet session exists
Lesson8PortletSessionBean sessionBean = getSessionBean(request);
if( sessionBean==null ) {
response.getWriter().println("<b>NO PORTLET SESSION YET</b>");
return;
}
//ログインしているユーザーの属性名一覧を取得
if (psh != null){
PumaHome service = (PumaHome) psh.getPortletService(PumaHome.class);
PumaProfile pp = service.getProfile(request);
126
IBM Japan Systems Engineering
try{
List user_attr_names = pp.getDefinedUserAttributeNames();
sessionBean.setUserAttributeNames(user_attr_names);
} catch (PumaException pe){
pe.printStackTrace();
}
}
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(VIEW_
JSP);
rd.include(request,response);
}
public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
if( request.getParameter(FORM_FIND_USERS_BY_ATTRIBUTE) != null ) {
//ユーザー検索(属性検索)
try{
String search_key = request.getParameter(FORM_TEXT_FIND_USERS_BY_ATT
RIBUTE_KEY);
String search_value = request.getParameter(FORM_TEXT_FIND_USERS_BY_A
TTRIBUTE_VALUE);
Lesson8PortletSessionBean sessionBean = getSessionBean(request);
if(search_key != null && search_value != null && !search_key.equals
("") && !search_value.equals("")){
if (psh != null){
PumaHome service = (PumaHome) psh.getPortletService(PumaHom
e.class);
PumaProfile pp = service.getProfile(request);
PumaLocator pl = service.getLocator(request);
List user_list = pl.findUsersByAttribute(search_key, search
_value);
127
IBM Japan Systems Engineering
Iterator user_iter = user_list.iterator();
User user1;
List list1;
List list2 = new ArrayList();
Map map1;
String user_dn;
while(user_iter.hasNext()){
Lesson8PortletUserBean obj_user = new Lesson8PortletUse
rBean();
user1 = (User)user_iter.next();
user_dn = pp.getIdentifier(user1);
obj_user.setUserid(user_dn);
list1 = pp.getDefinedUserAttributeNames();
map1 = pp.getAttributes(user1, list1);
obj_user.setAttributeNames(map1);
list2.add(obj_user);
}
sessionBean.setUsers(list2);
}
}
} catch (PumaException pe){
pe.printStackTrace();
}
} // end of FORM_FIND_USERS_BY_ATTRIBUTE
}
private static Lesson8PortletSessionBean getSessionBean(PortletRequest request)
{
PortletSession session = request.getPortletSession();
if( session == null )
return null;
128
IBM Japan Systems Engineering
Lesson8PortletSessionBean sessionBean = (Lesson8PortletSessionBean)session.g
etAttribute(SESSION_BEAN);
if( sessionBean == null ) {
sessionBean = new Lesson8PortletSessionBean();
session.setAttribute(SESSION_BEAN,sessionBean);
}
return sessionBean;
}
}
<< Lesson8PortletSessionBean.java >>
package com.ibm.lesson8;
import java.util.List;
public class Lesson8PortletSessionBean {
private List userAttributeNames;
private List users;
public List getUserAttributeNames() {
return userAttributeNames;
}
public void setUserAttributeNames(List userAttributeNames) {
this.userAttributeNames = userAttributeNames;
}
public List getUsers() {
return users;
}
129
IBM Japan Systems Engineering
public void setUsers(List users) {
this.users = users;
}
public void addUser(Lesson8PortletUserBean user){
users.add(user);
}
}
<< Lesson8PortletUserBean.java >>
package com.ibm.lesson8;
import java.util.Map;
public class Lesson8PortletUserBean {
private String userid = "";
private Map attributeNames;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public Map getAttributeNames() {
return attributeNames;
}
public void setAttributeNames(Map attributeNames) {
this.attributeNames = attributeNames;
}
130
IBM Japan Systems Engineering
}
<< Lesson8PortletView.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="jav
a.util.*,com.ibm.lesson8.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<%
Lesson8PortletSessionBean sessionBean = (Lesson8PortletSessionBean)renderReques
t.getPortletSession().getAttribute(Lesson8Portlet.SESSION_BEAN);
List user_attr_names = sessionBean.getUserAttributeNames();
List users = sessionBean.getUsers();
%>
<DIV style="margin: 12px; margin-bottom: 36px">
<FORM method="POST" action="<portlet:actionURL/>">
<fieldset>
<legend>ユーザー検索(属性検索)</legend>
<table>
<tr>
<td align="right">
<LABEL>属性名:</LABEL>
</td>
<td align="left">
<select name="<%=Lesson8Portlet.FORM_TEXT_FIND_USERS_BY_ATTRIBUTE_KEY%>"
>
<%
Iterator attr_iter = user_attr_names.iterator();
String attr_name;
while(attr_iter.hasNext()){
attr_name = (String)attr_iter.next().toString();
if(attr_name.equalsIgnoreCase("uid")){
131
IBM Japan Systems Engineering
%>
<option value="<%=attr_name%>" selected ><%=attr_name%></option>
<%
} else {
%>
<option value="<%=attr_name%>" ><%=attr_name%></option>
<%
}
}
%>
</select>
</td>
</tr>
<tr>
<td align="right">
<LABEL>文字列(ワイルドカード:<font color="red">*</font>):</LABEL>
</td>
<td align="left">
<INPUT name="<%=Lesson8Portlet.FORM_TEXT_FIND_USERS_BY_ATTRIBUTE_VALUE%>
" type="text"/><br>
</td>
</tr>
</table>
<INPUT name="<%=Lesson8Portlet.FORM_FIND_USERS_BY_ATTRIBUTE%>" type="submit"
value="ユーザー検索"/><br><br>
</fieldset>
</FORM>
<%
if(users != null && !users.isEmpty()) {
%>
<fieldset>
<legend>検索結果</legend>
<%
Iterator u_itar1 = users.iterator();
while(u_itar1.hasNext()){
132
IBM Japan Systems Engineering
Lesson8PortletUserBean u_user = (Lesson8PortletUserBean)u_itar1.next();
String u_id = u_user.getUserid();
Map u_map = u_user.getAttributeNames();
Iterator u_iter2 = u_map.keySet().iterator();
String u_key;
String u_value;
%>
【<%=u_id%>】<br>
<%
while(u_iter2.hasNext()){
u_key = (String)u_iter2.next();
u_value = u_map.get(u_key).toString();
%>
<%=u_key%>=<%=u_value%><br>
<%
}
%>
<hr>
<%
}
%>
</fieldset>
<%
}
%>
</DIV>
<< portlet.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<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/p
ortlet-app_1_0.xsd" id="com.ibm.lesson8.Lesson8Portlet.248c255311">
<portlet>
133
IBM Japan Systems Engineering
<portlet-name>Lesson8</portlet-name>
<display-name>Lesson8</display-name>
<display-name xml:lang="ja">Lesson8</display-name>
<portlet-class>com.ibm.lesson8.Lesson8Portlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson8.nl.Lesson8PortletResource</resource-bundle>
<portlet-info>
<title>Lesson8</title>
<short-title>Lesson8</short-title>
<keywords>Lesson8</keywords>
</portlet-info>
</portlet>
</portlet-app>
<< web.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:x
si="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.co
m/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>
Lesson8</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
134
IBM Japan Systems Engineering
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
135
IBM Japan Systems Engineering
10 [演習9]ポートレット間通信(連携ポートレット)
ポートレット間でメッセージ(プロパティ)の通信を行います。一般に「連携ポートレッ
ト」と呼ばれます。
[目的]
z
連携ポートレットの概念を理解
z
wsdl ファイルの定義を理解
z
ワイヤーの作成
[イメージ画像]
受信用ポートレット
送信用ポートレット
136
IBM Japan Systems Engineering
10.1 プロジェクトの情報
プロジェクト名
Lesson9
エンタープライズ・アプリケーション・プロジェクト名
Lesson9EAR
(受信用)ポートレット名
Lesson9
(受信用)表示名
Lesson9
(受信用)ポートレット・クラス
com.ibm.lesson9.Lesson6Portlet
(送信用)ポートレット名
Lesson9sender
(送信用)表示名
Lesson9sender
(送信用)ポートレット・クラス
com.ibm.lesson9.Lesson9senderPortlet
10.2 ポートレット間通信の概要
ポートレット間でメッセージ(プロパティ)の通信を行うことが出来ます。プロパティー
を提供する送信側ポートレットは、ソース・ポートレットと呼ばれます。 ソース・ポート
レットによって公開されるプロパティは、「出力プロパティ」と呼ばれます。
プロパティーを受け取る受信側ポートレットは、ターゲット・ポートレットと呼ばれます。
ターゲット・ポートレットによって受け取られるプロパティは、「入力プロパティ」と呼ば
れます。
そして、出力プロパティと入力プロパティを関連付ける機能は、
「ワイヤー」と呼ばれます。
ワイヤーは、個別のアプリケーションではなく、ポータルサーバー側で作成します。
以下の図を使って説明します。
送信側が変数 outputProperty を送信し、ポータルサーバーがワイヤーを使って、受信側
と関連付けます。受信側は変数 inputProperty として受け取ります。
送信側(Source)
ポータルサーバー
outputProperty
受信側(Target)
inputProperty
ワイヤー
出力
入力
つまり、ポートレット間通信を行うには、
①
送信側ポートレットの作成
137
IBM Japan Systems Engineering
②
受信側ポートレットの作成
③
ポータルによるワイヤーの作成
が必要となります。
10.3 送信用ポートレットを新規作成
プロジェクト作成時に、一緒に作成されたポートレット Lesson9Portlet を受信用として利
用します。よって、送信用のポートレット Lesson9senderPortlet を新規作成します。
(1)「ポートレット・デプロイメント記述子(portlet.xml)」を開きます。「ポートレット」
タブを選択して、「新規」ボタンを押下します。
138
IBM Japan Systems Engineering
(2)プロジェクトを「Lesson9」、ポートレット名を「Lesson9sender」、ポートレットのタイ
プを「基本ポートレット」にして、
「次へ」ボタンを押下します。
(3)パッケージ接頭部を「com.ibm.lesson9」、クラス接頭部を「Lesson9senderPortlet」に
して、「次へ」ボタンを押下します。
139
IBM Japan Systems Engineering
(4)「次へ」ボタンを押下します。
(5)「終了」ボタンを押下します。
(6)ポートレット・デプロイメント記述子のポートレット一覧に、Lesson9sender が追加さ
れていることを確認します。
プロジェクト・エクスプローラー内に、以下のファイルが作成されていることを確認しま
す。
140
IBM Japan Systems Engineering
【Java】
¾
Lesson9senderPortlet.java
¾
Lesson9senderPortletSessionBean.java(使用しないので削除しても構いません)
【jsp】
¾
Lesson9senderPortletView.jsp
【property】
¾
Lesson9senderPortletResource.properties
¾
Lesson9senderPortletResource_ja.properties
最後に、ポートレット・デプロイメント記述子を保存します。
10.4 wsdl ファイルの追加
プロジェクト・エクスプローラー内の/Lesson9/WebContent の直下にフォルダー「wsdl」を
作成します(作成方法は演習2で説明済み)。プロジェクト・エクスプローラー内の
/Lesson9/WebContent/wsdl に wsdl ファイル「Lesson9.wsdl」と「Lesson9sender.wsdl」を
インポートします。
※wsdl ファイルはハンズオンセットの以下の場所にあります。
/Lab/wsdl
141
IBM Japan Systems Engineering
10.5 ポートレット・デプロイメント記述子に wsdl を登録
各ポートレット毎に、使用する wsdl ファイルを登録します。
具体的には、<preference>タグにおいて、
「com.ibm.portal.propertybroker.wsdllocation」
と
「com.ibm.portal.pagecontext.enable」
を登録します。
¾
com.ibm.portal.propertybroker.wsdllocation
プロジェクト内における wsdl ファイルの PATH を設定
¾
com.ibm.portal.pagecontext.enable
タスク・プロパティーを検索出来るように、"true"を設定
・ポートレット・デプロイメント記述子の例
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app>
<portlet>
142
IBM Japan Systems Engineering
<portlet-name>Lesson9</portlet-name>
・・・・・(省略)
<portlet-info>
<title>Lesson9</title>
<short-title>Lesson9</short-title>
<keywords>Lesson9</keywords>
</portlet-info>
<portlet-preferences>
<preference>
<name>com.ibm.portal.propertybroker.wsdllocation</name>
<value>/wsdl/Lesson9.wsdl</value>
<read-only>true</read-only>
</preference>
<preference>
<name>com.ibm.portal.pagecontext.enable</name>
<value>true</value>
<read-only>true</read-only>
</preference>
</portlet-preferences>
</portlet>
<portlet>
<portlet-name>Lesson9sender</portlet-name>
・・・・・(省略)
<portlet-info>
<title>Lesson9sender</title>
<short-title>Lesson9sender</short-title>
<keywords>Lesson9sender</keywords>
</portlet-info>
<portlet-preferences>
<preference>
<name>com.ibm.portal.propertybroker.wsdllocation</name>
<value>/wsdl/Lesson9sender.wsdl</value>
<read-only>true</read-only>
</preference>
<preference>
<name>com.ibm.portal.pagecontext.enable</name>
143
IBM Japan Systems Engineering
<value>true</value>
<read-only>true</read-only>
</preference>
</portlet-preferences>
</portlet>
</portlet-app>
10.6 データ・タイプ、メッセージ及びオペレーションの定義
(1) <types> タグ
転送されるデータのデータ・タイプを宣言します。このデータ・タイプは XML Schema
Datatypes(XSD specification を参照してください)を使用して宣言されます。
<types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://le
sson9">
<xsd:simpleType name="MyDatatype">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:schema>
</types>
(2) <message> タグ
<types>によって定義したデータ・タイプをメッセージに登録します。データの送受信はこ
のメッセージ単位に行われます。
・output
<message name="SourceAction_Response">
<part name="MyDatatype_Output" type="tns0:MyDatatype"/>
</message>
・input
<message name="MyDatatype_Request">
<part name="MyDatatype_Input" type="tns0:MyDatatype"/>
</message>
(3) <portType>タグ
操作(operation)を定義します。
使用するメッセージ毎に出力、入力の指定を行います。
//出力
144
IBM Japan Systems Engineering
<portType name="Lesson9sender_Service">
<operation name="Lesson9sender">
<output message="tns:SourceAction_Response"/>
</operation>
</portType>
//入力
<portType name="Lesson9_Service">
<operation name="Lesson9">
<input message="tns:MyDatatype_Request"/>
</operation>
</portType>
・関連図
<types>
name=MyDatatype
<portType>
データ型=string
name=Lesson9sender_Service
入出力=output
<message>
name=SourceAction_Response
message=tns:SourceAction_Response
type=tns0:MyDatatype
<portType>
name=Lesson9_Service
入出力=input
<message>
name=MyDatatype_Request
message=tns:MyDatatype_Request
type=tns0:MyDatatype
145
IBM Japan Systems Engineering
・イメージ図
<portType>
output
input
<message>
<message>
<types>
<types>
10.7 バインディング <binding> の概要
バインディングは、連携ポートレットをサポートするために拡張されています。実際のユー
ザー操作(アクション)と、メッセージを関連付ける為に、<binding>タグを定義します。
・関連図
【output】
<binding>
name=Lesson9sender_Binding
<portType>
type=tns:Lesson9sender_Service
name=Lesson9sender_Service
アクションの定義
【input】
<binding>
name=Lesson9_Binding
<portType>
type=tns:Lesson9_Service
name=Lesson9_Service
アクションの定義
146
IBM Japan Systems Engineering
(1) <portlet:action>タグ
それぞれの操作ごとに、ポートレットのアクション名を与える必要があります。ポートレッ
トのアクション名は、wsdl ファイルのバインディングにある<portlet:action>タグの
「name」属性を使用して指定できます。「actionNameParameter」属性は、アクションを定
義するために使用されます。processAction メソッドにはアクション名を運ぶパラメーター
が無い為、この属性は標準ポートレット(JSR168 準拠ポートレット)で重要になります。
標準ポートレットでは、actionNameParameter を使用しなければ、どのアクションが呼び出
さ れ た の か を 判 別 す る こ と が で き ま せ ん 。 processAction メ ソ ッ ド に お い て 、
actionNameParameter で指定した値をキーとして、リクエストオブジェクトからパラメータ
を取得します。そのパラメータがポートレットのアクション名です。
//wsdl ファイル
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption" nam
e="SourceAction" type="standard"/>
//Java コード
String actionValue = request.getParameter("ACTION_NAME_PARAM");
if(actionValue != null && "SourceAction".equals(actionValue)) {
・・・・・(省略)
}
(2) <portlet:param>タグ
それぞれのパラメータごとに、アクションのパラメータ名を与える必要があります。ポー
トレットのパラメータ名は、wsdl ファイルのバインディングにある<portlet:param>タグの
「name」属性を使用して指定できます。
さらに、そのパラメータをバインドする場所を指定するために「boundTo」属性を使用でき
ます。boundTo 属性の種類を以下の表に示します。
boundTo 属性の種類
値
要求パラメータ
request-parameter
要求属性
request-attribute
セッション
session
描画パラメータ(※1)
render-parameter
※1:メッセージ送信(出力)時のみ使用可能
送信側と受信側のそれぞれで boundTo 属性が異なる場合でも問題ありません。例えば、送
信側が要求属性(request-attribute)方式で送信したプロパティ(パラメータ)を、受信側
147
IBM Japan Systems Engineering
が要求パラメータ(request-parameter)方式で受け取ることが出来ます。
メッセージ送信時は、<portlet:param>を、<output>と</output>で囲みます。
メッセージ受信時は、<portlet:param>を、<input>と</input>で囲みます。
以下にバインディングの例を示します。
・メッセージ送信(出力)用のバインディングの例
<binding name="Lesson9sender_Binding" type="tns:Lesson9sender_Service">
<portlet:binding/>
<operation name="Lesson9sender">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption"
name="SourceAction" type="standard"/>
<output>
<portlet:param boundTo="request-attribute" caption="Property.Caption" name="out
putProperty" partname="MyDatatype_Output"/>
</output>
</operation>
</binding>
・メッセージ受信(入力)用のバインディングの例
<binding name="Lesson9_Binding" type="tns:Lesson9_Service">
<portlet:binding/>
<operation name="Lesson9">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption"
name="TargetAction" type="standard" />
<input>
<portlet:param boundTo="request-parameter" caption="Property.Caption" name="inp
utProperty" partname="MyDatatype_Input"/>
</input>
</operation>
</binding>
(3) caption 属性とリソース・バンドルの関係
<portlet:action>タグや<portlet:param>タグに定義している「caption」属性は、アク
ション名や送受信するプロパティ名を別名で表示する際に使用します。caption の値をキー
として、リソース・バンドルから実際に表示する文字列を取得します。
148
IBM Japan Systems Engineering
・Lesson9senderPortletResource.properties
(Lesson9senderPortletResource_ja.properties を使ってもよい)
javax.portlet.title=Lesson9sender
javax.portlet.short-title=Lesson9sender
javax.portlet.keywords=Lesson9sender
Property.Caption=outputProperty Property
Action.Caption=SourceAction Action
・Lesson9PortletResource.properties
(Lesson9PortletResource_ja.properties を使ってもよい)
javax.portlet.title=Lesson9
javax.portlet.short-title=Lesson9
javax.portlet.keywords=Lesson9
Property.Caption=inputProperty Property
Action.Caption=TargetAction Action
10.8 メッセージ送信時のプログラム例
boundTo 属性毎のプログラム実装例を示します。実装方法は異なっても、全て同じ動作をし
ます。
(1) 要求パラメータ(request-parameter)を用いたメッセージ送信
STEP1: ソース・アクション・パラメータをアクション要求に配置します。
プロパティーの転送は、ユーザーがボタンをクリックしたりリンクを選択するなどのアク
ションを実行したときに起動します。 ユーザーがパラメータ転送を起動するアクションを
実行すると、ソース・アクション・パラメータ ACTION_NAME_PARAM が、アクション要求セッ
ト内に配置され、アクション値は SourceAction になります。
//(例)実行ボタンを含む書式の使用
<FORM method="POST" action="<portlet:actionURL/>">
<input type="hidden" name="outputProperty" value="data"/>
<input type="hidden" name="ACTION_NAME_PARAM" value="SourceAction"/>
<INPUT name="submit" value="Submit" type="submit"/>
</FORM>
//(例)出力プロパティーを直接要求パラメータ・スコープ内に配置
<a href="<portlet:actionURL><portlet:param name="ACTION_NAME_PARAM" value="SourceAct
149
IBM Japan Systems Engineering
ion"/><portlet:param name="outputProperty" value="data"/></portlet:actionURL>">Send
Data</a>
・wsdl ファイルの一部
<binding name="Lesson9sender_Binding" type="tns:Lesson9sender_Service">
<portlet:binding/>
<operation name="Lesson9sender">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption"
name="SourceAction" type="standard" />
<output>
<portlet:param boundTo="request-parameter" caption="Property.Caption" name="ou
tputProperty" partname="MyDatatype_Output"/>
</output>
</operation>
</binding>
(2) 要求属性(request-attribute)を用いたメッセージ送信
STEP1: ソース・アクション・パラメータをアクション要求に配置します。
プロパティーの転送は、ユーザーがボタンをクリックしたりリンクを選択するなどのアク
ションを実行したときに起動します。 ユーザーがパラメータ転送を起動するアクションを
実行すると、ソース・アクション・パラメータ ACTION_NAME_PARAM が、アクション要求セッ
ト内に配置され、アクション値は SourceAction になります。
//(例)実行ボタンを含む書式の使用
<FORM method="POST" action="<portlet:actionURL/>">
<input name="ACTION_NAME_PARAM" value="SourceAction" type="hidden"/>
<input name="submit" value="Submit" type="submit"/>
</FORM>
//(例)ポートレット actionURL の使用
<a href="<portlet:actionURL><portlet:param name="ACTION_NAME_PARAM" value="SourceAct
ion"/></portlet:actionURL>">Send Data</a>
STEP2: 出力プロパティーをプロパティー・ブローカーが使用できるようにします。
プロパティー転送が起動されると、プロパティー・ブローカーが、ウィザードで定義され
たプロパティー名とロケーションで出力プロパティーを検索します。 出力プロパティーを
request-attribute スコープ内の変数名 outputProperty に配置します。
150
IBM Japan Systems Engineering
//(例)ポートレット・クラスの processAction() メソッドを使用して、書式または URL アク
ションを処理
public void processAction(ActionRequest request, ActionResponse response) throws Port
letException, java.io.IOException {
String actionValue = request.getParameter("ACTION_NAME_PARAM");
if(actionValue != null && "SourceAction".equals(actionValue)) {
//pleace value into proper scope
request.setAttribute("outputProperty", "data");
}
・wsdl ファイルの一部
<binding name="Lesson9sender_Binding" type="tns:Lesson9sender_Service">
<portlet:binding/>
<operation name="Lesson9sender">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption"
name="SourceAction" type="standard" />
<output>
<portlet:param boundTo="request-attribute" caption="Property.Caption" name="ou
tputProperty" partname="MyDatatype_Output"/>
</output>
</operation>
</binding>
(3) セッション(session)を用いたメッセージ送信
STEP1: ソース・アクション・パラメータをアクション要求に配置します。
プロパティーの転送は、ユーザーがボタンをクリックしたりリンクを選択するなどのアク
ションを実行したときに起動します。 ユーザーがパラメータ転送を起動するアクションを
実行すると、ソース・アクション・パラメータ ACTION_NAME_PARAM が、アクション要求セッ
ト内に配置され、アクション値は SourceAction になります。
//(例)実行ボタンを含む書式の使用
<FORM method="POST" action="<portlet:actionURL/>">
<input name="ACTION_NAME_PARAM" value="SourceAction" type="hidden"/>
<input name="submit" value="Submit" type="submit"/>
</FORM>
151
IBM Japan Systems Engineering
//(例)ポートレット actionURL の使用
<a href="<portlet:actionURL><portlet:param name="ACTION_NAME_PARAM" value="SourceAct
ion"/></portlet:actionURL>">Send Data</a>
STEP2: 出力プロパティーをプロパティー・ブローカーが使用できるようにします。
プロパティー転送が起動されると、プロパティー・ブローカーが、ウィザードで定義され
たプロパティー名とロケーションで出力プロパティーを検索します。 出力プロパティーを
session スコープ内の変数名 outputProperty に配置します。
//(例)ポートレット・クラスの processAction() メソッドを使用して、書式または URL アク
ションを処理
public void processAction(ActionRequest request, ActionResponse response) throws Port
letException, java.io.IOException {
String actionValue = request.getParameter("ACTION_NAME_PARAM");
if(actionValue != null && "SourceAction".equals(actionValue)) {
//pleace value into proper scope
request.getPortletSession.setAttribute("outputProperty", "data");
}
・wsdl ファイルの一部
<binding name="Lesson9sender_Binding" type="tns:Lesson9sender_Service">
<portlet:binding/>
<operation name="Lesson9sender">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption"
name="SourceAction" type="standard"/>
<output>
<portlet:param boundTo="session" caption="Property.Caption" name="outputProper
ty" partname="MyDatatype_Output"/>
</output>
</operation>
</binding>
(4) 描画パラメータ(render-parameter)を用いたメッセージ送信
STEP1: ソース・アクション・パラメータをアクション要求に配置します。
152
IBM Japan Systems Engineering
プロパティーの転送は、ユーザーがボタンをクリックしたりリンクを選択するなどのアク
ションを実行したときに起動します。 ユーザーがパラメータ転送を起動するアクションを
実行すると、ソース・アクション・パラメータ ACTION_NAME_PARAM が、アクション要求セッ
ト内に配置され、アクション値は SourceAction になります。
//(例)実行ボタンを含む書式の使用
<FORM method="POST" action="<portlet:actionURL/>">
<input name="ACTION_NAME_PARAM" value="SourceAction" type="hidden"/>
<input name="submit" value="Submit" type="submit"/>
</FORM>
//(例)ポートレット actionURL の使用
<a href="<portlet:actionURL><portlet:param name="ACTION_NAME_PARAM" value="SourceAct
ion"/></portlet:actionURL>">Send Data</a>
STEP2: 出力プロパティーをプロパティー・ブローカーが使用できるようにします。
プロパティー転送が起動されると、プロパティー・ブローカーが、ウィザードで定義され
たプロパティー名とロケーションで出力プロパティーを検索します。 出力プロパティーを
render-parameter スコープ内の変数名 outputProperty に配置します。
//(例)ポートレット・クラスの processAction() メソッドを使用して、書式または URL アク
ションを処理
public void processAction(ActionRequest request, ActionResponse response) throws Port
letException, java.io.IOException {
String actionValue = request.getParameter("ACTION_NAME_PARAM");
if(actionValue != null && "SourceAction".equals(actionValue)) {
//pleace value into proper scope
response.setRenderParameter("outputProperty", "data");
}
・wsdl ファイルの一部
<binding name="Lesson9sender_Binding" type="tns:Lesson9sender_Service">
<portlet:binding/>
<operation name="Lesson9sender">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption"
name="SourceAction" type="standard"/>
153
IBM Japan Systems Engineering
<output>
<portlet:param boundTo="render-parameter" caption="Property.Caption" name="out
putProperty" partname="MyDatatype_Output"/>
</output>
</operation>
</binding>
10.9 メッセージ受信時のプログラム例
boundTo 属性毎のプログラム実装例を示します。実装方法は異なっても、全て同じ動作をし
ます。
(1) 要求パラメータ(request-parameter)を用いたメッセージ受信
STEP1: 入力プロパティーを検索します。
プロパティー転送があると、プロパティー・ブローカーが入力プロパティーをターゲット・
ポートレットで使用可能にします。 入力プロパティーにアクセスするには、ターゲット・
ポートレットが、ウィザードで定義されたロケーションでそれを検索する必要があります。
//(例)ポートレット・クラスの processAction() メソッドを使用して、スコープ変数から入
力プロパティーをプルする
public void processAction(ActionRequest request, ActionResponse response) throws Port
letException, java.io.IOException {
String actionValue = request.getParameter("ACTION_NAME_PARAM");
if(actionValue != null && "TargetAction".equals(actionValue)) {
String input = request.getParameter("inputProperty");
}
}
・wsdl ファイルの一部
<binding name="Lesson9_Binding" type="tns:Lesson9_Service">
<portlet:binding/>
<operation name="Lesson9">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption"
name="TargetAction" type="standard" />
<input>
<portlet:param boundTo="request-parameter" caption="Property.Caption" name="in
154
IBM Japan Systems Engineering
putProperty" partname="MyDatatype_Input"/>
</input>
</operation>
</binding>
(2) 要求属性(request-attribute)を用いたメッセージ受信
STEP1: 入力プロパティーを検索します。
プロパティー転送があると、プロパティー・ブローカーが入力プロパティーをターゲット・
ポートレットで使用可能にします。 入力プロパティーにアクセスするには、ターゲット・
ポートレットが、ウィザードで定義されたロケーションでそれを検索する必要があります。
//(例)ポートレット・クラスの processAction() メソッドを使用して、スコープ変数から入
力プロパティーをプルする
public void processAction(ActionRequest request, ActionResponse response) throws Port
letException, java.io.IOException {
String actionValue = request.getParameter("ACTION_NAME_PARAM");
if(actionValue != null && "TargetAction".equals(actionValue)) {
String input = request.getAttribute("inputProperty");
}
}
・wsdl ファイルの一部
<binding name="Lesson9_Binding" type="tns:Lesson9_Service">
<portlet:binding/>
<operation name="Lesson9">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption"
name="TargetAction" type="standard" />
<input>
<portlet:param boundTo="request-attribute" caption="Property.Caption" name="in
putProperty" partname="MyDatatype_Input"/>
</input>
</operation>
</binding>
(3) セッション(session)を用いたメッセージ受信
155
IBM Japan Systems Engineering
STEP1: 入力プロパティーを検索します。
プロパティー転送があると、プロパティー・ブローカーが入力プロパティーをターゲット・
ポートレットで使用可能にします。 入力プロパティーにアクセスするには、ターゲット・
ポートレットが、ウィザードで定義されたロケーションでそれを検索する必要があります。
//(例)ポートレット・クラスの processAction() メソッドを使用して、スコープ変数から入
力プロパティーをプルする
public void processAction(ActionRequest request, ActionResponse response) throws Port
letException, java.io.IOException {
String actionValue = request.getParameter("ACTION_NAME_PARAM");
if(actionValue != null && "TargetAction".equals(actionValue)) {
String input = request.getPortletSession.getAttribute("inputProperty");
}
}
・wsdl ファイルの一部
<binding name="Lesson9_Binding" type="tns:Lesson9_Service">
<portlet:binding/>
<operation name="Lesson9">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Caption"
name="TargetAction" type="standard" />
<input>
<portlet:param boundTo="session" caption="Property.Caption" name="inputPropert
y" partname="MyDatatype_Input"/>
</input>
</operation>
</binding>
156
IBM Japan Systems Engineering
10.10 ワイヤーの作成
(1)Lesson9 を「サーバーで実行」します。以下のように受信用と送信用の2つのポートレッ
トが表示されます。
受信用ポートレット
送信用ポートレット
(2)ページ「Lesson9」のメニューから、「ページ・レイアウトの編集」を選択します。
157
IBM Japan Systems Engineering
(3)ページレイアウトの「コンテンツ」タブが選択されているので、「ワイヤー」タブを選
択します。
(4)ポートレット・ワイヤリング・ツールが表示されます。
158
IBM Japan Systems Engineering
(5)各パラメータを設定します。
【設定内容】
¾
ソース・ポートレット: Lesson9sender
¾
送信: outputProperty Property
¾
ターゲット・ページ: lesson9(・・・・・省略・・・・・)
¾
ターゲット・ポートレット: Lesson9
¾
受信: TargetAction Action,inputProperty Property
¾
ワイヤー・タイプ: 公開
ワイヤー・タイプを「パーソナル」にした場合は、操作しているユーザーのみが有効とな
り、「公開」にした場合は、どのユーザーでも共通に利用することが出来ます。
159
IBM Japan Systems Engineering
(6)「+」アイコンを押下します。
(7)ワイヤーが作成されます。「完了」ボタンを押下します。
160
IBM Japan Systems Engineering
(8)送信用ポートレット(Lesson9senderPortlet)のテキストボックスに文字列を入力して、
「送信」ボタンを押下します。
(9)受信用ポートレット(Lesson9Portlet)に受信メッセージが表示されます。
10.11 異なるページに対する通信
送信用ポートレットと受信用ポートレットが異なるページに配置してあっても、通信する
ことが出来ます。その場合、受信用ポートレットに対するワイヤーに追加設定を行います。
(1)ページレイアウトの「ワイヤー」タブを選択して、ポートレット・ワイヤリング・ツー
ルを表示します。画面右下にある「アクションの管理」ボタンを押下します。
161
IBM Japan Systems Engineering
(2)受信用ポートレットにある「グローバル」チェックボックスを"ON"して、「OK」ボタン
を押下します。
(3)他のページに送信用ポートレットを配置して、送信側のページにおいて、ワイヤーを作
成します。これにより、異なるページ間における通信が可能となります。
162
IBM Japan Systems Engineering
10.12 解答例
送信用ポートレットは、要求属性(request-attribute)として、送信しています。
受信用ポートレットは、要求パラメータ(request-parameter)として、受信しています。
<< Lesson9Portlet.java >>
package com.ibm.lesson9;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
/**
* A sample portlet based on GenericPortlet
*/
public class Lesson9Portlet extends GenericPortlet {
public static final String VIEW_JSP
= "/_Lesson9/jsp/html/Lesson9PortletVie
w.jsp";
public static final String SESSION_BEAN = "Lesson9PortletSessionBean";
public void init() throws PortletException{
super.init();
}
public void doView(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
163
IBM Japan Systems Engineering
// Check if portlet session exists
Lesson9PortletSessionBean sessionBean = getSessionBean(request);
if( sessionBean==null ) {
response.getWriter().println("<b>NO PORTLET SESSION YET</b>");
return;
}
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(VIEW_
JSP);
rd.include(request,response);
}
public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
String actionValue = request.getParameter("ACTION_NAME_PARAM");
if(actionValue != null && "TargetAction".equals(actionValue)) {
String input = request.getParameter("inputProperty");
Lesson9PortletSessionBean sessionBean = getSessionBean(request);
if( sessionBean != null ){
sessionBean.setFormText(input);
}
}
}
private static Lesson9PortletSessionBean getSessionBean(PortletRequest request)
{
PortletSession session = request.getPortletSession();
if( session == null )
return null;
Lesson9PortletSessionBean sessionBean = (Lesson9PortletSessionBean)session.g
etAttribute(SESSION_BEAN);
if( sessionBean == null ) {
sessionBean = new Lesson9PortletSessionBean();
session.setAttribute(SESSION_BEAN,sessionBean);
}
164
IBM Japan Systems Engineering
return sessionBean;
}
}
<< Lesson9PortletSessionBean.java >>
package com.ibm.lesson9;
public class Lesson9PortletSessionBean {
private String formText = "";
public void setFormText(String formText) {
this.formText = formText;
}
public String getFormText() {
return this.formText;
}
}
<< Lesson9senderPortlet.java >>
package com.ibm.lesson9;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
/**
165
IBM Japan Systems Engineering
* A sample portlet based on GenericPortlet
*/
public class Lesson9senderPortlet extends GenericPortlet {
public static final String VIEW_JSP
= "/_Lesson9sender/jsp/html/Lesson9send
erPortletView.jsp";
public static final String FORM_SUBMIT
= "Lesson9senderPortletFormSubmit";
public static final String FORM_TEXT
= "Lesson9senderPortletFormText";
public void init() throws PortletException{
super.init();
}
public void doView(RenderRequest request, RenderResponse response) throws Portle
tException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(VIEW_
JSP);
rd.include(request,response);
}
public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
if( request.getParameter(FORM_SUBMIT) != null ) {
String actionValue = request.getParameter("ACTION_NAME_PARAM");
if(actionValue != null && "SourceAction".equals(actionValue)) {
request.setAttribute("outputProperty", request.getParameter(FORM_TE
XT));
}
}
}
}
166
IBM Japan Systems Engineering
<< Lesson9senderPortletSessionBean.java >>
未使用
<< Lesson9PortletView.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="com.
ibm.lesson9.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<%
Lesson9PortletSessionBean sessionBean = (Lesson9PortletSessionBean)renderReques
t.getPortletSession().getAttribute(Lesson9Portlet.SESSION_BEAN);
String message = sessionBean.getFormText();
if(message == null){
message = "";
}
%>
<DIV style="margin: 12px; margin-bottom: 36px">
受信メッセージ:<%=message%>
</DIV>
<< Lesson9senderPortletView.jsp >>
<%@page session="false" contentType="text/html" pageEncoding="Shift_JIS" import="com.
ibm.lesson9.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<DIV style="margin: 6px">
<H3 style="margin-bottom: 3px">ようこそ!</H3>
<DIV style="margin: 12px; margin-bottom: 36px">
<FORM method="POST" action="<portlet:actionURL/>">
<LABEL for="<%=Lesson9senderPortlet.FORM_TEXT%>">送信メッセージ:</LABEL><BR
167
IBM Japan Systems Engineering
>
<INPUT name="<%=Lesson9senderPortlet.FORM_TEXT%>" type="text"/>
<INPUT name="<%=Lesson9senderPortlet.FORM_SUBMIT%>" type="submit" value="送
信"/>
<INPUT name="ACTION_NAME_PARAM" value="SourceAction" type="hidden"/>
</FORM>
</DIV>
</DIV>
<< Lesson9PortletResource.properties >>
javax.portlet.title=Lesson9
javax.portlet.short-title=Lesson9
javax.portlet.keywords=Lesson9
Property.Caption=inputProperty Property
Action.Caption=TargetAction Action
<< Lesson9senderPortletResource.properties >>
javax.portlet.title=Lesson9sender
javax.portlet.short-title=Lesson9sender
javax.portlet.keywords=Lesson9sender
Property.Caption=outputProperty Property
Action.Caption=SourceAction Action
<< Lesson9.wsdl >>
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:portlet="http://www.ibm.c
om/wps/c2a" xmlns:tns="http://lesson9/" xmlns:tns0="http://lesson9" name="Lesson9_Ser
vice" targetNamespace="http://lesson9/">
<types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://
lesson9">
<xsd:simpleType name="MyDatatype">
<xsd:restriction base="xsd:string"/>
168
IBM Japan Systems Engineering
</xsd:simpleType>
</xsd:schema>
</types>
<message name="MyDatatype_Request">
<part name="MyDatatype_Input" type="tns0:MyDatatype"/>
</message>
<portType name="Lesson9_Service">
<operation name="Lesson9">
<input message="tns:MyDatatype_Request"/>
</operation>
</portType>
<binding name="Lesson9_Binding" type="tns:Lesson9_Service">
<portlet:binding/>
<operation name="Lesson9">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Captio
n" name="TargetAction" type="standard" />
<input>
<portlet:param boundTo="request-parameter" caption="Property.Caption" name="
inputProperty" partname="MyDatatype_Input"/>
</input>
</operation>
</binding>
</definitions>
<< Lesson9sender.wsdl >>
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:portlet="http://www.ibm.c
om/wps/c2a" xmlns:tns="http://lesson9/" xmlns:tns0="http://lesson9" name="Lesson9send
er_Service" targetNamespace="http://lesson9/">
<types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://
lesson9">
<xsd:simpleType name="MyDatatype">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
169
IBM Japan Systems Engineering
</xsd:schema>
</types>
<message name="SourceAction_Response">
<part name="MyDatatype_Output" type="tns0:MyDatatype"/>
</message>
<portType name="Lesson9sender_Service">
<operation name="Lesson9sender">
<output message="tns:SourceAction_Response"/>
</operation>
</portType>
<binding name="Lesson9sender_Binding" type="tns:Lesson9sender_Service">
<portlet:binding/>
<operation name="Lesson9sender">
<portlet:action actionNameParameter="ACTION_NAME_PARAM" caption="Action.Captio
n" name="SourceAction" type="standard" />
<output>
<portlet:param boundTo="request-attribute" caption="Property.Caption" name="
outputProperty" partname="MyDatatype_Output"/>
</output>
</operation>
</binding>
</definitions>
<< portlet.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<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/p
ortlet-app_1_0.xsd" id="com.ibm.lesson9.Lesson9Portlet.03c2f6a411">
<portlet>
<portlet-name>Lesson9</portlet-name>
<display-name>Lesson9</display-name>
<display-name xml:lang="ja">Lesson9</display-name>
<portlet-class>com.ibm.lesson9.Lesson9Portlet</portlet-class>
<init-param>
170
IBM Japan Systems Engineering
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson9.nl.Lesson9PortletResource</resource-bundle>
<portlet-info>
<title>Lesson9</title>
<short-title>Lesson9</short-title>
<keywords>Lesson9</keywords>
</portlet-info>
<portlet-preferences>
<preference>
<name>com.ibm.portal.propertybroker.wsdllocation</name>
<value>/wsdl/Lesson9.wsdl</value>
<read-only>true</read-only>
</preference>
<preference>
<name>com.ibm.portal.pagecontext.enable</name>
<value>true</value>
<read-only>true</read-only>
</preference>
</portlet-preferences>
</portlet>
<portlet>
<portlet-name>Lesson9sender</portlet-name>
<display-name>Lesson9sender</display-name>
<display-name xml:lang="ja">Lesson9sender</display-name>
<portlet-class>com.ibm.lesson9.Lesson9senderPortlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
171
IBM Japan Systems Engineering
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>ja</supported-locale>
<resource-bundle>com.ibm.lesson9.nl.Lesson9senderPortletResource</resource-b
undle>
<portlet-info>
<title>Lesson9sender</title>
<short-title>Lesson9sender</short-title>
<keywords>Lesson9sender</keywords>
</portlet-info>
<portlet-preferences>
<preference>
<name>com.ibm.portal.propertybroker.wsdllocation</name>
<value>/wsdl/Lesson9sender.wsdl</value>
<read-only>true</read-only>
</preference>
<preference>
<name>com.ibm.portal.pagecontext.enable</name>
<value>true</value>
<read-only>true</read-only>
</preference>
</portlet-preferences>
</portlet>
</portlet-app>
<< web.xml >>
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:x
si="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.co
m/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>
172
IBM Japan Systems Engineering
Lesson9</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
173
IBM Japan Systems Engineering
11 TIPS
演習では収まりきらなかった項目を TIPS として載せておきます。
11.1 ユーザー属性の取得
演習8において、Puma オブジェクトによるユーザー属性の取得を行いました。それとは別
に JSR168 の仕様で、ユーザー属性を取得する方法があります。
任意のユーザー属性を指定するには、ポートレット・デプロイメント記述子(portlet.xml)
の<user-attribute>エレメントの下に Member Manager 属性名を指定する必要があります。
さらに、要求内の「USER_INFO マップ」を調べることで、属性値を取得することができます。
Member Manager 属性名を直接指定しないで、Java Portlet Specification の付録、「PLT.D
User Information Attribute Names」にある属性を指定することでも値を取得可能です。
「PLT.D User Information Attribute Names」にある属性、および Member Manager の対応
する属性名(wmmAttributeName)を載せておきます。
ユーザー属性名
Member Manager の対応する属性名
user.gender
ibm-gender
user.employer
o
user.department
ou
user.jobtitle
ibm-jobTitle
user.name.prefix
ibm-personalTitle
user.name.given
givenName
user.name.family
sn
user.name.middle
ibm-middleName
user.home-info.telecom.telephone.number
homePhone
user.home-info.online.email
ibm-otherEmail
user.business-info.postal.street
street
user.business-info.postal.stateprov
stateOrProvinceName
user.business-info.postal.postalcode
postalCode
user.business-info.postal.country
countryName
user.business-info.telecom.telephone.number
telephoneNumber
user.business-info.telecom.fax.number
facsimileTelephoneNumber
user.business-info.telecom.mobile.number
mobile
user.business-info.telecom.pager.number
pager
174
IBM Japan Systems Engineering
user.business-info.online.email(※1)
ibm-primaryEmail
※1:
「WebSphere Portal 6.0 Information Center」には、
「user.business-info.telecom.online.email」
と記載されていますが、
「user.business-info.online.email」の誤りです。
(例)ポートレット・デプロイメント記述子(portlet.xml)
<portlet-app>
<portlet>
・・・・・(省略)
</portlet>
<user-attribute>
<name>user.name.given</name>
</user-attribute>
<user-attribute>
<name>user.name.family</name>
</user-attribute>
<user-attribute>
<name>user.business-info.online.email</name>
</user-attribute>
</portlet-app>
(例)Java コード
Map userInfo = (Map)renderRequest.getAttribute(RenderRequest.USER_INFO);
System.out.println((String)userInfo.get("user.name.given"));
System.out.println((String)userInfo.get("user.name.family"));
System.out.println((String)userInfo.get("user.business-info.online.email"));
11.2 名前衝突の回避
ポートレットのアウトプットに使われるフォーム名やフィールド名、Java スクリプトの関
数名等は、他ポートレットやポータルサーバーの使用する名前との衝突を避けなければな
りません。その解決策として、演習7でも説明したネームスペース・エンコーディングを
用います。
【ネームスペース・エンコーディング】
¾
Java コードの場合
RenderResponse.getNamespace メソッド
¾
JSP の場合
175
IBM Japan Systems Engineering
<portlet:namespace/>タグ
PC_x_yyyyy_ のようにエンコードされます。
※x_yyyyy はポートレットのオブジェクト ID
(例)
<script language="JavaScript">
var PC_7_8000CB1A0G71802E1QUCIP0004_data1;
<!-var <portlet:namespace/>data1;
function <portlet:namespace/>checkData(){
・・・・・(省略)
return true;
}
function PC_7_8000CB1A0G71802E1QUCIP0004_checkData(){
-->
</script>
<form action="<portlet:actionURL/>" method="post" onSubmit="return <portlet:namespac
e/>checkData()">
<INPUT name="edit" value="save" type="submit"/>
</form>
11.3 ユーザー設定値の書き込みに関する補足
演習 4 において、編集モードに切り替えてから、ユーザー設定値を PortletPreferences オ
ブジェクトを使用して保管していました。実際は、表示モードでも書き込みは可能です。
176
IBM Japan Systems Engineering
12 その他
12.1 特殊互換モードについて
前のバージョンの WebSphere Portal または他のベンダーのポータル製品向けに作成された
ポートレットでは、カスタム・ポートレット・モード edit_defaults をサポートしないこ
とがあります。それらのポートレットでは、個人構成に対する変更(編集モード)のみがサ
ポートされています。そのようなポートレットの編集共用設定(edit_defaults)をセット
アップできるようにするには、ポートレット WAR ファイル内のポートレット・デプロイメン
ト記述子(portlet.xml)を編集して、ポートレットを再デプロイして更新することにより、
特殊互換モードを有効にする必要があります。
ポートレット・デプロイメント記述子(portlet.xml)において、サポート対象の edit モー
ドに加え、新規ポートレット・モード edit_defaults_compatibility を宣言します。
<portlet-app>
<portlet>
・・・・・(省略)
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<!--
edit mode MUST be supported
-->
<portlet-mode>edit_defaults_compatibility</portlet-mode>
</supports>
・・・・・(省略)
</portlet>
</portlet-app>
また、ポートレット・デプロイメント記述子(portlet.xml)内の最後の<portlet>タグの後
に、新規モードをカスタム・ポートレット・モードとして宣言する必要があります。
・・・・・(省略)
</portlet>
<custom-portlet-mode>
<portlet-mode>edit_defaults_compatibility</portlet-mode>
</custom-portlet-mode>
</portlet-app>
177
IBM Japan Systems Engineering
通常、ポートレットのモード切替を行う際、「共用設定の編集」を選択すると、編集共用設
定(edit_defaults)モードに切り替わりますが、上記の設定を行うと、編集(edit)モードに
切り替わります。編集モードの中で、PortletPreferences を書き込むと、編集共用設定と
して書き込むことが出来ます。edit_defaults モードおよび edit_defaults_compatibility
モードは、相互に排他的です。ポートレットは一度にその内の 1 つしかサポートできません。
※一般的にポートレットを新規開発する場合は、特殊互換モードにする必要は
ありません。
178
IBM Japan Systems Engineering
演習は以上で終了になります。
179
Fly UP