I will be waiting for your knock ever after from today.


Visards, Inc.

Java Sticky Note

java
  ・JSTL
  ・Commons Net
  ・Apache
  ・Tomcat
  ・James
  ・Jetspeed
  ・POI
  ・Jexl
  ・Jelly
  ・Blojsom
  ・eclipse

link
  ・James

author
  ・profile

Jetspeed  
<< prev | Index | next >>
Jetspeedによるポータルサイトの構築

mixiチェック

5. ポートレットの作成
本節では,ポートレットのプログラム構造の概略を 説明し,実際にポートレットを作成します.Jetspeed では,多くのポートレットがVelocityテンプレートを 用いて作成されていますが,ここでは広く普及してい るJSPをテンプレートとして使用するポートレットを 作成します.Velocityは,決して難易度の高い技術で はありませんので,Velocityでのポートレットの作成 にも,チャレンジしてみてください.

5.1 ポートレットのプログラム構造
ポートレットアプリケーションの振る舞いの決定に 大きな役割を果たすのが,次の3つのプログラムです.
  • ポートレットクラス
  • ポートレットクラスは,ポートレットの基本的な振 る舞いを制御するクラスです. たとえば, VelocityPortletクラスでは,Velocityを使用するため のコンテキストの初期化を行い,アクションクラスを 呼び出し,表示に使用するVelocityのテンプレートフ ァイルを決定する処理を行っています.

  • アクションクラス
  • 最大化やカスタマイズなど,ユーザの操作によるイ ベントを処理し,表示上必要なパラメータの設定を行 い,さらにポートレット表示に使用するテンプレート を決定するクラスです.

  • テンプレート
  • データの表示を担当します.テンプレートは,JSP, HTML,Velocity等で記述されます.

MVCモデルでは,ポートレットクラス・アクショ ンクラスがControllerに相当し,テンプレートがView に相当します.なお,アクションクラスやテンプレー トは必ず必要というわけではなく,ポートレットクラ スのみからポートレットを作成することも可能ですが, 一般的にはJetspeed上のポートレットアプリケーショ ンはこのような構造になっています.

5.2 ポートレットの作成方法
新たにポートレットを作成するには,主に次の方法 があります.

 a) 標準ポートレットクラスを使用し,表示テンプレ ートを新規に作成する
 b) 標準ポートレットクラスを使用し,Actionクラス, 表示テンプレートを新規作成する
 c) 新規にポートレットクラス,Actionクラス,表示 テンプレートを作成する

上記項目は,上のものほど作成するプログラム量が 少なく,下のものほどプログラムの自由度が増しま す.本稿では,b の方法を用いて,Actionクラスおよび,JSP による表示テンプレートを作成することにします. JSPでポートレットを作成する場合、多くの場合 新規にポートレットを 作成する必要はありません。標準ポートレットとして用意されている JspPortletを使用し、Actionクラスにロジックを実装するようにします。
Jetspeedで提供されている主なポートレットクラスとアクションクラス の関係を図10に示します.
    図10-1 ポートレットクラスの構造



    図10-2 アクションクラスの構造

サンプルポートレットは,次の手順で作成していき ます.
    1) Actionクラスの作成
    2) テンプレートの作成
    3) 設定ファイルの記述

5.3 サンプルポートレットの説明
サンプルで作成するポートレットは,メモを表示す るポートレットです.メモ情報は,サブジェクトと本 文からなるものとします(図11).
    図11 サンプルポートレットの表示

単純にテキスト情 報を表示するだけならHTMLポートレットでも可能で すが,ポートレットのタイトルバー上にあるカスタマ イズボタン(図4参照)をクリックすると表示される カスタマイズモードでメモ内容を編集できるようにし (図12),さらにポートレットの最大化表示(ポート レットのタイトルバー上の最大化ボタンをクリック) にも対応するようにします.通常表示モードでは,メ モの内容は20文字程度しか表示しませんが,最大表 示モードではメモの全テキストを表示するようにしま す(図13).
    図12 サンプルポートレットのカスタマイズモード

    図13 サンプルポートレットの最大化



リスト2 CustomeJspPortletクラス
 1 package sample;
 2 
 3 import org.apache.turbine.util.RunData;
 4 import org.apache.ecs.ConcreteElement;
 5 import org.apache.jetspeed.portal.portlets.JspPortlet;
 6 
 7 import org.apache.turbine.services.jsp.JspService;
 8 import org.apache.turbine.util.Log;
 9 import org.apache.turbine.modules.ActionLoader;
