Oracle® Fusion Middleware Oracle WebCenter PortalおよびOracle JDeveloperでのポータルの開発 11gリリース1 (11.1.1.9.0) E49666-05 |
|
![]() 前 |
![]() 次 |
この章では、開発者がデータにアクセスして、クライアント・アプリケーションで使用できるようにするための、シンプルで拡張可能な方法を提供するサービス・アクセス・レイヤーのプロパティ・サービスについて説明します。
この章の内容は、次のとおりです。
プロパティ・サービスは、RESTまたはJava APIを介したデータの取得および更新のためのメカニズムです。リレーショナル・データベース、Oracle Metadata Service (MDS)のリポジトリ、LDAPのリポジトリなどの、任意のデータ・ソースにデータを格納できます。シナリオのコンテキストにデータをフェッチする、データ・プロバイダとは異なり(第67.1項「データ・プロバイダの概要」)、プロパティ・サービスは、シナリオのコンテキスト外のデータのフェッチおよび更新に使用できます。さらに、プロパティ・サービスでは、プロパティ・セットと呼ばれる、編成されたデータの表現を作成できます。その各々は、ネームスペースに一意に関連付けられています。プロパティ・セットは、RESTリクエストまたはJavaメソッド・コールを使用して、ネームスペースを参照するだけで検索できます。シナリオの詳細は、第66.1.1項「パーソナライズ・アーキテクチャ」を参照してください。
注意: WebCenter Portalには、便利なようにプロパティ・サービス・データ・プロバイダが用意されており、プロパティ・セットからシナリオのコンテキストにデータをフェッチできます。詳細は、第70.5項「プロパティ・サービス・データ・プロバイダの使用」を参照してください。 |
このセクションでは、プロパティ・サービスの概念を説明します。
プロパティ・サービスとその機能には、多くのユースケースが存在します。重要なユース・ケースは、複数のソースのデータを集約し、そのデータをシナリオで使用できるようにする機能です。後で説明しますが、プロパティ・サービスは、データ・プロバイダを介してコンダクタやシナリオと統合されます。データ・プロバイダは、シナリオのコンテキスト内のプロパティ・サービスから提供されたデータへのアクセスを提供します。たとえば、複数のソースからのデータで構成されたユーザー・プロファイルを作成した後、複数のシナリオでそのプロファイルを使用することが可能です。
プロパティ・セットは、簡単に言えば、関連プロパティのコレクションです。たとえば、本のコレクションを表し、ISBN番号、表題、著者、ページ数などのプロパティが含まれるプロパティ・セットが考えられます。
各プロパティ・セットには、プロパティ・セット定義と呼ばれるスキーマがあります。この定義には、ゼロ以上のプロパティ(セットのメンバー)を指定します。プロパティには、名前、詳細、データ・タイプなどがあります。プロパティ・セットは、プロパティ・セット定義をインスタンス化したものと考えられます。
図70-1に、JDeveloperのビジュアル・エディタでのプロパティ・セット定義を示します。プロパティ・セット定義の要素を、1つ1つ見ていきます。
最初に、プロパティ・セット定義が階層としてモデル化されます。JDeveloperのビジュアル・エディタを使用すると、プロパティ・セット定義が容易に作成できます。まず、階層の一番上には、ネームスペース要素が定義されています。すべてのプロパティ・セットが、ネームスペースのコンテキスト内に存在します。ネームスペースの名前を使用して、RESTリクエストまたはJavaメソッド・コールによりプロパティ・セット定義を検索できます。図70-1では、ネームスペースはmyPropertiesという名前です。
次に、プロパティ・セット定義そのものが作成され、名前が付けられます。この例では、プロパティ・セット定義はEmployeeという名前です。次の手順では、プロパティ・セット定義にプロパティ・マップを組み込みます。各プロパティ・マップには、名前、定義(データ型のようなもの)およびマップに関連付けられたロケータ・クラスがあります。図70-2に、新規プロパティ・マップの作成に使用されるダイアログと、プロパティ・マップ用に定義を選択できるドロップダウン・メニューを示します。定義には、String、StringArray、Number、Int、DateTime、その他複数のものがあります。たとえば、nameプロパティのマッピングには、String型の定義タイプを指定します。プロパティ・セットは、ユーザー・プロファイルなどの、適切に構造化されたデータのモデリングに特に役立つことがわかります。
各プロパティ・セットは、ロケータと呼ばれるJavaコンポーネントに関連付けられています。ロケータは、ILocatorクラスのカスタム実装で、プロパティ・セットのデータの取得、フィルタリングおよび更新のためのメソッドが含まれます。この意味では、ロケータはデータ・プロバイダ(第67.1項「データ・プロバイダの概要」)に似ています。REST API (またはJava API)を使用すると、モバイル・アプリケーションやポータルなどのクライアント・アプリケーションで直接データを取得できます。
注意: ロケータ・クラスは、ネームスペース・レベル、プロパティ・セット定義レベルまたは個々のプロパティ・レベルで連結できます。ロケータは、固有の優先順で解決されます。個々のプロパティに連結されたロケータは、プロパティ・セット定義レベルなどのロケータよりも優先されます。カスタム・ロケータが指定されていない場合は、デフォルトのロケータが使用されます。 |
WebCenter Portalでは、プロパティ・セットのデータを取得し、事前構成済データベースに格納する、デフォルトのプロパティ・セット・ロケータが提供されています。このデフォルト・ロケータは、プロパティ・セット用に他のロケータが指定されなかった場合のみ使用されます。使用するユース・ケースで、デフォルトのロケータでは不十分な場合は、カスタム・ロケータを開発できます。第70.7項「カスタム・ロケータの実装」も参照してください。
プロパティ・サービスには、統合されたキャッシュ・サービスと、データ検証用のコードを作成するためのインタフェースも含まれています。第70.6項「プロパティ・サービスのキャッシュ・サービスの使用」を参照してください。
コンダクタやシナリオなどの概念を熟知していない場合は、第66章「Oracle WebCenter Portalアプリケーションのパーソナライズ」を参照してください。
プロパティ・サービスが、コンダクタに直接関連付けられていないことに注意することは重要です。これは、プロパティ・サービスを使用して、シナリオのコンテキスト外のデータを取得および更新できることを意味します。ただし、WebCenter Portalでは、プロパティ・サービス・データ・プロバイダが用意されており、プロパティ・サービスのデータをシナリオに取得することが可能です。シナリオでは、データをさらにフィルタして処理し、他のシナリオのデータとともにまとめたり、ビジネス・オブジェクトなどの、他のデータ統合機能を利用したりできます。
図70-3に、ここまでの項で説明した、プロパティ・サービス全体のアーキテクチャを示します。
この項では、新規プロパティ・セット定義の作成方法について説明します。
注意: 一般的に、1つまたは複数のプロパティ・マップを伴う、明確に定義されたプロパティ定義を作成することが最良です。ただし、要素がゼロのプロパティ・セット定義にすると、動的なプロパティ・セットの作成が可能になるため、便利な場合があります。 |
注意: JDeveloperで作成されたプロパティ・セット定義は、デプロイ中にMDSにインポートされます。これらのプロパティ・セット定義に基づき、実行時に作成されたプロパティ・セットはすべて、デフォルトのデータベース(または、カスタム・ロケータにより構成されるような、他の永続性の記憶域)に格納されます。 |
JDeveloperでプロパティ・セット定義を作成するには、これらの手順に従います。
プロジェクトのクラスパスに、データ統合コンポーネントが含まれるようにします。第2.5項「パーソナライズのためのJDeveloperの設定」を参照してください。
アプリケーション・ナビゲータで、プロジェクトを右クリックし、「新規」を選択します。
「新規ギャラリ」ダイアログの「一般」カテゴリで、「パーソナライズ」を選択します。
ダイアログの「アイテム」の部分で、プロパティのネームスペースを選択して「OK」をクリックします。
プロパティのネームスペースの作成ダイアログで、ネームスペースの名前を入力します。
「プロパティ・サービス」エディタが、デザイン・ビューで開きます。図70-4に示すように、プロパティのネームスペースの定義ノードを右クリックし、新規プロパティ・セット定義の作成を選択します。
新規プロパティ・セット定義の作成ダイアログで、名前を入力して「OK」をクリックします。
新しいプロパティ・セット定義のノードを右クリックし、新規プロパティ・セット定義マップの作成を選択します。
注意: このダイアログでは、プロパティ・セット定義に含める個別のプロパティ・マップを定義できます。各プロパティ・マップがロケータ・クラスを持つことが可能なことに注意してください。デフォルトのロケータ・クラスは、デフォルトのデータベースの中でプロパティ・セットのデータを検索します。別のソースからデータを取得するには、カスタム・ロケータを実装する必要があります。詳細は、第70.7項「カスタム・ロケータの実装」を参照してください。 |
プロパティ・マップの作成/編集ダイアログで、プロパティの名前を入力します。プロパティの定義(データ型のようなもの)を選択します。たとえば、名前はStringDef型、従業員IDはIntDef (整数)型にします。プロパティのロケータ・クラスも指定できます。ロケータ・クラスを指定しない場合、プロパティではデフォルトのロケータが使用されます。第70.1.3項「ロケータについて」を参照してください。
さらにプロパティを作成する場合は、プロパティ・セット定義のノードを右クリックして、同様の手順に従います。
作業内容を保存します。
次に、プロパティ・セット定義をサーバーにデプロイする必要があります。サーバーでは新しいプロパティ・セットのインスタンス化に使用されます。
プロパティ・セット定義を作成した後は、サーバーにデプロイする必要があります。JDeveloperから、統合WebLogic Serverまたは、外部の管理対象サーバーに対してデプロイできます。プロパティ・セット定義をデプロイした後は、REST APIやJava APIを介して、またはシナリオでプロパティ・サービス・データ・プロバイダを介してアクセスできます。
この例では、統合WebLogic Serverのインスタンスに対してデプロイします。
第70.2項「JDeveloperでのプロパティ・セット定義の作成」の説明に従って、1つまたは複数のプロパティ・セット定義を作成します。
デプロイ先を決定します。ターゲットのサーバーは、稼動している必要があります。
アプリケーション・メニューから、パーソナライズ・ファイルのデプロイを選択します。
次のようにデプロイ・ターゲットを選択します。
最後に選択されたサーバーへ: 最後に選択されたサーバーにデプロイします。
サーバーへ: このオプションを使用すると、デプロイ先のサーバーを選択できます。
ファイルシステムへ: メタデータ・アーカイブ(MAR)ファイルをファイル・システムへデプロイします。このファイルは、後でサーバーにデプロイできます。
この例では、サーバーへを選択します。
「サーバーへのデプロイ」ダイアログで、「IntegratedWebLogicServer」を選択し、サーバー・インスタンスとして「DefaultServer」を選択します。
「OK」をクリックします。JDeveloperにより、所定の定義ファイルがサーバーにデプロイされます。厳密には、これらのファイルはメタデータ・アーカイブ(MAR)ファイルに配置され、さらにそのファイルがサーバーにデプロイされます。図70-6に示すように、デプロイの結果は、「デプロイメント・ログ」ウィンドウで見ることが可能です。
プロパティ・セット定義がデプロイされたので、早速デプロイをテストできます。
この項では、プロパティ・セット定義のデプロイのテストが可能な、2つの方法について考察します。
使用可能なプロパティ・セットを検索する1つの方法は、RESTリクエストを送信して、レスポンスを表示することが可能なツールを使用することです。そのようなツールやブラウザ・プラグインは多数存在します。REST APIの詳細は、第53章「Oracle WebCenter Portal REST APIの使用」を参照してください。
RESTクライアント・ツールで、このURLを入力します。ここでhostおよびportは、WCPSサーバーが稼動しているホスト名およびポート名です。
http://host:port/wcps/api/property/resourceIndex
ネームスペースのURIを検索し、そのURLをブラウザで入力します。例:
http://host:port/wcps/api/conductor/namespaces
たとえば、次のように入力します。http://myhost:7101/wcps/api/conductor/namespaces
レスポンス内で、作成したプロパティ・セットのネームスペースを検索します。たとえば、Employee_Namespace
というプロパティ・セットのネームスペースを作成した場合(第70.2項「JDeveloperでのプロパティ・セット定義の作成」を参照)のレスポンスは、図70-7に示すレスポンス同様の見かけになります。
図70-7 デプロイされたネームスペース、Employee_Namespaceを示したRESTのレスポンス
デプロイされたプロパティ・セット定義には、シナリオでプロパティ・サービス・データ・プロバイダを介してアクセスできます。詳細は、第70.5項「プロパティ・サービス・データ・プロバイダの使用」を参照してください。
プロパティ・サービス・データ・プロバイダ(oracle.PropertiesServiceProvider
)を使用すると、プロパティ・サービス・データをシナリオに統合できます。このプロバイダでは、次のことが可能です。
指定されたプロパティ・セット定義のプロパティ・セットの取得
名前によるプロパティ・セットの取得
プロパティ・セットからの指定されたプロパティの返却
プロパティ・サービス・データ・プロバイダは、その他のプロバイダと同様、次の手順でシナリオのデータ・プロバイダ・ファンクションの起動を選択して、使用します。
シナリオ・エディタで、新しいシナリオを作成します。シナリオ・エディタの使用の詳細は、第66章「JDeveloperでのパーソナライズされたシナリオの作成」を参照してください。
要求された場合、サーバーへのURL接続を作成します。「URL接続」ダイアログで、次の情報を入力します。
フィールド名 | 値 |
---|---|
名前 | Conductor |
URLエンドポイント | http://host:port/wcps/api/conductor/resourceIndex
例: http://example.com:7101/wcps/api/conductor/resourceIndex |
認証タイプ | 基本 |
ユーザー名 | weblogic |
パスワード | weblogic1 |
レルム | WCPS |
「開始」ノードをクリックして、次の文を追加を選択してから、データ・プロバイダの起動を選択します。
プロバイダの起動ノードをクリックして、起動するプロバイダのプロパティを選択します。
プロバイダの起動ダイアログで、「oracle.PropertiesServiceProvider」ノードを開いてから、「LocalServerConnection」ノードを開き、最後に「GetProperiesResource」ノードを開きます。図70-8を参照してください。
実行するメソッドを選択して、ダイアログの下部でパラメータを入力します。パラメータには、プロパティ・セットまたは取得するプロパティを指定できます。メソッドの詳細は、第70.5.2項「プロパティ・サービス・データ・プロバイダ・メソッドのリファレンス」を参照してください。
この項では、各プロパティ・サービス・データ・プロバイダ・メソッドについて説明します。これらのメソッドを使用すると、指定されたネームスペースのプロパティ・セットおよびそのプロパティにアクセスできます。
第70.5.2.2項「getProperty(namespace, definition, set, property)」
第70.5.2.5項「getPropertySets(definition, search, restrictions)」
第70.5.2.6項「getPropertySets(namespace, definition, search, restrictions)」
現在の、デフォルトのネームスペースからプロパティを取得します。
パラメータ:
definition: デフォルトのネームスペースに存在する、プロパティ・セット定義の名前
set: プロパティ・セット定義のインスタンスの名前
property: 取得するプロパティの名前
戻り値:
プロパティの型のオブジェクト。プロパティが見つからない場合は、nullを返します。
例:
getProperty("EmployeeSetDef", "kjones", "address")
指定されたネームスペースから、プロパティを取得します。
パラメータ:
namespace: ネームスペースの名前
definition: デフォルトのネームスペースに存在する、プロパティ・セット定義の名前
set: プロパティ・セット定義のインスタンスの名前
property: 取得するプロパティの名前
戻り値:
プロパティの型のオブジェクト。
例:
getProperty("NS1", "EmployeeSetDef", "kjones", "address")
現在またはデフォルトのネームスペースのプロパティ・セットを取得します。
パラメータ:
definition: デフォルトのネームスペースに存在する、プロパティ・セット定義の名前
set: プロパティ・セット定義のインスタンスの名前
戻り値:
プロパティ・セットを格納しているMapオブジェクト。
例:
getPropertySet("EmployeeSetDef", "kjones")
指定されたのネームスペースのプロパティ・セットを取得します。
パラメータ:
namespace: ネームスペースの名前
definition: デフォルトのネームスペースに存在する、プロパティ・セット定義の名前
set: プロパティ・セット定義のインスタンスの名前
戻り値:
プロパティ・セットを格納しているMapオブジェクト。
例:
getPropertySet("NS1", "EmployeeSetDef", "kjones")
指定されたプロパティ・セット定義のインスタンスである、プロパティ・セットのリストを取得します。このリストは、オプションのsearchおよびrestrictionsパラメータで操作できます。このメソッドは、現在またはデフォルトのネームスペースを検索します。
パラメータ:
definition: デフォルトのネームスペースに存在する、プロパティ・セット定義の名前
search: (オプション)入力された検索式(文字)を適用して、指定されたプロパティ・セットを取得します。nullが指定された場合、入力されたプロパティ・セットの、すべてのプロパティ・セットが取得されます(ページ区切りのコンテキスト内)。
restrictions: (オプション)プロパティのリストが指定されたListオブジェクト。このリストで指定されたもののみが取得されます。nullが指定された場合、すべてのプロパティが取得されます。
戻り値:
プロパティの型のオブジェクト。
例:
getProperty("EmployeeSetDef", "tmyProp:equals:someValue")
その他の検索文字列の例:
myFavoriteHobbies:contains:campingtps-created-on:gt:1980-01-01T00:00:00.000-070
指定されたプロパティ・セット定義のインスタンスである、プロパティ・セットのリストを取得します。このリストは、オプションのsearchおよびrestrictionsパラメータで操作できます。このメソッドは、指定されたネームスペースのみを検索します。
パラメータ:
namespace: ネームスペースの名前
definition: デフォルトのネームスペースに存在する、プロパティ・セット定義の名前
search: (オプション)入力された検索式を適用して、指定されたプロパティ・セットを取得します。nullが指定された場合、入力されたプロパティ・セットの、すべてのプロパティ・セットが取得されます(ページ区切りのコンテキスト内)。
restrictions: (オプション)プロパティのリストが指定されたListオブジェクト。このリストで指定されたもののみが取得されます。nullが指定された場合、すべてのプロパティが取得されます。
戻り値:
プロパティの型のオブジェクト。
例:
getProperty("NS1", "EmployeeSetDef", "tmyProp:equals:someValue")
その他の検索文字列の例:
myFavoriteHobbies:contains:campingtps-created-on:gt:1980-01-01T00:00:00.000-070
プロパティ・サービスには、組込みのキャッシュ・レイヤーが含まれており、プロパティ・セットが返される際に、自動的にキャッシュします。プロパティ・サービスは、頻繁に使用されるデータへの高速アクセスを提供する、インメモリー・データ・グリッド・キャッシング・ソリューションである、Oracle Coherenceを使用します。Oracle Coherenceの構成の詳細は、Oracle Coherenceのドキュメントを参照してください。
プロパティ・サービスのキャッシュ構成ファイルは、次の場所にあります。
$ORACLE_HOME/user_projects/applications/<domain>/conductor-extensions-library/WEB-INF/classes.
デフォルトのキャッシュ構成ファイルを変更することも、必要であれば他のキャッシュ構成ファイルを追加することも自由にできます。プロパティ・サービスによってインスタンス化されたキャッシュ・ファクトリはすべて、プロパティ・サービスのクラス・ローダーに固有のものです。キャッシュ構成ファイルは、次の場所にあります。
$ORACLE_HOME/user_projects/applications/<domain>/conductor-extensions-library/WEB-INF/classes.
構成は、エンド・ユーザーのニーズに合わせて変更できますが、キャッシュの名前は変更しないでおく必要があります。
各プロパティ・セットは、ロケータと呼ばれるJavaコンポーネントに関連付けられています。ロケータは、ILocatorクラスのカスタム実装で、プロパティ・セットのデータの取得、フィルタリングおよび更新のためのメソッドが含まれます。使用するユース・ケースで、デフォルトのロケータでは不十分な場合は、カスタム・ロケータを開発できます。
この項では、単純なカスタム・ロケータの実装方法、構成方法および起動方法について説明します。これは非常に基本的な例ではありますが、カスタム・ロケータの開発および使用の多くの重要な側面について説明しています。
ロケータ全般の概要は、第70.1.3項「ロケータについて」を参照してください。
JDeveloperでのカスタム・ロケータの開発を始める前に、適切に設定が行われていることを確認します。いくつかの構成は、使用する環境で構成を行うか、確認する必要があります。詳細は、第2.5項「パーソナライズのためのJDeveloperの設定」を参照してください。
注意: この例では、ロケータはJDeveloperのFusion Webアプリケーションの状態で作成されています。ファンクション・プロバイダは、WebCenter Portalアプリケーションや、Javaの機能が組み込まれた、他の任意のタイプのJDeveloperアプリケーションの状態で作成することも可能です。 |
例を使用して、本に関連するデータ(著者、表題、IBSN番号など)にアクセスするロケータの作成方法を説明します。ここでは、Javaクラスに生データが単純にハードコードされていますが、ロケータを同様に作成してデータベース内のデータにアクセスするようにできます。
一般的に使用される手法である、ロケータからのデータ・アクセスを委任するデータ・アクセス・オブジェクト(DAO)のパターンも使用して説明します。データが蔵書でも、ユーザーのデータベースでも、在庫システムでも、同様のパターンが適用できます。
主な手順は次のとおりです。
Bookプロパティ・セット定義を定義します。
Bookプロパティ・セット定義に関してプロパティ・サービスへ通知します。
IPropertyLocatorインタフェースを実装して、Bookオブジェクトからプロパティをロードします。
第70.2項「JDeveloperでのプロパティ・セット定義の作成」の全体的な手順に従い、次の3つの部分のある、新しいプロパティ・セット定義を作成します。
ネームスペースbook.property.locatorのコール
プロパティ・セット定義BookPropertySetDefinitionのコール
title、authorおよびISBNという、3つのStringDef型のプロパティ・マッピングの追加
図70-9に、JDeveloperのビジュアル・エディタでのこの単純な定義を示します。
ここからは、デフォルトのロケータ・クラスを使用します。後ほど、デフォルトから新しいカスタム・ロケータの実装を使用するように変更します。
例70-1のクラスでは、ハードコードされた、静的なbookデータから単純にマップを作成します。本の表題が、マップのキーとして使用されています。実際のユース・ケースでは、ライブラリ・データベースなどの、外部のデータ・ソースからデータを取得します。
例70-1 Bookデータを作成するクラス
package locator; import java.util.HashMap; import java.util.Map; class Library { static String [] titles = {"Into Thin Air", "Climbing Everest", "Rocky Mountains"}; static String [] ISBNs = {"0-201-69581-2", "0-423-78123-1", "0-321-23425-2"}; static String [] authors = {"Jon Krakauer", "Fooey Handley", "Rick Bicknell"}; // Keyed by title private static Map<String, Book> library = new HashMap<String,Book>(); static void generateLibrary() { for (int i=0; i<titles.length; i++) { Book book = new Book(titles[i], authors[i], ISBNs[i]); library.put(book.getTitle(), book); } } static Book getBook(String title) { return library.get(title); } }
例70-2のJavaBeanクラスでは、Libraryクラス(表題、著者およびISBN番号)にハードコードされたbookの属性を示しています。例のコードを簡略化するため、getProperty(String name)メソッドを追加しました。実際には、JavaBeanイントロスペクションがよりよい方法です。
例70-2 Bookデータを表現する単純なJavaBean
package locator; public class Book { String title; String author; String ISBN; public Book(String title, String author, String ISBN) { setTitle(title); setAuthor(author); setISBN(ISBN); } public void setTitle(String title) { this.title = title; } public String getTitle() { return title; } public void setAuthor(String author) { this.author = author; } public String getAuthor() { return author; } public void setISBN(String ISBN) { this.ISBN = ISBN; } public String getISBN() { return ISBN; } String getProperty(String propName) { if (propName.equals("ISBN")) { return getISBN(); } if (propName.equals("title")) { return getTitle(); } if (propName.equals("author")) { return getAuthor(); } return null; } }
DAOクラスは前述のクラスよりも魅力的です。ここでは、DAOはソースからデータをフェッチするという大変な作業をします。この場合のソースは、作成したLibraryオブジェクトですが、データベース、RESTサービスまたは他のソースにすることも可能です。
例70-3 データ・アクセス・オブジェクトの実装
package model; import java.util.ArrayList; import java.util.List; import java.util.Map; import oracle.wcps.property.IContext; import oracle.wcps.property.IProperty; import oracle.wcps.property.IPropertyDefinition; import oracle.wcps.property.IPropertyDefinitionName; import oracle.wcps.property.IPropertyMapping; import oracle.wcps.property.IPropertyName; import oracle.wcps.property.IPropertyService; import oracle.wcps.property.IPropertySet; import oracle.wcps.property.IPropertySetDefinition; import oracle.wcps.property.ServiceFactory; import oracle.wcps.property.Type; import oracle.wcps.property.model.Property; class BookPropertyDAO { IPropertyService service; // Generate the library that will provide our backing store. static { Library.generateLibrary(); } /** * Assume the name of the PropertySet is the title of the book. */ void loadProperties(IPropertySet propertySet, IPropertySetDefinition iPropertySetDefinition, List<IPropertyName> propertyNames, IContext context) throws Exception { String title = propertySet.getName().getName(); Book book = Library.getBook(title); loadProperties(book, propertySet, iPropertySetDefinition, propertyNames, context); } private void loadProperties(Book book, IPropertySet propertySet, IPropertySetDefinition iPropertySetDefinition, List<IPropertyName> propertyNames, IContext context) throws Exception { Map<IPropertyName, IPropertyMapping> mappings = iPropertySetDefinition.getPropertyMappings(); // Null propertyNames is valid, and indicates to get all properties if (propertyNames==null) { propertyNames = new ArrayList<IPropertyName>(); propertyNames.addAll(mappings.keySet()); } // Loop over all property names, create a Property value, and add it to the Property set // for (IPropertyName pname : propertyNames) { String value = book.getProperty(pname.getName()); if (value != null) { IPropertyMapping mapping = mappings.get(pname); addProperty(value, pname, propertySet, mapping, context); } } } // Add typed properties according to the information in our mappings private void addProperty(String value, IPropertyName pname, IPropertySet propertySet, IPropertyMapping mapping, IContext context) { // The property mappings could be useful if we wanted to get the individual //PropertyDefinitions and inspect their type. IPropertyDefinitionName pdefName = mapping.getPropertyDefinitionName(); // We need the namespace to look up our property definitions if (service==null) { String ns = propertySet.getNamespaceName().getName(); System.err.println("Using namespace: " + ns); //service = ServiceFactory.getPropertyService(IContext.NULL, ns); service = ServiceFactory.getPropertyService(context, ns); } IPropertyDefinition pdef = service.getPropertyDefinition(context, pdefName); //service.getPropertyDefinition(IContext.NULL, pdefName); Type type = pdef.getType(); IProperty ps = Property.builder().withProperty(pname, value, type).build(); System.err.println("Adding " + ps.getName() + " of type " + ps.getType()); propertySet.putProperty(pname, ps); } }
最後に例70-4に、ロケータ・クラスそのものを示します。最初に注目するのは、ILocatorが実装されていることです。このインタフェースには、ロケータのすべてのCRUD (作成、取得、更新、削除)操作を可能にする、複数のメソッドが含まれます。ただし、この例では、読取り操作に相当するloadProperties()のみが実装されています。このインタフェースの詳細は、WebCenter Portal APIリファレンス(Javadoc)で参照できます。
もうひとつ重要な点は、loadProperties()メソッドがDAOに委任することです。DAOのクラスには、loadProperties()というまったく同じメソッドがあり、ライブラリ・データ・ストアからのデータのフェッチ動作を行います。
例70-4 ロケータ・クラスの例
package locator; import java.util.List; import java.util.Map; import oracle.wcps.property.IContext; import oracle.wcps.property.INamespaceName; import oracle.wcps.property.IPagedList; import oracle.wcps.property.IPropertyLocator; import oracle.wcps.property.IPropertyMapping; import oracle.wcps.property.IPropertyName; import oracle.wcps.property.IPropertySet; import oracle.wcps.property.IPropertySetDefinition; import oracle.wcps.property.IPropertySetDefinitionName; import oracle.wcps.property.filter.PropertySetFilterContext; import oracle.wcps.property.filter.expression.PropertySetExpression; public class BookPropertyLocator implements IPropertyLocator { private BookPropertyDAO dao; // Must have a public default constructor, since the Property Service instantiates // this public BookPropertyLocator() { dao = new BookPropertyDAO(); } /** * Load property values, optionally returning only a subset of those. * @param context the IContext containing parameters passed in from the PropertyService * @param iPropertySet The PropertySet into which the retrieved values will be loaded * @param iPropertySetDefinition The PropertySetDefinition defining the 'shape' of the properties * @param propertyNames List of PropertyNames to load. If null, all will be loaded. */ public void loadProperties(IContext context, IPropertySet iPropertySet, IPropertySetDefinition iPropertySetDefinition, List<IPropertyName> propertyNames) { try // Delegate to BookProperDAO dao.loadProperties(iPropertySet, iPropertySetDefinition, propertyNames, context); } catch (Exception e) { throw new RuntimeException("Cannot load properties ", e); } } /** * Filter properties; load/return those properties that only match the filter criteria. * @param context the IContext containing parameters passed in from the PropertyService * @param iNamespaceName * @param iPropertySetDefinitionName * @param propertySetFilterContext * @return */ public IPagedList<IPropertySet> filter(IContext context, INamespaceName iNamespaceName, IPropertySetDefinitionName iPropertySetDefinitionName, PropertySetFilterContext propertySetFilterContext) { return null; //To Be Implemented } // As a read-only implementation, we don't support this public void storeProperties(IContext context, IPropertySet iPropertySet, IPropertySetDefinition iPropertySetDefinition, List<IPropertyName> list) { throw new UnsupportedOperationException("BookPropertyLocator is read-only"); } // As a read-only implementation, we don't support this public void removeProperties(IContext context, IPropertySet iPropertySet, List<IPropertyName> list) { throw new UnsupportedOperationException("BookPropertyLocator is read-only"); } // As a read-only implementation, we don't support this public void removeProperties(IContext context, INamespaceName iNamespaceName, IPropertySetDefinitionName iPropertySetDefinitionName) { throw new UnsupportedOperationException("BookPropertyLocator is read-only"); } public int count(IContext context, INamespaceName p1, IPropertySetDefinitionName p2, PropertySetExpression p3) { return 0; } } ;
ILocatorインタフェースのloadProperties()メソッドについて、もう少し詳しく見てみます。このメソッドでは、次のパラメータ型を取ります。
IContext: IContextオブジェクトは、認証のための媒体です。この型のオブジェクトは、プロパティ・サービスから渡されます。ログイン済のユーザーの、ユーザー名とパスワード資格証明などのデータが含まれます。たとえば、次のようにユーザー名とパスワードを取得できます。
String u = context.getProperty(IContext.USERNAME_KEY); string p = context.getProperty(IContext.PASSWORD_KEY);
また、requestオブジェクトを取得して、資格証明や他のリクエスト情報の取得に使用することも可能です。
HttpServletRequest request = context.getProperty(IContext.HTTP_REQUEST_KEY)
IPropertySet: 取得されたプロパティ・セットの値は、このオブジェクトにロードされます。
IPropertySetDefinition: データの構造を定義するオブジェクトです。この構造は、前の第70.7.2「プロパティ・セット定義の作成」で作成したPropertySetDefinitionに基づいています。
List<IPropertyName>: このオブジェクトでは、ロードのためにPropertyNameオブジェクトのリストが提供されます。nullの場合、すべてのPropertyNameオブジェクトがロードされます。
クラスの例が完成したので、コンパイル、デプロイおよびロケータの使用が可能になりました。
前述のプロパティ・セット定義の作成の際は、デフォルトのロケータを使用しました。カスタム・ロケータを実装したので、これを定義に追加する必要があります。
使用するプロジェクトの「リソース」フォルダで、ns_book.property.locator.xml
ファイルを探します。
デザイン・ビューで「ロケータ」ノードを右クリックし、ロケータ情報の編集を選択します。
図70-10に示すように、「追加」アイコン(プラスのシンボル)をクリックし、「新規ロケータ」ダイアログでBookPropertyLocatorと入力して、「OK」をクリックします。
ロケータ・マップの構成ダイアログで、未割当てのプロパティを「ロケータに割り当てられたプロパティ」リストに追加します。追加が完了すると、author、titleおよびISBNが割り当てられたプロパティとして表示されます。
「OK」をクリックします。
これでデザイン・ビューのロケータ情報ノードに、カスタム・ロケータが表示されるようになりました。
作業内容を保存します。
デプロイする前には、方法は問いませんが、プロジェクトをコンパイルするのが決まりです。たとえば、JDeveloperなら、「ビルド」メニューから「メイク」を選択できます。
作成したプロパティのネームスペース定義をサーバーにデプロイするには、第70.3項「プロパティ・セット定義のデプロイ」の手順に従ってください。
次の手順に従って、カスタム・ロケータ・クラスもサーバーにデプロイする必要があります。
この項は、ユーザーがJDeveloperでのJARファイルの作成に不慣れな場合、JARファイル構造(デプロイメント・プロファイル)の設定方法を説明し、必要な要素がすべて含まれるようにするものです。
アプリケーション・ナビゲータで、プロジェクト(この例では、Modelというプロジェクト)を右クリックし、「プロジェクト・プロパティ」を選択します。
「プロジェクト・プロパティ」ダイアログで「デプロイ」を選択します。
「新規」をクリックします。
「アーカイブ・タイプ」として「JARファイル」を選択し、JARの名前を入力します。
「OK」をクリックします。
「JARオプション」ダイアログで、「コントリビュータ」を選択します。
図70-11に示すように、「プロジェクトの出力ディレクトリ」、「プロジェクトのソースパス」および「プロジェクトの依存性」が選択されていることを確認します。
「フィルタ」を選択します。
「パターン」タブを選択します。
「パターン」タブで、次のファイル・パターンを追加し、特定のタイプのファイルのJARへの組込みおよび除外を行います。
図70-12に、リストに追加後のこれらのパターンを示します。
対象: **.class
対象外: **.java
対象外: **.txt
対象外: **.html
「OK」をクリックしてから、「プロジェクト・プロパティ」ダイアログの「OK」をクリックします。
プロジェクトを保存します。
JARデプロイメント・プロファイルを設定したら、プロジェクトからのJARファイルの生成は準備完了です。
アプリケーション・ナビゲータで、プロジェクト(この場合、Modelプロジェクト)を右クリックし、「デプロイ」を選択します。
デプロイするJARファイルを選択します。これは、第70.7.8.1項「JARファイル構造の設定」でファイルに指定した名前です。
「デプロイメント・アクション」ダイアログで、「JARファイルにデプロイ」を選択して「終了」をクリックします。
JARファイルがプロジェクト・ディレクトリに配置されます。このファイルは、ファイル・システムの<Workspace_Directory>/Model/deploy
で確認できます。たとえば、MyProvidersというワークスペースの場合、JARはC:\JDeveloper\mywork\MyProviders\Model\deploy
にあります。
JARファイルは、サーバーにコピーする必要があります。
前の手順で作成したJARファイルをコピーします。前述したとおり、ファイルは<Workspace_Directory\Model\deploy
に配置されています。
JARファイルを、サーバーのデフォルト・ドメインの次の場所に貼り付けます。
$DOMAIN_HOME/locator-extensions-library/WEB-INF/lib
例:
C:\JDeveloper\system11.1.7.40.63.82\DefaultDomain\locator-extensions-library\WEB-INF\lib
サーバーを再起動します。
これらの基本的な手順に従って、シナリオを作成します。シナリオの作成の詳細は、第66.2.2項「JDeveloperでのパーソナライズされたシナリオの作成」を参照してください。
BookPropertyScenarioという新しいシナリオを作成します。
シナリオに、Invoke Providerノードを追加します。
プロバイダのプロパティを編集します。
既知のプロバイダのリストの中から「oracle.PropertiesServiceProvider」ノードを開き、プロバイダのメソッドまでたどります。
GetProperty(namespace, definition, set, property)メソッドを選択します。
次のパラメータ値を追加します。
プロバイダ・プロパティの編集ダイアログで、忘れずに戻り値を指定してください。この例では、変数property
をコールします。
return文を作成して、プロパティの値を返します。戻り変数には、次のような式言語(EL)の書式を使用する必要があることに注意してください。${property}
シナリオを保存して実行します。
前の項で作成したシナリオのXMLソース・コードは、次のようになります。
<scenario:scenario xmlns:common="http://xmlns.oracle.com/wcps/conductor/common/1.0.0" xmlns:scenario="http://xmlns.oracle.com/wcps/conductor/scenarios/1.0.0"> <body> <call-provider> <provider-name>oracle.PropertiesServiceProvider</provider-name> <method-name>GetProperty</method-name> <variable>property</variable> <input> <parameter> <common:name>namespace</common:name> <common:value>book.property.locator</common:value> </parameter> <parameter> <common:name>definition</common:name> <common:value>BookPropertySetDefinition</common:value> </parameter> <parameter> <common:name>set</common:name> <common:value>Into Thin Air</common:value> </parameter> <parameter> <common:name>property</common:name> <common:value>ISBN</common:value> </parameter> </input> </call-provider> <return> <expression>${property}</expression> </return> </body> <name>BookPropertyScenario</name> </scenario:scenario>