第13章
この章では、追加の機能を実装するためのexteNd DirectorポートレットツールおよびAPIの使用を中心として、ポートレットを開発する方法について説明します。この章のトピックは、次のとおりです。
Java Portlet 1.0 APIの詳細については、Java Community ProcessのWebサイトを参照してください。
http://jcp.org/aboutJava/communityprocess/final/jsr168/index.html
exteNd Directorポータルで実行するポートレットを開発するときは、次の手順をお勧めします。
ポートレット開発ツールで説明されているexteNd Director開発ツールを使用してポートレットクラスを作成する。
ポートレット定義の作成に関する節で説明されているように、ポートレットクラスのインスタンス(ポートレット定義)を最低1つ作成する。
ポートレット定義の登録に関する節で説明されているように、ポートレット定義を最低1つ登録しポートレット登録を作成する。
ポートレットのテストに関する節で説明されているように、ポートレット登録を直接ブラウザで実行し、ポートレットをテストする。
ポータルページへのポートレットの追加に関する節で説明されているように、ポートレット登録を適切なポータルページに追加する。
ポートレットクラスとポートレット定義の詳細については、ポートレットオブジェクトモデルに関する節を参照してください。
exteNd Directorでは、ポートレットを開発するための次のようなツールが提供されています。
「ページフロー設計ツール」を使用すると、「ページフロー」と呼ばれる特殊なポートレットをJavaコーディングせずに作成することができます。ページフロー設計ツールを参照してください。
「ポートレットウィザード」を使用すると、従来のJavaコーディング方法を使用してカスタムポートレットクラスの作成プロセスを簡素化できます。
exteNd Directorでは、ページフローを開発するための設計ツールが提供されています。 名前から分かるとおり、「ページフロー」とはポートレットセッション内にあるアクティビティ間のコントロールフローを実装するポートレットのことです。 これらのアクティビティは、ユーザの操作の順序やバックグラウンド処理タスクをモデル化できます。 exteNd Directorの設計ツールではJavaコードを記述する必要がなく、ページフロー内でアクティビティの定義やリンクのプロセスを容易にします。
次のようなページフロー設計ツールの中から選択できます。
ページフローと設計ツールの使用法の詳細については、『Pageflow and Form Guide』を参照してください。
次のような場合、カスタムロジックの開発にページフロー設計ツールを使用できます。
ポートレットアプリケーションロジックの大部分はページフローを使用して実装できますが、カスタムポートレットクラスを記述した方がよい状況もあります。 exteNd Directorのポートレットウィザードは次の方法でこのプロセスを簡素化します。
ポートレットウィザードを使用してカスタムポートレットクラスを作成する方法の詳細については、ポートレットウィザードの使用に関する節を参照してください。
次のような場合、カスタムロジックの開発にポートレットウィザードを使用できます。
この節では、ポートレットクラスのロジック要件とポートレットウィザードによって自動生成される内容について説明します。
ポートレットクラスには最低限、次のロジックを含める必要があります。
ポートレットウィザードでは、exteNd Directorポータルの操作に必要なパッケージをインポートするために次のコードが自動生成されます。
次に、ポートレットウィザードのデフォルト設定に基づいて生成されたポートレットクラスの例を示します。
/** * Generated by Novell XSLT Code Generator, version 1.0. * This generated source file may be freely modified. */ package com.novell.portlets; //Java imports import java.io.PrintStream; import java.io.PrintWriter; import javax.portlet.*; // Portal/Framework imports import com.sssw.fw.api.*; import com.sssw.portal.api.*; // Portlet API imports import com.novell.afw.portlet.api.EbiPortletConstants; /** * MyPortlet */ public class MyPortlet extends GenericPortlet { // an Instance of a log for error/trace reporting private static EbiLog m_log = com.sssw.fw.log.EboLogFactory.getLog(com.sssw.fw.log.EboLogFactory.PORTLET); /** * Get the initialization parameters from the portlet.xml file */ public void init() throws PortletException { } /** * Helper method to serve up the mandatory view mode * @param request an portlet request object * @param response an render response object */ public void doView( RenderRequest request, RenderResponse response ) throws PortletException, java.io.IOException { try { // Uncomment the code below when access to portal subsystems is needed /* // EbiContext stores information about the user\qs environment EbiContext ebiContext = com.sssw.fw.factory.EboFactory.createEbiContext( request, response, getPortletContext() ); // Get a reference to the Portal Context object EbiPortalContext ebiPortalContext = ( EbiPortalContext ) request.getAttribute( EbiPortletConstants.EBI_PORTAL_CONTEXT ); */ PortletURL renderUrl = response.createRenderURL(); response.setContentType( EbiPortletConstants.MIME_TYPE_HTML ); renderUrl.setPortletMode( PortletMode.VIEW ); PrintWriter writer = response.getWriter(); // Build the screen of HTML, set it as the content StringBuffer sb = new StringBuffer(); // Output code goes here sb.append( "View Mode" ); sb.append( "<br></br>" ); writer.print( sb.toString() ); } catch ( Throwable e ) { // Log any errors generated m_log.error(e); new PortletException( e ); } } /** * Process any requests that the portlet may have. * @param request an action request object * @param actionResponse an action response object */ public void processAction (ActionRequest request, ActionResponse response) throws PortletException, java.io.IOException { try { PortletContext portletContext = getPortletContext(); // only log items if the log level indicates we should if ( m_log.isTrace() ) { m_log.trace( "MyPortlet in processAction method" ); } // Do "save" processing here if necessary, and then // set the portlet mode to be "View" after completion. response.setPortletMode( PortletMode.VIEW ); } catch ( Throwable e ) { // Log any errors generated m_log.error(e); new PortletException( e ); } } }
Java Portlet 1.0で定義されているように、すべてのポートレットはPortletインタフェースを実装します。 Portletインタフェースでは各ポートレットのライフサイクルを管理するために、ポートレットコンテナが使用するメソッドを提供します。
ポートレットはPortletインタフェースを直接実装することもできますし、GenericPortletクラスを拡張することもできます。GenericPortletクラスで説明されているように、GenericPortletクラスはポートレットインタフェースを実装すると同時にヘルパメソッドを提供します。
ポートレットを開発するときには、Portletインタフェースを直接実装せずに、GenericPortletクラスを拡張することができます。
GenericPortletクラスはPortletインタフェースのデフォルトの実装を提供します。 GenericPortletを拡張すると、GenericPortletのヘルパメソッドにアクセスでき、次のタスクのコーディングを簡素化することができます。
GenericPortletインタフェースで定義される次のメソッドは、ポートレットコンテナで説明されている標準ポートレットモードを実装します。 ポートレットを記述するときは、実装する各モードの必要に応じて、これらのメソッドをカスタム処理ロジックで上書きできます。
これらのメソッドは各モードで表示操作を実行します。
注記: exteNd Directorは編集モードのデフォルト実装で説明されているとおり、編集モードのデフォルトの実装を提供します。
GenericPortletインタフェースで定義される次のメソッドは、ポートレットのライフサイクルで説明されているポートレットのライフサイクルの段階を実装します。
メソッド |
説明 |
---|---|
init() |
ポートレットコンテナによって呼び出され、ポートレットをサービスに配置します。 |
processAction() |
アクション要求が発行されたことをポートレットに通知します。 |
render() |
表示要求が発行されたことをポートレットに通知します。 |
destroy() |
ポータルコンテナによって呼び出され、ポートレットをサービスから取り出します。 |
次のgetメソッドはGenericPortletインタフェースで定義されており、ポートレット設定パラメータへのアクセスを提供します。
メソッド |
取得する内容 |
---|---|
getInitParameter() |
名前が付けられたポートレット初期化パラメータの値。 |
getInitParameterNames() |
すべてのポートレット初期化パラメータの名前。 |
getPortletConfig() |
ポートレットの設定オブジェクト。 |
getPortletContext() |
ポートレットアプリケーションコンテキスト(ポートレットコンテキストの説明を参照)。 |
getPortletName() |
ポートレットの名前。 |
getResourceBundle() |
指定されたロケールのリソースバンドル。 |
exteNd DirectorはJava Portlet 1.0で定義された標準コンテキストオブジェクトをサポートしていますが、それに加えて次の独自のコンテキストオブジェクトを提供しており、ポートレットがexteNd Directorポータルと通信し、他のexteNd Directorサブシステムと通信することができます。
EbiContextはexteNd Directorのフレームワークシステムで定義されているインタフェースで、これを介してすべてのexteNd Directorサブシステムが通信を行います。 EbiContextには、現在のユーザエージェントまたはブラウザに適したユーザのID、セッション、応答オブジェクト、および要求オブジェクトを含む、ユーザ環境の情報が保存されます。
EbiContextを介して他のexteNd Directorサブシステムの情報にアクセスすることもできます。詳細については、他のサブシステムの情報にアクセスするためのEbiContextの使用を参照してください。
EbiContextオブジェクトは、要求の期間中に存在しています。 新しい要求の1つ1つに対して、exteNd Directorポータルは新規コンテキストオブジェクトをインスタンス化します。 要求間で保持される情報はEbiSessionオブジェクトに保存され、EbiContextでgetEbiSession()メソッドを呼び出すことによって使用できます。
これに対して、各ポートレットアプリケーションには標準のjavax.portlet.PortletContextが1つあります。 標準のPortletContextオブジェクトは、ポートレットアプリケーションにあるexteNd Director固有の情報へのアクセスを提供していません。
ポートレットは、FrameworkサブシステムのEboFactoryクラスでcreateEbiContext()メソッドを呼び出すことによりEbiContextオブジェクトを参照できます。 EbiContextコンテキストオブジェクトを取得するには、次のコードを使用します。
EbiContext context = com.sssw.fw.factory.EboFactory.createEbiContext(req, res, getPortletContext());
次のように、特定のタイプのポートレット要求やポートレット応答に関連付けられたEbiContextを取得できます。
アクションコンテキストオブジェクトを取得するには、次のコードを使用します。
com.sssw.fw.factory.EboFactory.createEbiContext(javax.portlet.ActionRequest request, javax.portlet.ActionResponse response, javax.portlet.PortletContext ctxt)
このメソッドでは、ポートレットのprocessAction()メソッドからEbiActionContextオブジェクトを呼び出したときに、EbiActionContextオブジェクトが戻されます。 EbiActionContextはEbiContextを拡張したものです。 EbiContextオブジェクトと異なり、EbiActionContextオブジェクトは基礎となるラップオブジェクトとしてActionRequestおよびActionResponseを持つことが保証されています。
表示コンテキストオブジェクトを取得するには、次のコードを使用します。
com.sssw.fw.factory.EboFactory.createEbiContext(javax.portlet.RenderRequest request, javax.portlet.RenderResponse response, javax.portlet.PortletContext ctxt)
このメソッドでは、ポートレットのrender()、doView()、doEdit()、またはdoHelp()メソッドからEbiRenderContextオブジェクトが戻されます。 EbiRenderContextはEbiContextを拡張したものです。 EbiContextオブジェクトとEbiRenderContextオブジェクトでは、EbiRenderContextは基礎となるラップオブジェクトとしてRenderRequestおよびRenderResponseを持つことが保証されている点で異なります。
ポートレットがEbiContextを介して他のexteNd Directorサブシステムの情報にアクセスする方法はいくつかあります。
EbiContextを使用して他のサブシステムのコンテキストオブジェクトにアクセスする。
たとえば、次のコードはFrameworkサブシステムのEbiContextからRuleサブシステムのEbiContextにアクセスします。
... //Get the EbiContext EbiContext context = com.sssw.fw.factory.EboFactory.createEbiContext(req, res, getPortletContext()); ... // get the re context out of fw context com.sssw.re.api.EbiContext reContext = com.sssw.re.factory.EboFactory.createEbiContext(context);
exteNd Directorマネージャオブジェクトによって実装されたメソッドにEbiContextを渡してサブシステム固有のデータにアクセスする。
たとえば、次のコードはFrameworkサブシステムのEbiContextをコンテンツマネージャに渡し、Content Managementサブシステムから情報を取得します。
... //Get the EbiContext EbiContext context = com.sssw.fw.factory.EboFactory.createEbiContext(req, res, getPortletContext()); ... //Find a document from the content management repository, String html_path = req.getParameter("html_path"); ... EbiContentMgmtDelegate cmgr = com.sssw.cm.client.EboFactory.getDefaultContentMgmtDelegate(); EbiDocument doc = (EbiDocument)cmgr.lookupDirectoryEntry(context, html_path,EbiDocument.EL_DOCUMENT);
標準のjavax.portlet.PortalContextと同じように、EbiPortalContextオブジェクトはポータル固有の情報にポートレットがアクセスできるようにします。 EbiPortalContextはパーソナルページ、共有ページ、およびコンテナページに関するデータなど、exteNd Directorポータル固有の情報を返すメソッドを提供する点が異なります。
ポートレットは、FrameworkサブシステムのEboFactoryクラスでcreateEbiContext()メソッドを呼び出すことによりEbiPortalContextオブジェクトを参照できます。EbiPortalContextコンテキストオブジェクトを取得するには、次のコードを使用します。
// Get a reference to the Portal Context object EbiPortalContext ebiPortalContext = ( EbiPortalContext ) request.getAttribute( EbiPortletConstants.EBI_PORTAL_CONTEXT );
FrameworkサブシステムのEbiResponseインタフェースにあるsetContentType()メソッドを呼び出すことにより、各ポートレットの表示応答のコンテンツタイプを設定する必要があります。
重要: モードはコンテンツタイプに基づいています。 このため、ポートレットのdoView()、doEdit()、およびdoHelp()メソッド(またはrender()メソッド)のモードを設定する「前に」コンテンツタイプを設定することを強くお勧めします。 この操作順序によって、exteNd Directorはコンテンツタイプに対してモードを検証できます。
ポートレットを同期または非同期で実行するように設定できます。 exteNd Directorのデフォルトでは、ポートレットは非同期で実行されます。 各ポートレットはそれ自体のスレッドで実行されるため、コンテンツ表示が並行して発生することがあります。 exteNd Directorポータルはページ上の各ポートレットが表示操作を完了するまで、またはタイムアウトするまで(どちらか早い方)待ってから、表示出力をページに集約します。
ポートレットを同期または非同期で実行するかどうかを決定するガイドラインを次に示します。
展開前のタスクに関する節で説明されているように、ポートレットアプリケーションを非同期で実行するためのアプリケーションサーバのサポートレベルを決定します。
動作環境で1つまたは複数のポートレットが非同期で実行されないように決定した場合は、非同期ポートレット表示をオフにするに関する節で説明されているように、非同期ポートレット表示を無効にできます。
ポートレットの非同期表示は次のファイルのプロパティ設定で制御されます。
この節では非同期表示を制御するさまざまな設定について説明します。
注記: フレームワークのservice.xmlファイルおよびconfig.xmlファイルはWEB-INF\lib\ConfigService\FrameworkService-confにあります。 ポータルのconfig.xmlファイルはWEB-INF\lib\ConfigService\PortalService-conf\config.xmlにあります。
フレームワークのservice.xmlファイルはスレッドプールの実装としてどのクラスをロードするか指定します。 スレッドプールの実装クラスはEbiThreadPoolManagerインタフェースを実装します。
<service> <interface>com.sssw.fw.api.EbiThreadPoolManager</interface> <impl-class>com.sssw.fw.core.EboThreadPoolManagerImpl</impl-class> <description>The thread pool manager for dealing with multithreading</description> <max-instances>1</max-instances> <startup>M</startup> </service>
max-instancesの設定は無視されます。 このクラスは常にシングルトンとして処理されます。
フレームワークのconfig.xmlファイルは、スレッドプールの動作を制御する複数のパラメータを指定します。
<property> <key>com.sssw.fw.api.threadpool.buffersize</key> <value>10</value> </property> <property> <key>com.sssw.fw.api.threadpool.maxthreads</key> <value>100</value> </property> <property> <key>com.sssw.fw.api.threadpool.minthreads</key> <value>4</value> </property> <property> <key>com.sssw.fw.api.threadpool.initialthreads</key> <value>10</value> </property> <property> <key>com.sssw.fw.api.threadpool.keepalifetime</key> <value>300000</value> </property> <property> <key>com.sssw.fw.api.threadpool.enabled_at_startup</key> <value>true</value> </property>
次に各設定について説明します。
ポータルのconfig.xmlファイルにはポータルの非同期処理全体を制御する複数のプロパティが含まれています。
<property> <key>com.novell.afw.portal.aggregation.default_request_timeout </key> <value>2000</value> </property> <property> <key>com.novell.afw.portal.aggregation.max_request_timeout</key> <value>2500</value> </property> <property> <key>com.novell.afw.portal.aggregation.render_synch_in_main_thread </key> <value>true</value> </property>
次に各設定について説明します。
novell-portlet.xmlファイルには各ポートレットの最大タイムアウト間隔を決定するmax-timeoutというプロパティが含まれています。
<portlet name="StockQuotePortlet">
<style>
<name>StockQuotePortletDefault</name>
<display-name>Default StockQuote Portlet Style</display-name>
<user-agent>
<device-name>Generic_HTML</device-name>
<file-name>$RESOURCE_SET$/portlet-style/StockQuote.xsl
</file-name>
</user-agent>
</style>
<requires-authentication>0</requires-authentication>
<auto-register enabled="true">
<category>General Portlets</category>
</auto-register>
<max-timeout>1000</max-timeout>
</portlet>
max-timeoutプロパティでは、ポートレットの表示要求の終了をポータルが待つ最大時間(ミリ秒単位)を設定します。
注記: 値0は-1として解釈されますが、これはこのポートレットがタイムアウト値を持たないことを意味し、デフォルトの要求タイムアウトが適用されます。
要求のタイムアウトは次のように決定されます。
手順1の値がdefault_request_timeoutとmax_request_timeoutの間の場合、その値がこの要求の最大タイムアウトとして使用されます。
手順1の値がdefault_request_timeoutより小さい場合は、この要求のタイムアウトはdefault_request_timeoutに設定されます。
手順1の値がmax_request_timeoutの値より大きい場合、max_request_timeoutの値が現在の要求のタイムアウト値として使用されます。
max_request_timeoutの設定は同期ポートレットと非同期ポートレットの両方に適用されます。 同期ポートレットは順次処理されるため、タイムアウトは各ポートレットが戻された後に確認されます。 max_request_timeoutの値に達した場合、新しい表示処理は開始されず、残った未処理の同期ポートレットすべてのコンテンツとしてデフォルトのタイムアウトメッセージが使用されます。
注記: 要求タイムアウト設定をportlet.xmlファイルの有効期限キャッシュ設定と混同しないでください。 有効期限キャッシュ設定はコンテンツのキャッシュに使用されます。
この節では、ポートレットの初期設定と設定の情報を取得する方法について説明します。
exteNd Directorが提供する柔軟なパラダイムによって、ポートレット初期設定を4つのレベルの優先度で適用できます。次に初期設定を優先度の低いものから順番にリストします。
詳細については、ポートレットの初期設定に関する節を参照してください。
初期設定を取得および設定するには通常、標準のjavax.portlet.PortletPreferencesインタフェースのメソッドを呼び出します。 これらのメソッドは指定された初期設定の値を、使用できる最高レベルの優先度で取得および設定します。
特定のレベルで優先度の初期設定を取得および設定する場合など、さらに高度なカスタマイズについてはEbiPortletInfoManagerで提供されているメソッドを参照してください。
exteNd Directorは、ポートレット設定に関する節で説明されているように、ポートレットがポータルと通信する方法を決定する設定のグループを定義します。 EbiPortletSettingsインタフェースのメソッドを呼び出すことによってこれらの値を取得および設定できます。
exteNd Directorでは、novell-portlet.xml展開記述子または関連付けられたポートレットフラグメント展開記述子で<style>要素を指定することにより、XMLコンテンツを生成するポートレットのスタイルを設定できます。
各ポートレットに指定できる<style>要素は1つですが、各スタイルにはデバイス固有のXSLスタイルシートを指す複数のユーザエージェントを組み込むことができます。
<style>要素を指定する方法の詳細については、novell-portlet.xmlの仕組みに関する節を参照するか、novell-portlet.xmlスキーマの次のコードを確認してください。
extend5 install directory\Common\Resources\SchemaCatalog\novell-portlet.xsd
exteNd Directorでは、編集モードのデフォルト実装を提供しています。
ポートレットで編集オプションを有効にしていても編集モードを明示的にサポートしていない場合、ポートレットに対して定義され、エンドユーザが編集可能なすべての初期設定の初期設定シートがexteNd Directorによって表示されます。
このデフォルトの実装を使用する場合は、次のガイドラインに従ってください。
ポートレットのポートレットフラグメント展開記述子で、目的の初期設定をすべて定義していることを確認する。
次のようにポートレットフラグメント展開記述子で編集オプションを有効にする。
<supported-option>edit</supported-option>
重要: 編集オプションを有効にしており、doEdit()メソッドを実装することによって編集モードをサポート「する」場合、次のようにポートレットフラグメント展開記述子で編集モードと編集オプションの「両方」を必ず有効にしてください。
<supports>要素の下に<portlet-mode>エントリを追加します。
<supports> <portlet-mode>edit</portlet-mode> </supports>
<supported-option>edit</supported-option>
javax.portlet.RenderResponse
にある適切なメソッドを呼び出して表示URLやアクションURLを作成する場合、PortletURL.setSecure(true)
を呼び出すことによってURLが安全なURLかどうかを設定できます。
デフォルトの安全なポートは443です。サーバが別の安全なポートを使用するように設定した場合は、ポートレットURLの作成時にexteNd Directorポータルがそのポートを使用するように指示できます。次のようにPortalService config.xmlにプロパティを追加します。
次のようにPortalサブシステム設定ファイルにプロパティを追加します。
<property> <key>portlet-url-secure-port</key> <value>444</value> </property>
exteNd DirectorのAPIでは、FrameworkサブシステムのEboCookieUtilクラスにあるメソッドを使用してポートレットのCookieの取得および設定ができます。
Cookieを取得するため、HTTP要求からポートレット要求のプロパティへヘッダを伝達するメソッドを呼び出すことができます。
メソッド |
説明 |
---|---|
getCookieValue() |
指定されたCookieの値を取得します。 |
getCookie() |
HTTP要求から指定されたCookieを取得します。 |
getCookies() |
HTTP要求からCookieのアレイを返します。 |
Cookieを設定するため、addCookieToResponse()メソッドを呼び出すことができます。このメソッドはset-cookieヘッダをPortletResponseプロパティからHTTP応答へ伝達し、さらにクライアントへ戻します。
スコープパスおよびXPathsの操作に関する章で説明されているように、要求スコープパスと応答スコープパスを使用してCookieを取得および設定することもできます。
Copyright © 2004 Novell, Inc. All rights reserved. Copyright © 1997, 1998, 1999, 2000, 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved. more ...