10 import org.apache.jetspeed.services.template.TemplateLocatorService;
11 import org.apache.ecs.StringElement;
12 import org.apache.turbine.services.TurbineServices;
13 import org.apache.ecs.ElementContainer;
14 
15 // カスタマイズ可能なJspPortlet
16 public class CustomizeJspPortlet extends JspPortlet {
17 
18     // ポートレットのコンテンツを生成
19     public ConcreteElement getContent(RunData rundata) {
20 
21         String template = "";
22         try {
23 
24             JspService service = (JspService)TurbineServices.getInstance().
25                 getService(JspService.SERVICE_NAME);
26 
27             service.addDefaultObjects(rundata);
28 
29             // JSPテンプレートから参照できるように設定
30             rundata.getRequest().setAttribute("portlet", this);
31             rundata.getRequest().setAttribute("js_peid", this.getID());
32 
33             String actionName = getPortletConfig().getInitParameter("action");
34 
35             rundata.getRequest().setAttribute("template",
36                 getPortletConfig().getInitParameter("template"));
37 
38             if (actionName != null) {
39                 try {
40                     // actionクラスの実行
41                     ActionLoader.getInstance().exec(rundata, actionName);
42                 } catch(Exception e) {
43                     Log.error(e);
44                 }
45             }
46 
47             // actionクラスで設定されたテンプレートの取得
48             template = (String)rundata.getRequest().getAttribute("template");
49 
50             TemplateLocatorService lserv =
51                 (TemplateLocatorService)TurbineServices.getInstance()
52                 .getService(TemplateLocatorService.SERVICE_NAME);
53             String locatedTemplate = lserv.locatePortletTemplate( rundata,
54                 template );
55 
56             // 出力
57             service.handleRequest(rundata, locatedTemplate);
58         } catch (Exception e) {
59             String message = "CustomizeJspPortlet: error : " + e.getMessage();
60             Log.error(message, e);
61             // エラー出力
62             return new StringElement( message );
63         }
64         return new ElementContainer();
65 
66     }
67 
68     // カスタマイズモードを有効にする
69     public boolean providesCustomization() {
70         return( true );
71     }
72 
73 }


5.3.1 ポートレットクラスについて
Jetspeed 1.4b3版までのJetspeedで提供されていたJSPポートレットでは、 ポートレットのカスタマイズモードはサポートしていませんでした。つまり、 カスタマイズボタンをクリックしても、メモ内容を変更するといった カスタマイズモードに移行する事ができませんでした。Jetspeed 1.4b4から は、JSPポートレットはカスタマイズモードをサポートしているので、 カスタマイズモードを使用するポートレットでも、標準のJSPポートレット が使用でき、新規にポートレットを作成する必要はなくなりました。
5.3.2 Action クラスの作成
アクションクラスは,表示・最大化・カスタマイズなどのイベントを処 理し,ポートレットの表示に使用するテンプレートを選択する,MVCモデ ルでのControllerに相当する処理を担当するクラスです.このメカニズムは, Turbineが提供している機能を使用するもので,Action クラスの実装は, Turbineが定義している抽象クラスであるActionクラスを実装する必要があ ります(図10参照).
Jetspeedでは,標準で多くのActionクラスの実装も提供していますので, Actionクラスを直接継承して実装することはあまりありません.今回作成す るSampleJspActionクラス(リスト3)のように,テンプレートとしてJSPを 使用する場合には,JspPortletActionクラスを継承してアクションクラスを 実装します.JspPortletActionクラスは,表示モードやイベントごとに異な るメソッドが呼び出されるように実装されています.表2 に,JspPortlet Actionクラスがイベント処理時に呼び出す主なメソッドを記述します.

表2 JspPortletAction クラスのイベント処理メソッド
メソッド 概要
buildNormalContext() 通常表示モードでポートレットを表示するときに呼び出されます
buildMaximizedContext() 最大表示モードでポートレットを表示するときに呼び出されます
buildConfigureContext() カスタマイズモードを表示するときに呼び出されます


サンプルプログラムのActionクラス(リスト3)では,表2 の3 つのメソッドと, カスタマイズモードでユーザがフォームに入力した値を受け取り処理するためのメ ソッドとして,doUpdate( )メソッドを実装します.本来,Actionクラスの役割は Controllerですので,ビジネスロジックに相当する処理はこのクラスと分離して実 装すべきですが,今回は簡単なサンプルプログラムですので,Actionクラス内で メモに関する処理も実装しています.

リスト2 SampleJspActionクラス
 1 package sample.actions;
 2 
 3 import org.apache.jetspeed.modules.actions.portlets.JspPortletAction;
 4 import org.apache.jetspeed.portal.Portlet;
 5 import org.apache.jetspeed.util.PortletSessionState;
 6 import org.apache.turbine.util.RunData;
 7 import javax.servlet.http.HttpServletRequest;
 8 
 9 
10 public class SampleJspAction extends JspPortletAction {
11 
12     // 通常表示
13     protected void  buildNormalContext(Portlet portlet, RunData rundata)
14         throws Exception {
15 
16         // 設定されているサブジェクト、本文の取得
17         String subject = (String)PortletSessionState.getAttributeWithFallback(
18             portlet, rundata, "subject");
19         String body = (String)PortletSessionState.getAttributeWithFallback(
20             portlet, rundata, "body");
21 
22         // サブジェクト、本文を JSP で使用できるように設定
23         HttpServletRequest request = rundata.getRequest();
24         request.setAttribute("subject", subject);
25         request.setAttribute("body", body);
26 
27         // テンプレート設定
28         setTemplate(rundata, 
29             portlet.getPortletConfig().getInitParameter("template"));
30     }
31 
32     // 最大表示
33     protected void buildMaximizedContext(Portlet portlet, RunData rundata)
34         throws Exception {
35 
36         buildNormalContext(portlet, rundata);
37 
38         setTemplate(rundata,
39             portlet.getPortletConfig().getInitParameter("maximizeTemplate"));
40     }
41 
42     // 編集モード表示
43     protected void buildConfigureContext(Portlet portlet, RunData rundata)
44         throws Exception {
45 
46         buildNormalContext(portlet, rundata);
47 
48         setTemplate(rundata, 
49             portlet.getPortletConfig().getInitParameter("customizeTemplate"));
50     }
51 
52     // データ更新
53     public void doUpdate(RunData rundata, Portlet portlet) {
54 
55         HttpServletRequest request = rundata.getRequest();
56 
57         String subject = getParameter(rundata, "subject");
58         String body    = getParameter(rundata, "body");
59         portlet.setAttribute("subject", subject, rundata);
60         portlet.setAttribute("body", body, rundata);
61 
62         request.setAttribute("subject", subject);
63         request.setAttribute("body", body);
64     }
65 
66     // リクエストパラメータの取得
67     private String getParameter(RunData rundata, String parameter) {
68         String value = rundata.getParameters().getString(parameter);
69         try {
70             value = new String (value.getBytes("8859_1"), "EUC-JP");
71         } catch(Exception e) {}
72         return( value );
73     }
74 
75 }

    ・buildNormalContext()の実装
    このメソッドは,通常表示モードでポートレットを表示するときに呼び出される メソッドです(リスト3 - 13行目〜30行目).JspPortletActionクラスは抽象クラ スで,このクラスを継承してActionクラスを作成する場合は,このbuildNormal Contextメソッドの実装は必須です.
    リスト3では,メモのサブジェクトと本文のテキストを,テンプレートのJSPプロ グラム内で使用できるように,リクエストの属性として設定し,出力テンプレー トとして使用するJSPファイルを選択する処理を行うだけです.
    buildNormalContext( )メソッドの引数は,PortletとRunDataです.Portletの実 態は,前節で作成したCustomizeJspPortletクラスです.getPortletConfig( ) メソッドでポートレットの実行環境に関する情報を保持しているPortletConfigを 取得することができ,PortletConfig のgetInitParameter( )でポートレットのレジ ストリマークアップ(リスト1)内で記述されているパラメータを取得することがで きます.ここでは,通常表示モードで使用するテンプレートのJSPファイルを,レ ジストリマークアップから取得しています
    もう一方の引数RunDataは,Turbineフレームワー クが提供しているリクエスト,およびレスポンスを処 理するためのパラメータです.簡単に言ってしまえば サーブレットにおけるServletRequest とServlet Responseをまとめたようなクラスですが,これらとの 大きな違いは,認証されたユーザ情報に基づくACL (Access Control List)の情報が含まれることと,テ ンプレートやスクリーンなどTurbineフレームワーク の出力方式と結びついた情報を含んでいることです. これにより,PortletアプリケーションがACLに基づく ユーザの認可処理といったセキュリティ関連の処理を 容易にし,またテンプレートに基づく出力を行うこと が可能となります.今回のサンプルプログラムでは, RunDataからユーザのリクエストを取得するために, getRequest( )メソッドを使用しています(リスト3 - 23行目).
    PortletSessionState.getAttributeWithFallback( )メ ソッドは,ポートレットがカスタマイズされていれば その情報を,カスタマイズされた情報がなければポー トレットのレジストリマークアップ(リスト1)に記 述されたパラメータを取得します(リスト3 - 17,19 行目).ここでは,メモのサブジェクトと本文をこの メソッドで取得しています.取得したメモのサブジェ クトと本文は,テンプレートのJSPファイル内で使用 できるようにリクエストの属性として設定します(リ スト3 - 24行目〜25行目).
    最後に,表示に使用するテンプレートを設定するた めにsetTemplate( )メソッドを呼び出しています(リ スト3 - 28行目).レジストリマークアップ内で “template”という名称で定義されているテンプレー トファイルを読み出して,表示用のテンプレートとし て設定する処理を行っています.

    ・buildMaximizedContext( )の実装
    このメソッド(リスト3 - 33〜40行目)は,ポートレ ットが最大化されたときに呼び出されるメソッドです. 今回のサンプルプログラムでは,メモ内容を取得し, リクエストに設定する処理はbuildNormalContext( ) と同様の処理ですので,このメソッドをそのまま呼び 出しています.
    最大表示モードで使用するテンプレートファイルは, 通常表示モードとは異なるファイル(リスト1,レジ ストリマークアップ内の“maximizeTemplate”で定 義)を使用しますので,テンプレートの設定処理のみ を行っています.

    ・buildConfigureContext( )の実装
    このメソッドは,カスタマイズモードを表示すると きに呼び出されるメソッドです.今回のサンプルプロ グラムでは,メモ内容を取得しリクエストに設定する 処理はbuildNormalContext( )と同様の処理ですので, このメソッドをそのまま呼び出しています. カスタマイズモードの出力に使用するテンプレート ファイルは,レジストリマークアップ(リスト1)で “customize Template”と定義されているものを使用 するように設定しています.

    ・doUpdate( )メソッドの実装
    上記buildConfigureContext( )メソッドで,カスタ マイズモードが表示できるようになりましたが,カス タマイズモードのフォーム(図13参照)で入力された 値を受け取り,その値をポートレットに反映させるた めのメソッドが必要です.それが,このdoUpdate( ) メソッドです.
    カスタマイズモードで使用するJSPテンプレートフ ァイルsample-customize.jsp(リスト4)のsubmitボ タンの名前が,
    <input type="submit" name="eventSubmit_doUpdate">
    というように,eventSubmit_doUpdateと記述してい ます.ここで記述したeventSubmit_に続く名称のメ ソッドが,Actionの実装クラスから呼び出されるよう にJspPortletActionクラスが実装されています.この ため,テンプレートファイルのsubmitボタンの名称に 合わせたメソッド名(doUpdate)で,このメソッド を実装する必要があります.
    今回のサンプルプログラムでは,ユーザが入力した サブジェクトと本文を受け取り,カスタマイ ズ値としてポートレットに設定する処理を行 います.カスタマイズモードで入力された文 字列は本来,
    rundata.getParameter().getString(parameter)
    で取得することが可能です.ただ,現時点で はこのメソッドは正しく国際化されていない ため,日本語のデータを上記メソッドで受け 取ることができません.ここでは,受け付け たリクエストをこのクラス内で直接EUCコー ドに変換して処理しています(リスト3 - 70 行目).
    受け取ったデータは,Portlet クラスの setAttribute( )メソッドでポートレットの属性 として設定しています.この処理で,設定さ れたデータ(メモのサブジェクトと本文)は, PSMLファイル上に自動的に永続化されます.

5.3.3 テンプレートの作成
テンプレートの役割は,MVCモデルにお けるViewの処理です.
テンプレートでは,Actionメソッドで設定 されたリクエスト属性を取得し,HTMLを出 力します.Actionメソッドでポートレットの 表示モードごとに呼び出すテンプレートを設 定していますので,それに合わせて通常のポ ートレット表示用のテンプレートとして sample.jsp(リスト5),最大化ポートレット 表示用のテンプレートとしてs a m p l e - maximize.jsp(リスト6),カスタマイズペー ジ表示用テンプレートとしてsample-customize.jsp(リスト4) を作成します.

    リスト4 sample-customize.jsp
    <%@ page language="java" session="false" %>
    <%@ page contentType = "text/html;charset=EUC-JP" %>
    <%@ taglib uri='/WEB-INF/templates/jsp/tld/template.tld' prefix='jetspeed' %>
    <%
    	String subject = (String)request.getAttribute("subject");
    	String body = (String)request.getAttribute("body");
    	// Escape characters for the subject and body are omitted.
    %>
    <form action="<jetspeed:dynamicUri />" method="post">
    
    <table>
        <tr>
        <td>タイトル</td>
        <td><input type="text" name="subject" value="<%= subject %>"></td>
        </tr>
    
        <tr>
        <td>本文</td>
        <td><textarea name="body" rows="3" cols="30"><%= body %></textarea></td>
        </tr>
    </table>
    
    <input type="submit" name="eventSubmit_doUpdate">
    </form>
    

    リスト5 sample.jsp
    <%@ page contentType = "text/html;charset=EUC-JP" %>
    <%
    	String subject = (String)request.getAttribute("subject");
    	String body = (String)request.getAttribute("body");
    	if (body.length() > 23) {
    		body = body.substring(0,20) + "...";
    	}
    	// Escape characters for the subject and body are omitted.
    %>
    <b><%= subject %></b><br/>
    <br/>
    <%= body %>
    

    リスト5 sample-maximize.jsp
    <%@ page language="java" session="false" %>
    <%@ page contentType = "text/html;charset=EUC-JP" %>
    <%
    	String subject = (String)request.getAttribute("subject");
    	String body = (String)request.getAttribute("body");
    	// Escape characters for the subject and body are omitted.
    %>
    <font size="+1">最大表示</font><br>
    <b><%= subject %></b><br/>
    <br/>
    <%= body %>
    
ごく簡単なJSPファイルですので,見ていただけれ ばどのような処理をしているかすぐわかると思います. どのJSPファイルでも,SampleJspActionクラスでリ クエストの属性として設定した情報を取得し,それを 画面上に表示する処理を行っています.sample.jspで は,本文テキストは,20文字程度しか表示しないよ うに処理していますが,最大化表示するsamplemaximize. jspでは,本文テキストをすべて表示するようになっています. また,sample-customize.jspの submit のname パラメータで,Action クラスの doUpdateメソッドが呼び出されるように設定してい ます.

5.3.4 コンパイル
作成したリスト2をコンパイルします.コンパイ ルには,サーブレットのクラスライブラリのほかに, ECS とTurbine のクラスライブラリが必要です. $JETSPEED/WEB-INF/lib/の下にあるecs-1.4.1.jar とturbine-2.2.jarをクラスパスに追加し,コンパイル を実行してください.

5.3.5 設定
1) クラスファイルの配置
コンパイルしたクラスファイルは,Jetspeedが読み 込めるように,$JETSPEED/WEB-INF/classes/の下 に置いてください.これに併せて,アクションモジュ ールのパッケージをTurbineの設定ファイルに記述し ます.今回,アクションモジュールはsample.action パッケージとして作成しました.Turbineがこのアク ションモジュールを検索できるように,設定ファイル を修正します.$JETSPEED/WEB-INF/conf/ TurbineResources.properties の170 行目付近に, module.packagesを設定している部分がありますので, そこに以下の記述を追加してください.
module.packages=sample
また,作成したJSP テンプレートファイルは, $JETSPEED/WEB-INF/templates/jsp/portlets/html/ に置いてください.

2) レジストリマークアップの設定
レジストリは,XMLで記述します.ここで登録す るレジストリファイルがリスト1です.ポートレット のタイトルや説明文などのほかに,このポートレット のクラス名,使用するテンプレートファイル,アクシ ョンクラスをここで記述します.サンプルポートレッ トでは,通常表示,最大表示,カスタマイズページで それぞれ異なるテンプレートファイルを使用しますの で,それぞれのテンプレートを設定しています. このファイルはsample.xregとして,$JETSPEED/WEB-INF/conf/ の下に置いてください.なお, Jetspeedはレジストリマークアップのデータをキャッ シュしますので,この設定はTomcatのプロセスを停 止させてから行うようにしてください.

5.3.6 実行
以上で設定終了です.Jetspeedを起動し,ログイ ンしたら,画面上部にある“カスタマイズ: HTML” のリンクをクリックし,カスタマイズ画面に進みます. そこで“ポートレットの追加”ボタンをクリックし, 表示される画面で,SampleJSPポートレットを追加し てください(図14).

図14 ポートレットのカスタマイズ画面


画面上で,図11のようなポート レットが表示されます.標準表示では,テキストが一 部しか表示されませんが,最大化するとテキストがす べて表示されます.また,カスタマイズボタンから, サブジェクトや本文を変更することもできます.


 << prev  ↑index  next >>


このドキュメントに関するご意見、ご要望などはまで。


Copyright (C) 2003-2005 Visards, Inc. All Rights Reserved.