Oracle® Fusion Middleware Oracle WebCenter Portal開発者ガイド 11g リリース1 (11.1.1.6.0) B72084-01 |
|
![]() 前 |
![]() 次 |
WebCenter Portalのパーソナライズによって、ターゲット・コンテンツがユーザーとアプリケーションの両方のコンテキストに基づいて提供されます。また、WebCenter Portalのパーソナライズによって、アプリケーション・フローの宣言型定義を可能にするランタイム・システムと関連ツールが提供されます。
この章では、パーソナライズをWebCenter Portal: Frameworkアプリケーションに統合する方法について説明します。内容は次のとおりです。
パーソナライズの詳細は、次を参照してください。
"『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のパーソナライズ・サービスの管理に関する項
パーソナライズによって、WebCenter Portalアプリケーションで、動的に導出されたユーザー・エクスペリエンスが提供されます。パーソナライズでは、入力データの定義済ソースが評価され、その評価に基づく決定が生成された後、その情報が宣言的に定義されたパーソナライズ・シナリオに適用されます。たとえば、パーソナライズでは、特定のユーザーのアプリケーション体験をターゲットとし、そのユーザーに関する人事管理データベース内の情報に基づいて、コンテンツを戻したり、アプリケーション・フローを変更したりできます。
この項では、パーソナライズの機能と要件の概要について説明します。内容は次のとおりです。
図67-1は、パーソナライズのアーキテクチャと、パーソナライズを構成するデフォルトのサービスおよびコンポーネントを示しています。これらについて、およびパーソナライズのその他のコンポーネントについては、次を参照してください。
この項では、パーソナライズ・コンダクタの役割について説明します。パーソナライズ・エンジンの中心であるコンダクタは、シナリオと呼ばれる作業単位を含み、それらを実行します。コンダクタは、準備済のシナリオを実行し、コンダクタに接続するプロバイダ拡張機能へのアクセスを提供します。次の項では、コンダクタのこれらの側面について説明します。
シナリオは、JDeveloperのシナリオ・エディタを使用して作成された(またはXMLファイルとして提供された)スクリプトによって定義されます。またシナリオは、条件文を評価し、コンテンツをなんらかの形式で(クライアントに)戻すことができる単純な構文に基づいています。スクリプトのアクションは、ファンクション・プロバイダの式を基に、データ・プロバイダと問合せを使用して、フィルタ処理されたコンテンツをクライアント・アプリケーションに戻すことができます。また、シナリオを、ターゲット・コンテンツを戻すためではなく、アプリケーション・フローの動的な変更に使用することによって、パーソナライズされたユーザー・エクスペリエンスをアプリケーション内で提供することもできます。
JDeveloperでは、シナリオ・エディタを使用して、シナリオをグラフィカルに設計できます。また、XMLファイル・ベースのシナリオを作成することもできます。シナリオの作成の詳細は、第67.2.2.4項「ノード・タイプを使用したシナリオ・フローの指定」および第67.2.3項「ファイル・ベースのシナリオの作成」を参照してください。
コンダクタ内で実行されるシナリオでは、特定のユーザーをターゲットとしたコンテンツを戻すだけでなく、アプリケーション・フローを制御したり、ユーザー・インタフェース・コンポーネントをレンダリングしたり、アプリケーション関連イベントを実行したりすることもできます。コンダクタのパブリックJavaおよび式言語(EL) APIを使用すると、既存のJavaアプリケーションやWebベースのアプリケーションとのシームレスな統合を実現できます。JavaおよびEL APIの使用の詳細は、第68章「パーソナライズAPIの外部的な使用」を参照してください。
プロパティ・サービスは、プロパティ・セットを使用してユーザーまたはアプリケーション・データのセットを編成し、プロパティ定義を使用してプロパティ・データにデータ型を割り当てます。プロパティ・サービスを拡張すると、企業のLDAPリポジトリに格納されている他のユーザー・プロファイル・データにアクセスしたり、Oracle MDSなどの他のリポジトリにアクセスしたりできます。プロパティ・サービスとプロパティ・セットの詳細は、第67.1.3項「パーソナライズ・プロパティ・サービス」を参照してください。
プロバイダによって、シナリオ内の外部リソースにアクセスする方法が提供されます。コンダクタでは、プロパティ・サービス、Content Serverプロバイダ(CMIS)およびアクティビティ・グラフに対応した3つのデフォルト・プロバイダだけでなく、シナリオ内からのカスタム・プロバイダの実装とそれらへのアクセスを可能にする、拡張可能なアーキテクチャもサポートされます。プロバイダの詳細は、第67.1.4項「パーソナライズ・プロバイダ」を参照してください。
この項では、パーソナライズ・プロパティ・サービスについて説明します。このプロパティ・サービスによって、開発者は単純でスケーラブルな方法を使用して、ユーザー・データにアクセスできるようになります。
この項の内容は、次のとおりです。
プロパティ・サービスは、JavaおよびREST APIを使用して、ユーザーに関するプロパティ(年齢や性別など)やその他の情報(現在の時間など)を格納および取得します。これらのプロパティは、プロパティ・セットの一部です。プロパティ・セットでは、スキーマを定義できます(スキーマによってプロパティのタイプが定義されます)。また、スキーマを含まないプロパティ・セットをオンデマンドで作成することもできます。プロパティ・セットには、アイデンティティ・ストアLDAPサーバー、ファイルなど様々な場所から、あるいはSQL問合せを使用して取得されたプロパティを含めることができます。JavaおよびREST APIの使用の詳細は、第68章「パーソナライズAPIの外部的な使用」を参照してください。
プロパティ・サービスは、デフォルトのパーソナライズ・キャッシュ(使用可能な場合はCoherenceキャッシュ)を使用し、デフォルトでプロパティ・セットをデータベースに格納します。また、プロパティ・サービスは拡張可能なため、Oracle MDSなどの追加リポジトリを構成することもできます。
プロパティ・サービスは、プロパティ・セットを使用してユーザーまたはアプリケーション・データのセットを編成し、プロパティ定義を使用してプロパティ・データにデータ型を割り当てます。プロパティ・サービスを拡張して、企業のLDAPリポジトリに格納されている既存のユーザー・プロファイル・データへのアクセスを可能にすることもできます。プロパティ・セットの詳細は、第67.2.2.5項「プロパティ・セットとプロパティ・ロケータの定義」を参照してください。WebCenter Portalアプリケーション用のJDeveloperプロジェクトでは、プロパティ・セット・エディタによって、namespace
、PropertySet
およびProperty
の定義を含むプロパティ・ネームスペース・ファイルが作成されます。
プロパティ・ロケータは、プロパティ・サービスによって起動され、プロパティの外部ストアにアクセスします。たとえば、パーソナライズによって提供される、デフォルトのピープル・コネクション・プロパティ・ロケータは、ピープル・コネクションRESTサービスを使用して、ユーザーのプロファイル情報にアクセスします。プロパティ・ロケータの詳細は、第67.2.2.5項「プロパティ・セットとプロパティ・ロケータの定義」を参照してください。ピープル・コネクション・プロパティ・ロケータの詳細は、第67.1.4.1.4項「ピープル・コネクション・ロケータ」を参照してください。
プロバイダは、外部サービスとの通信を可能にする、コンダクタ用のインタフェース・ポイントです。パーソナライズによって、プロパティ・サービス、Oracle WebCenter Content: Content Serverおよびアクティビティ・グラフに対応したデフォルト・プロバイダと、プロパティ・サービス・プロバイダがピープル・コネクションとの統合を実現するために使用するロケータが提供されます。また、データ・プロバイダおよびファンクション・プロバイダという実装可能な2つのタイプのカスタム・プロバイダも提供されます。
この項では、デフォルト・プロバイダと2つのタイプのカスタム・プロバイダについて説明します。内容は次のとおりです。
この項では、シナリオ内からアクセスできるデフォルト・プロバイダについて、およびプロパティ・サービス・プロバイダがピープル・コネクションとの統合を実現するために使用するロケータについて説明します。
この項の内容は、次のとおりです。
プロパティ・サービス・プロバイダを使用すると、プロパティ・サービスとの統合を実現できます。また、このプロバイダを使用すると、特定のプロパティ・セット定義に対応したプロパティ・セットを取得したり、名前でプロパティ・セットを取得したり、プロパティ・セットから特定のプロパティを戻したりできます。プロパティ・サービス・プロバイダの詳細は、第67.2.2.8.1項「プロパティ・サービス・プロバイダの使用」を参照してください。
CMISプロバイダでは、標準ベースのCMIS (Content Management Interoperability Services)コンテンツ・サーバー(特にOracle WebCenter Content Server)からコンテンツを検索および取得するためのサービスが提供されます。また、CMISプロバイダでは、結果を単純な形式に変換するためのユーティリティ・ファンクション・プロバイダも提供されます。CMISプロバイダの統合の詳細は、第67.2.2.8.2項「CMISプロバイダの使用」を参照してください。Content Serverプロバイダの接続構成の作成および編集の詳細は、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のRESTサービス・アイデンティティ・アサータの構成に関する項を参照してください。
アクティビティ・グラフ・プロバイダ(ActivityGraphProvider)では、アクティビティ・グラフ・エンジン(アクティビティ・グラフ・サービスの基礎)との統合が提供されます。これにより、WebCenter内での分析に基づいて推奨された接続先の候補がユーザーに提供されます。たとえば、アクティビティ・グラフ・プロバイダ・メソッドrecommendedUsers
は、特定のユーザーの接続先として考えられるユーザーのリストをアクティビティ・グラフ・エンジンに問い合せます。
アクティビティ・グラフ・エンジンは、エンタープライズ・アプリケーションによって収集されるアクションの中央リポジトリを提供します。アクティビティ・グラフ・サービスとアクティビティ・グラフ・エンジンの詳細は、第46項「アクティビティ・グラフ・サービスの統合」を参照してください。
アクティビティ・グラフ・プロバイダは、WebCenter Portal: Spacesサーバー上で実行される、2つのアクティビティ・グラフ用RESTサービスに基づいて構築されているため、環境内にWebCenter Portal: Spacesをインストールする必要があります。シナリオへのアクティビティ・グラフ・プロバイダの統合の詳細は、第67.2.2.8.3項「アクティビティ・グラフ・プロバイダの使用」を参照してください。アクティビティ・グラフ・プロバイダの接続構成の作成および編集の詳細は、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のアクティビティ・グラフ・プロバイダの構成に関する項を参照してください。
ピープル・コネクション・ロケータは、プロパティ・プロバイダがWebCenter People Connectionsサービスとの連携を実現するために使用するILocatorです。ピープル・コネクション・サービスのメリットの1つは、WebCenter Portal: Spaces上に格納されているユーザー・プロファイル情報にアクセスできることです。ピープル・コネクション・サービスの詳細は、第VI部「ピープル・コネクション・サービスの使用」を参照してください。ピープル・コネクション・ロケータの詳細は、第67.2.2.8.1項「プロパティ・サービス・プロバイダの使用」を参照してください。ピープル・コネクション・ロケータの接続構成の作成および編集の詳細は、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のOracle People Connectionsロケータの構成に関する項を参照してください。
データ・プロバイダは、コンダクタのアーキテクチャに接続し、なんらかのサービスのかわりに機能するコンポーネントです。データ・プロバイダから戻されたデータは、そのまま(Javaクラスとして)使用することも、連結して同じシナリオに含まれる他のデータ・プロバイダへの入力として使用することもできます。
プロパティ・サービス・プロバイダ、アクティビティ・グラフ・プロバイダおよびCMISプロバイダは、すべてデフォルトで提供されるデータ・プロバイダです。ただし、データ・プロバイダ(oracle.wcps.conductor.provider.IDataProvider
)では、従来のシステムや外部データ・ストアとの統合などを目的としたカスタム・データ・プロバイダを記述できる、コンダクタ用の拡張ポイントも提供されます。カスタム(またはデフォルト)・データ・プロバイダは、シナリオ内から「プロバイダの起動」
ノードを使用してコールできます。
通常、データ・プロバイダは、特定のユーザーの入力コンテキストまたは外部のアプリケーション・データ・セット(またはその両方)で動作します。パーソナライズに含まれるプロパティ・サービスでは、ユーザーまたはアプリケーション・データに合ったタイプのデータ記憶域を提供できます。プロバイダへの入力として、このプロパティ・サービスにアクセスできます。独自のデータ・プロバイダの作成の詳細は、第67.4.1項「カスタム・プロバイダの追加」を参照してください。
ファンクション・プロバイダ(oracle.wcps.conductor.provider.IFunctionProvider
)では、式言語(EL)式を使用して起動できるユーティリティ・メソッド(データの操作と変換、ビジネス・ルールの計算などの用途があります)の作成を目的とした、コンダクタ用の拡張ポイントも提供されます。単純な例は、${strings:concat('string1','string2')}
)です。CMISプロバイダとアクティビティ・グラフ・プロバイダには、それぞれ、その他のユーティリティとして特に、データ変換を容易にする独自のファンクション・プロバイダがあります。パーソナライズELの詳細は、付録G「パーソナライズ・サービス関連のEL」を参照してください。
この項では、Frameworkアプリケーションにパーソナライズを統合する方法について説明します。
この項の内容は、次のとおりです。
この項では、JDeveloperを使用して、パーソナライズ・サービスを統合するWebCenter Portalアプリケーションを開発するための、設計時のシステム要件と依存性について説明します。パーソナライズの要件、依存性およびオプションの全リストは、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のパーソナライズの前提条件に関する項を参照してください。
シナリオ内でCMISプロバイダ、アクティビティ・グラフ・プロバイダまたはピープル・コネクション・ロケータを使用している場合は、WebCenter Portal: Spacesをインストールする必要があります。基本的な反復開発の場合、ドメインにWebCenter Portal: Spacesをインストールする必要はありません。
REST APIを使用するには、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』の最初に行う必要がある構成に関する項に記載されている手順を実行する必要があります。
パーソナライズでは、WebCenterトラスト・サービスによって、CMISプロバイダ経由でアクセスされるOracle WebCenter Content: Content Serverなど、WebCenterドメインに含まれる様々な管理対象サーバー間のシングル・サインオン(SSO)が提供されます。JDeveloperの統合ドメインの場合、DefaultDomain/scrpts-wcps
ディレクトリにあるWLSTスクリプト(configureWCPS.py
)を使用して、トラスト・サービスを構成する必要があります。このスクリプトを使用したWebCenterトラスト・サービスとシングル・サインオンの構成の詳細は、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のシングル・サインオンの構成に関する項を参照してください。
RESTサービスを構成する必要があります。RESTサービスを構成する方法の詳細は、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』の「RESTサービスの管理」の章を参照してください。
注意: 必要に応じて、アクティビティ・グラフとピープル・コネクションに対応したデフォルト・プロバイダをアプリケーションに含めることができますが、結果をJDeveloper内でテストすることはできません。また、これらのプロバイダは一部のみ構成されるため、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のOracle People Connectionsサービスの構成に関する項とアクティビティ・グラフ・サービスの構成に関する項の説明に従って、プロバイダの構成を完了する必要があります。 |
この項では、JDeveloperのパーソナライズ・ツールを使用して、パーソナライズされたシナリオを作成する方法について説明します。内容は次のとおりです。
プロパティ・ネームスペース・ファイルには、独自に定義するプロパティ定義とプロパティ・セット定義が含まれます。
JDeveloperでプロパティ・ネームスペース・ファイルを作成する手順は次のとおりです。
JDeveloper内のアプリケーションで、ナビゲーション・バーにあるそのアプリケーションを右クリックします。
「新規ギャラリ」ダイアログが表示されます(図67-3を参照)。
注意: 「パーソナライズ」カテゴリが表示されない場合は、「すべてのテクノロジ」タブを開いてそれを選択するか、「選択済のテクノロジ」をクリックしてプロジェクトにパーソナライズ・テクノロジを追加します。 |
「プロパティ・ネームスペース」を選択し、「OK」をクリックします。
「ネームスペースの作成」ダイアログが表示されます(図67-4を参照)。
ネームスペースの名前を入力し、「デフォルト・プロパティ定義を含める」チェック・ボックスを選択して、初期のデフォルト・プロパティ定義をネームスペースに追加した後、「OK」をクリックします。
「デフォルト・プロパティ定義を含める」チェック・ボックスによって、初期のデフォルト・プロパティ定義がネームスペース・ファイルに追加されるかどうかが制御されます。これらは、IntDef
、NumberDef
、StringDef
、BooleanDef
、DateTimeDef
、ClobDef
、IntArrayDef
、NumberArrayDef
、StringArrayDef
、BooleanArrayDef
、DateTimeArrayDef
およびClobArrayDef
です。プロパティ定義は、後から必要に応じて削除できます。または、チェック・ボックスを選択解除して、初期のプロパティ定義がない状態で作業を開始し、必要に応じてシナリオ・エディタで定義を作成することもできます。
設計ペインにネームスペース・ファイルがグラフィック形式で表示されます(図67-5を参照)。
第67.2.2.2項「プロパティ・セットとプロパティ定義の作成」の説明に従って、シナリオ内で必要になるプロパティ・セットとプロパティを定義します。
プロパティは、シナリオのフロー内で条件の評価基準にできる人や物に関するデータです。たとえば、プロパティには人の年齢や性別が含まれる場合があります。プロパティ・セットは、簡単に言えば、関連プロパティのコレクションまたはコンテナです。
プロパティ・セットと関連プロパティを定義する手順は次のとおりです。
JDeveloperのアプリケーション内で、設計ペインのネームスペースを右クリックし、「新規プロパティ・セット定義の作成」を選択して、「OK」をクリックします。
「新規プロパティ・セットの作成」ダイアログが表示されます(図67-6を参照)。
プロパティ・セットの名前を入力し、「OK」をクリックします。
設計ペインに、新しいプロパティ・セットのノードが表示されます(図67-7を参照)。
プロパティを新しいプロパティ・セットに追加するには、プロパティ・セットを右クリックし、「新規プロパティ定義マッピングの作成」を選択します。
「プロパティ定義の作成」ダイアログが表示されます(図67-8を参照)。
「プロパティ名」と「定義」(値タイプ)を入力し、「OK」をクリックします。
新しいプロパティ定義を作成するには、「定義」ドロップダウン・リストのNew Definition
を選択します。
新しいプロパティが、プロパティ・セットのグラフィック表現の一部として表示されます(図67-9を参照)。
他に必要なプロパティをプロパティ・セットに追加(または新しいプロパティ・セットを作成)した後、第67.2.2.3項「シナリオ・エディタでの新しいシナリオの作成」の説明に従ってシナリオを作成します。
コンダクタのシナリオ・エディタでは、コンダクタによって管理されるシナリオ定義を表示および編集するための視覚的なツールが提供されます。シナリオ・エディタは、シナリオをファイル形式および視覚的な形式の両方で格納します。このエディタはJDeveloper内から使用できます。シナリオを作成する前に、ネームスペース、およびシナリオに必要な少なくとも一部のプロパティ・セットとプロパティを作成する必要があります。
JDeveloperのシナリオ・エディタを使用して新しいシナリオを作成する手順は次のとおりです。
JDeveloper内のアプリケーションで、ナビゲーション・バーにあるそのアプリケーションを右クリックします。
「新規ギャラリ」ダイアログが表示されます(図67-10を参照)。
注意: 「パーソナライズ」カテゴリが表示されない場合は、「すべてのテクノロジ」タブを開いてそれを選択するか、「選択済のテクノロジ」をクリックしてプロジェクトにパーソナライズ・テクノロジを追加します。 |
「コンダクタ・シナリオ」を選択し、「OK」をクリックします。
「シナリオ定義」ダイアログが表示されます(図67-11を参照)。
「新規コンダクタ・シナリオ・ファイルの作成」を選択し、必要に応じて、ファイル名とファイルの格納場所を変更します。シナリオ名の拡張子(.scenarios_diagram
)は変更できないことに注意してください。
シナリオ・エディタに新しい「開始」ノードが表示されます(図67-12を参照)。
シナリオにノードを追加するには、新しいノードの追加先となるノードを右クリックし、「次の文を追加」を選択した後、図67-13のようにリストからノード・タイプを選択します。
新しいノードを右クリックして、ノード・プロパティの設定とフローの拡張に関するオプションを表示します。使用可能なノード・タイプについては、第67.2.2.4項「ノード・タイプを使用したシナリオ・フローの指定」を参照してください。
シナリオ・エディタでは、(判断に使用される)サブツリーの組合せによってフローが表されるツリー構造の固定レイアウト、およびループや複雑なネストされたif/else判断のフローを表す内部ラベル参照が使用されます。
ノード・タイプ
開始: 「開始」ノードは、シナリオの開始地点を定義するルート・レベルのノードです。
戻る: 「戻る」ノードは、シナリオの実行を停止し、指定されたEL式の評価結果をコール元に戻します。
変数の割当て: 「変数の割当て」ノードでは、現在実行中のシナリオのコンテキスト内にスコープ指定される変数を定義し、それを式によって初期化できます。
実行: 「実行」ノードは、戻り値を期待せずに、指定されたEL式を起動します。「変数の割当て」と同様、式の結果のみがシナリオのコンテキスト内に格納されません。
条件/Otherwise: 「条件」ノードは、EL式を評価し、EL式がtrueと評価された場合、そこに含まれる文を実行します。「Otherwise」ブロック内の文は、すべての条件文がfalseと評価された場合のみ実行されます。
ForEach: 「ForEach」ノードは、要素のコレクションに対してループおよび反復機能を提供するノードの一致ペアです。
while: 指定されたEL式がtrueと評価されるかぎり、ループおよび反復機能を提供します。
エラー発生: エラーが発生し、指定されたエラー・メッセージとともに、そのエラーがスローされます。
プロバイダの起動: IDataProviderの名前の実装を起動します。結果は、現在実行されているシナリオのコンテキスト内に格納されます。
シナリオの起動: 同じネームスペース内の別の名前付きシナリオを起動します。結果は、現在実行されているシナリオのコンテキスト内に格納されます。
プロパティ・エディタでは、プロパティ・サービスによって管理される、プロパティ・セット定義とそれに関連付けられたプロパティ定義を表示および編集できます。プロパティ・エディタは、プロパティ・サービスを通じてデータと通信し、それらを保持します。
プロパティ・セットとそれに含まれるプロパティは、様々な場所に様々な形式で格納できるため、それらの取得にはロケータ機能が必要です。プロパティ・セットのデータを取得し、事前構成済データベースに格納する、デフォルトのプロパティ・セット・ロケータが提供されています。このデフォルト・ロケータは、プロパティ・セット用に他のロケータが指定されなかった場合のみ使用されます。
ピープル・コネクション・サービス用のカスタム・ロケータもデフォルトで提供されます(詳細は第67.1.4.1.4項「ピープル・コネクション・ロケータ」を参照)が、他のデータソース用に追加のロケータを定義することもできます。プロパティとプロパティ・セット用に複数のロケータを定義でき、それらは優先順位に従って定義することもできます。ロケータの実装手順については、第67.4.2項「カスタム・ロケータの追加」を参照してください。
マーカー・インタフェースであるIFunctionProvider
を使用すると、ユーティリティ・コードにコンダクタ内の式言語サービスからアクセスできるようになります。IFunctionProvider
の実装には、注釈付きのpublicメソッドおよびstaticメソッドが含まれます。例67-1は、ファンクション・プロバイダの例を示しています。
例67-1 ファンクション・プロバイダの例
@FunctionProvider ( prefix="interpreter", resourceBundle="sample.InterpreterResources", nameBundleKey="provider.name", descriptionBundleKey="provider.description" ) public class InterpreterProvider implements IFunctionProvider { @PublicFunction ( functionName="english", descriptionBundleKey="english.description" ) public static String interpretEnglish(@PublicParameter(parameterName="phrase", descriptionBundleKey="phrase.description")String phrase) { String result = "Not Understood"; if ("Bonjour".equals(phrase)) { result = "Hello"; } return result; } @PublicFunction ( functionName="french", descriptionBundleKey="french.description" ) public static String interpretFrench(@PublicParameter(parameterName="phrase", descriptionBundleKey="phrase.description")String phrase) { String result = "Non compris"; if ("Hello".equals(phrase)) { result = "Bonjour"; } return result; } }
例67-1のファンクション・プロバイダは、次の式構文を使用してコールします。
${interpreter:english("Bonjour")} ${interpreter:french("Hello")}
例67-1に基づいて、ファンクション・プロバイダの結果に変数を割り当てる方法の例を、次に示します。
<assign-variable> <variable>greetings</variable> <expression>${interpreter:english("Bonjour")}</expression> </assign-variable>
データ・プロバイダの実装は、カスタム機能をシナリオの実行に統合するための、より構造化された方法です。ファンクション・プロバイダとは異なり、データ・プロバイダは、コンダクタに組み込まれた接続構成フレームワークにアクセスできるため、環境に固有の構成データを使用できます。次の図は、データ・プロバイダに対するクラスの相互作用を示しています。
IDataProvider
データ・プロバイダは、IConnection
という抽象的な名前の接続の実装を戻します。通常、このような名前付き接続は、コンダクタの接続構成サービスによって提供される環境の構成に基づいていますが、そうである必要はありません。データ・プロバイダによって構成サービスが使用される場合、その実装では、getConnectionConfigClass()
メソッドからoracle.wcps.connection.configuration.AnnotatedConfiguration
を拡張するクラスを戻す必要があります。このクラスには、データ・プロバイダに固有の構成データを表す、注釈付きのパブリック・フィールドが含まれている必要があります。
IConnection
oracle.wcps.conductor.provider.IConnection
の実装は、(指定およびデフォルトの)実行可能リソースを戻します。IConnection
の各インスタンスは1つの接続構成を表し、(静的ではない)IDataProvider
のインスタンス内で構成する必要があります。
IExecutableResource
oracle.wcps.conductor.provider.IExecutableResource
の実装には、外部システムとの統合コードの大部分が含まれ、そのインスタンスは(静的ではない)IConnection
のインスタンス内で構成する必要があります。IExecutableResource
では、引数を使用しないexecute
メソッドがデフォルト・メソッドとして提供されますが、IExecutableResource
がシナリオの実行に対して公開されている場合、実装内に注釈付きのカスタム・メソッドを記述できます。たとえば、シナリオから次のカスタム・メソッドを呼び出すことができます。
@PublicFunction ( functionName="custom", descriptionBundleKey="customFunction.description" ) public String callCustomMethod(@PublicParameter(parameterName="customParam", descriptionBundleKey="customParam.description") String param) { return param + " Results"; }
次の例は、カスタム・メソッドを含むプロバイダがどのようにシナリオ内から呼び出されるかを示しています。
<call-provider> <provider-name>myCustomProvider</provider-name> <connection-name>${connectionName}</connection-name> <method-name>custom</method-name> <variable>searchResults</variable> <input> <parameter> <common:name>customParam</common:name> <common:value>${someScenarioVariable}</common:value> </parameter> </input> </call-provider>
パーソナライズでは、シナリオ内で使用できる、プロパティ・サービス・プロバイダ、Content Serverプロバイダ(CMIS)およびアクティビティ・グラフ・プロバイダという3つのデフォルト・プロバイダが提供されます。この項では、これらのプロバイダをアプリケーションに統合する方法について説明します。内容は次のとおりです。
プロパティ・サービス・プロバイダ(oracle.PropertiesServiceProvider
)を使用すると、パーソナライズ・サーバーのプロパティ・サービスとの統合を実現できます。また、このプロバイダを使用すると、特定のプロパティ・セット定義に対応したプロパティ・セットを取得したり、名前でプロパティ・セットを取得したり、プロパティ・セットから特定のプロパティを戻したりできます。ピープル・コネクション・ロケータを使用してプロファイル・データをシナリオ内に統合する場合、そのロケータを使用する前にプロパティ・サービスを構成する必要があります。ピープル・コネクション・ロケータの詳細は、第67.1.4.1.4項「ピープル・コネクション・ロケータ」を参照してください。プロパティ・サービス・プロバイダの構成の詳細は、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のOracle People Connectionsロケータの構成に関する項を参照してください。
CMISプロバイダ(CMISProvider
)では、コンテンツを標準ベースのCMIS (Content Management Interoperability Services)コンテンツ・サーバーから検索して取得するためのサービスが提供されます。WebCenterの場合、これはOracle WebCenter Content: Content Serverによって提供されます。また、CMISプロバイダでは、結果を単純な形式に変換するためのユーティリティ・ファンクション・プロバイダ(CMISFunctionProvider
)も提供されます。次の例を試す前に、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のCMISプロバイダの構成に関する項の説明に従って、CMISプロバイダの接続を構成してください。
CMISプロバイダのシナリオの例
次を使用してシナリオを作成します(application/xml
のcontent-type
を必ず設定してください)。
リクエストURI:
POST http://localhost:8891/wcps/api/conductor/namespaces/myNameSpace/scenarios
リクエスト本文:
<scenarioMetadata> <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>CMISProvider</provider-name> <connection-name>CmisConfigConnection</connection-name> <variable>exprString</variable> <input> <parameter> <common:name>search</common:name> <common:value>SELECT * FROM cmis:document WHERE cmis:name LIKE 'flowers'</common:value> </parameter> </input> </call-provider> <return> <expression>${exprString}</expression> </return> </body> <name>CMIS Scenario</name> <comments>CMIS Scenario comments</comments> <tags> <tag>CMIS Scenario tag</tag> </tags> </scenario> </scenarioMetadata>
シナリオの実行
リクエストURI:
POST http://localhost:8891/wcps/api/conductor/namespaces/myNameSpace/scenarios/CMIS%20Scenario
リクエスト本文:
<parameters/>
CMISFunctionProviderの使用
ファンクション・プロバイダは、シナリオから起動できるユーティリティ・クラスです。CMISFunctionProvider
では、いくつかのメソッドがサポートされます(詳細はクラスのJavaDocを参照)。2つのメソッドの例を次に示します。
/** * Convert the array of input IDs to a CMIS query in the form of 'IN' * @param ids Array of document IDs, in the form of dDocName only * @return CMIS query String */ public static String getCMISQueryForDocIDs( @PublicParameter(parameterName="repository",descriptionBundleKey="getCMISQueryForDocIDs.parameter.description.inputList") String repository, @PublicParameter(parameterName="ids",descriptionBundleKey="getCMISQueryForDocIDs.parameter.description.inputList") List<String> ids)) ... /** * Convert the array of input IDs to a CMIS query in the form of 'IN' * @param ids, in the form of a WebCenter document ObjectURN. For example: stanl18-ucm11g#dDocName:MOUNTAINS * @return CMIS query String */ public static String getCMISQueryForDocIDsFromFullID(@PublicParameter(parameterName="ids", descriptionBundleKey="getCMISQueryForDocIDs.parameter.description.inputList") List<String> ids)
シナリオでのCMISFunctionProviderの使用
次のシナリオ・スニペットは、CMISFunctionProvider
にデータを渡して複数のノードに対するCMIS問合せを作成する方法の例を示しています。この問合せは、後からCMISプロバイダに送信されます。(より現実的な例としては、データを生成するかわりに、アクティビティ・グラフ・プロバイダのコールから得た結果を渡している場合などがあります。)
<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"> <comments>testFunctionProviderScenario4 comments</comments> <body> <assign-variable> <variable>ids</variable> <expression>${collections:new()}</expression> </assign-variable> <execute> <expression>${collections:append(ids,'StellentRepository#dDocName:MOUNTAINS')}</expression> </execute> <execute> <expression>${collections:append(ids,'StellentRepository#dDocName:PARKS')}</expression> </execute> <execute> <expression>${collections:append(ids,'StellentRepository#dDocName:PATAGONIAPARKS')}</expression> </execute> <!-- Assign those as IDs to send to CMIS --> <assign-variable> <variable>cmisQuery</variable> <expression>${cmisfunction:getCMISQueryForDocIDsFromFullID(ids)}</expression> </assign-variable> <!-- Make the call to CMIS --> <call-provider> <provider-name>CMISProvider</provider-name> <connection-name>NonProxyConnection</connection-name> <variable>cmisResults</variable> <input> <parameter> <common:name>search</common:name> <common:value>${cmisQuery}</common:value> </parameter> </input> </call-provider> <return> <expression>${cmisResults}</expression> </return> </body> <name>testFunctionProviderScenario4</name> </scenario:scenario>
アクティビティ・グラフ・プロバイダ(ActivityGraphProvider
)によって、WebCenter内での分析に基づいて推奨事項を提供するアクティビティ・グラフ・サービスとの統合が実現されます。次の例を試す前に、『Oracle Fusion Middleware Oracle WebCenter Portal管理者ガイド』のアクティビティ・グラフ・プロバイダの構成に関する項の説明に従って、アクティビティ・グラフ・サービスの接続を構成してください。
アクティビティ・グラフ・プロバイダのシナリオの例
次を使用してシナリオを作成します(application/xml
のcontent-type
を必ず設定してください)。
リクエストURI:
POST http://localhost:8891/wcps/api/conductor/namespaces/default/scenarios
リクエスト本文:
<scenarioMetadata> <scenario xmlns:common="http://xmlns.oracle.com/wcps/conductor/common/1.0.0"> <body> <call-provider> <provider-name>ActivityGraphProvider</provider-name> <connection-name>ActivityGraphConfigConnection</connection-name> <resource-name>QueryCommonItems</resource-name> <method-name>queryCommonItems</method-name> <variable>providerResults</variable> <input> <parameter> <common:name>sourceClassURN</common:name> <common:value>WC.user</common:value> </parameter> <parameter> <common:name>sourceObjectURN</common:name> <common:value>carl</common:value> </parameter> <parameter> <common:name>targetClassURN</common:name> <common:value>WC.user</common:value> </parameter> <parameter> <common:name>targetObjectURN</common:name> <common:value>monty</common:value> </parameter> <parameter> <common:name>similarityURN</common:name> <common:value>user-edit</common:value> </parameter> </input> </call-provider> <return> <expression>${providerResults}</expression> </return> </body> <name>QueryCommonItemsScenario</name> <comments>QueryCommonItemsScenario comments</comments> <tags> <tag>invoke</tag> <tag>sample</tag> <tag>provider</tag> <tag>resource</tag> <tag>input</tag> <tag>parameters</tag> <tag>overloaded</tag> </tags> </scenario> </scenarioMetadata>
シナリオの実行
次に進む前に、ヘッダー値Accept=application/xml
とcontent-type=application/xml
を設定する必要があります。
リクエストURI:
POST http://localhost:8891/wcps/api/conductor/namespaces/default/scenarios/QueryCommonItemsScenario
リクエスト本文:
<parameters/>
AGFunctionProviderの使用
ファンクション・プロバイダは、シナリオから起動できるユーティリティ・クラスです。AGFunctionProvider
では、次のメソッドがサポートされます。
/** * Return the value of 'ObjectURN', only for WC.document, from the input Object. * @param agResults From call to 'QueryRecommendations' or QueryItems. Can be one of the following Classes: * * From AG REST 'recommendations' * <ul> * <li> Recommendations * <li> RecommendedItems * <li> List<Recommendation> * </ul> * * From AG REST 'items' (common items) * <ul> * <li> Results * <li> Items * <li> List<Item> * </ul> * * @param dDocNameOnly If true, just the last part of the ObjectURN for * document will be returned; otherwise, the entire ObjectURN will be. * For example, if ObjectURN is example-ucm11g#dDocName:EXAMPLEACL000116, * if this value is 'true', then only EXAMPLEACL000116 will be returned. * Otherwise, all of stanl18-ucm11g#dDocName:EXAMPLEACL000116 is returned. * * @return a List of ObjectURN representing the document ID */ @PublicFunction public static List<String> getDocumentIDs( @PublicParameter(parameterName="agResults",descriptionBundleKey="getContentIDs.parameter.description.inputList")Object agResults, @PublicParameter(parameterName="dDocNameOnly", descriptionBundleKey="getContentIDs.parameter.description.inputList")boolean dDocNameOnly) { ... /** * Return the value of 'ObjectURN' for the 'ClassURN' from the input Object. * @param agResults From call to 'QueryRecommendations' or QueryItems. Can be one of the following Classes: * * From AG REST 'recommendations' * <ul> * <li> Recommendations * <li> RecommendedItems * <li> List<Recommendation> * </ul> * * From AG REST 'items' (common items) * <ul> * <li> Results * <li> Items * <li> List<Item> * </ul> * * param filterClassURN return content only of this type. Examples are: WC.wiki-page, WC.group-space, WC.user, WC.blog, * WC.topic, WC.document. If this is null, return all types. * * @return a List of ObjectURN representing the item identifier. */ @PublicFunction ( functionName="getContentIDs", descriptionBundleKey="getContentIDs.method.description" ) public static List<String> getContentIDs(@PublicParameter(parameterName="agResults", descriptionBundleKey="getContentIDs.parameter.description.inputList")Object agResults, @PublicParameter(parameterName="filterClassURN", descriptionBundleKey="getContentIDs.parameter.description.filterClassURN") String filterClassURN) ... /** * Filter recommendations by score. Only those recommendations with a score >= the cutoff will be preserved. */ @PublicFunction ( functionName="filterRecsByScore", descriptionBundleKey="filterRecsByScore.method.description" ) public static Recommendations filterRecsByScore( @PublicParameter(parameterName="recommendations", descriptionBundleKey="filterRecsByScore.parameter.description.agRecs") Recommendations recs, @PublicParameter(parameterName="cutoffScore", descriptionBundleKey="filterRecsByScore.parameter.description.cutoffScore") float cutoffScore ) {
シナリオでのAGFunctionProviderの使用
次のシナリオでは、まずアクティビティ・グラフRESTサービスがコールされます。そのコールの結果はagRecommendations
変数に格納されます。このシナリオでは、次にAGFunctionProvider.getContentIDs()
メソッドをコールしてagRecommendations
の結果(アクティビティ・グラフ・オブジェクト)を渡し、expressions
コールの評価内で保持されるドキュメントIDのList<String>
を戻します。
<expression>${agfunction:getContentIDs(agRecommendations,'WC.user')}</expression> <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"> <comments>CallProviderScenario comments</comments> <body> <call-provider> <provider-name>ActivityGraphProvider</provider-name> <connection-name>AgTestServerConnection</connection-name> <resource-name>QueryRecommendations</resource-name> <method-name>getRecommendationsUsingDefaultRecipe</method-name> <variable>agRecommendations</variable> <input> <parameter> <common:name>classURN</common:name> <common:value>WC.user</common:value> </parameter> <parameter> <common:name>objectURN</common:name> <common:value>carl</common:value> </parameter> </input> </call-provider> <!-- Now call function provider to translate into user IDs. A more specific call is available for WC.document; this just tests the ability of the function provider to handle different types of content --> <return> <expression>${agfunction:getContentIDs(agRecommendations,'WC.user')}</expression> </return> </body> <name>CallProviderScenario</name> </scenario:scenario>
シナリオ・エディタを使用するだけでなく、XML形式のファイル・ベースのシナリオを作成することもできます。ファイル・ベースのシナリオは、コンダクタのインポート・ファンクションとエクスポート・ファンクション、およびJDeveloper MDSの統合を通じてのみサポートされます。ファイル・ベースのシナリオをシナリオ・エディタにインポートするには、シナリオの作成時に「ファイルから作成」オプションを選択します。
表67-1は、シナリオ・ファイルのコンテンツを構成する文を示しています。文の詳細は、第67.2.2.4項「ノード・タイプを使用したシナリオ・フローの指定」のノードに関する説明を参照してください。
表67-1 シナリオの文
文 | 説明 | 例 |
---|---|---|
変数の割当て |
現在実行中のシナリオのコンテキスト内にスコープ指定された変数を作成します。 |
<assign-variable> <variable>index</variable> <expression>3</expression> </assign-variable> |
実行 |
戻り値を期待せずに、指定されたEL式を起動します。「変数の割当て」と同様、式の結果のみがシナリオのコンテキスト内に格納されません。 |
<execute> <comments>Adds to an existing collection.</comments> <expression>${collections:append(responses,'The outlook is not so good.')}</expression> </execute> |
条件/Otherwise |
EL式を評価し、EL式がtrueと評価された場合、そこに含まれる文を実行します。「Otherwise」ブロック内の文は、すべての条件文がfalseと評価された場合のみ実行されます。 |
<conditions> <body> <condition> <body> <assign-variable> <variable>customerType</variable> <expression>Great Customer</expression> </assign-variable> </body> <expression>${customer.totalMoneySpent >= 100000}</expression> </condition> <otherwise> <body> <assign-variable> <variable>customerType</variable> <expression>Good Customer</expression> </assign-variable> </body> </otherwise> </body> </conditions> |
ForEach |
要素のコレクションに対してループおよび反復機能を提供します。 |
<for-each> <body> <execute> <comments> Let's send each great customer an email, thanking them for their loyalty. </comments> <expression> ${emailService:sendMail(customer,'Subject:Thanks for being a great customer')} </expression> </execute> </body> <variable>customer</variable> <max-iterations>10</max-iterations> <items>${greatCustomers}</items> </for-each> |
while |
指定されたEL式がtrueと評価されるかぎり、ループおよび反復機能を提供します。 |
<while> <body> <assign-variable> <comments>Sum up customer invoices to arrive at customer total expenditure.</comments> <variable>customerTotalSpent</variable> <expression>${customerTotalSpent+order.invoiceTotal}</expression> </assign-variable> </body> <expression>${customer.id = currentCustomerId }</expression> <max-iterations>-1</max-iterations> </while> |
シナリオの起動 |
同じネームスペース内の別の名前付きシナリオを起動します。結果は、現在実行されているシナリオのコンテキスト内に格納されます。 |
<call-scenario > <variable>greeting</variable> <scenario>randomGreetingGenerator</scenario> <input> <parameter> <ns2:name>greetingsList</ns2:name> <ns2:value>hello, Bonjour, Buenos días</ns2:value> </parameter> </input> </call-scenario> |
プロバイダの起動 |
IDataProviderの名前の実装を起動します。結果は、現在実行されているシナリオのコンテキスト内に格納されます。 |
<call-provider> <provider-name>CRM_Provider</provider-name> <connection-name>crm_db</connection-name> <resource-name>getGreatCustomers</resource-name> <variable>greatCustomers</variable> <input> <parameter> <ns2:name>minMoneySpent</ns2:name> <ns2:value>100000</ns2:value> </parameter> </input> </call-provider> |
戻る |
指定されたEL式の評価結果を戻します。 |
<return> <comments>Return the sales rep who sold the most widgets this month.</comments> <expression>${bestSalesRep.id}</expression> </return> |
エラー発生 |
エラーが発生し、指定されたエラー・メッセージとともに、そのエラーがスローされます。 |
<raise-error> <comments>User is unathorized, so let's return a 401.</comments> <statusCode>401</statusCode> <message>User ${ScenarioContext.scenarioRequest.userPrincipal.name} is unauthorized to execute this scenario.</message> </raise-error> |
例67-2 ファイル・ベースのシナリオの例
<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"> <comments>sampleScenarioWithIf comments</comments> <body> <assign-variable> <variable>index</variable> <expression>3</expression> </assign-variable> <conditions> <body> <condition> <body> <assign-variable> <variable>ResultVar</variable> <expression>conditionSatisfied</expression> </assign-variable> </body> <expression>${index == 3}</expression> </condition> <otherwise> <body> <assign-variable> <variable>ResultVar</variable> <expression>otherwiseInvoked</expression> </assign-variable> </body> </otherwise> </body> </conditions> <return> <expression>${ResultVar}</expression> </return> </body> <name>sampleScenarioWithIf</name> <tags> <tag>if</tag> <tag>condition</tag> <tag>otherwise</tag> </tags> </scenario:scenario>
この項では、WebCenter Portal: SpacesおよびWebCenter Portal: Frameworkアプリケーションの実行時に、コンテンツ・プレゼンタを使用してターゲット・コンテンツをユーザーに表示する方法について説明します。また、REST APIを使用して、コンテンツを提供するための独自のユーザー・インタフェースを作成する方法についても説明します。
この項の内容は、次のとおりです。
コンテンツ・プレゼンタは、コンダクタの動的コンテンツ問合せ生成機能と密接に統合されており、動的コンテンツの単純な表示を可能にします。アプリケーション内でのコンテンツ・プレゼンタの使用の詳細は、第29章「コンテンツ・プレゼンタ表示テンプレートの作成」を参照してください。
WebCenter Portal: Spacesで式言語式を使用してパーソナライズ・サーバーのシナリオにアクセスする方法については、Oracle Fusion Middleware Oracle WebCenter Portal: Spacesユーザーズ・ガイドのページのパーソナライズに関する項を参照してください。
REST APIを使用すると、コンテンツ・プレゼンタを使用せずに、コンテンツを提供するための独自のユーザー・インタフェースを作成できます。REST APIの詳細は、第54章「Oracle WebCenter Portal REST APIの使用」を参照してください。
この項では、JDeveloperで、単純な文字列(Hello World
)を戻すシナリオを含む単純なアプリケーションを作成する方法について説明します。その後、シナリオの結果をJSPページに追加してテストし、統合WebLogic Server内でアプリケーションを実行して、結果をブラウザに表示します。
この項では、統合WebLogic Serverを構成して起動する手順、パーソナライズ・サーバーのコンダクタへの接続を定義する手順、およびシナリオとJSPアーティファクトをテスト用にサーバー・ドメインにデプロイする方法についても説明します。
注意: このチュートリアルの前提条件として、Oracle JDeveloperに対するWebCenter Portalの拡張機能( |
デフォルトのオプションとテクノロジを使用して、単純なWebCenter Portalアプリケーション(Hello_Applicaton
)を作成します。
「ファイル」メニューから「新規」を選択します。
「新規ギャラリ」が表示されます。
「すべてのテクノロジ」タブから「アプリケーション」を選択します。
リストから「Fusion Webアプリケーション(ADF)」
を選択し、「OK」をクリックします。
Fusion Webアプリケーション(ADF)の作成ウィザードが表示されます(図67-15を参照)。
「アプリケーション名」にHello_Application
と入力します。
Portal
プロジェクトのウィザード・ページの「ステップ4/5」
まで、「次へ」をクリックします。
「プロジェクト・テクノロジ」タブに、アプリケーション用にインストールできるテクノロジのリストが表示されます。
Portal
プロジェクト用に選択されたテクノロジのリストにWebcenter Personalization
を追加し、「終了」をクリックして、構成済のHello_Application
アプリケーションを作成します。
JDeveloperの統合サーバー(統合WLS)のデフォルト・ドメインを構成します。
ドメインは自動的に拡張され、パーソナライズ・コンポーネントの実行に必要なサーバー・アーティファクト(つまり、パーソナライズ・コンダクタとプロパティ・サービス)が含まれます。
「表示」メニューから「アプリケーション・サーバー・ナビゲータ」
を選択し、「アプリケーション・サーバー」
ツリー・ノードを開いてIntegratedWeblogicServer
を表示します。
現在のステータスは(ドメイン未構成)
になっています。
IntegratedWeblogicServer
を右クリックしてコンテキスト・メニューを表示し、「デフォルト・ドメインの作成」
を選択します。
ステータスは(ドメインの作成中)
と表示され、「メッセージ・ログ」ウィンドウに、ドメインの作成中であることを示す出力が表示されます。ドメインの作成が完了するまで待機します。この操作の完了には時間がかかる場合があります。完了すると、メッセージ・ログに「統合Weblogicドメインの処理が正常に完了しました。」
と表示されます。
IntegratedWeblogicServer
を右クリックしてコンテキスト・メニューを表示し、「サーバー・インスタンスの起動」を選択してサーバーを起動します。
「実行中: IntegratedWeblogicServer - ログ」
ビューに、サーバーの起動中であることを示す出力が表示されます。サーバーの起動が完了するまで待機します。この操作の完了には時間がかかる場合があります。完了すると、IntegratedWeblogicServerのメッセージ・ログに「IntegratedWebLogicServerが起動しました。」
と表示されます。
実行中のサーバー上でパーソナライズ(WCPS)トラスト・サービスを構成して、JDeveloperのIntegratedWebLogicServerドメインに対してシングル・サインオン(SSO)を有効にします。
「ツール」メニューから「WCPSトラスト・サービスの構成」を選択します。
このタスクを実行するための外部ツールの実行が開始され、その出力が「WCPSトラスト・サービスの構成 - ログ」
ビューにダイレクトされます。構成が完了するまで待機します。これには時間がかかる場合があります。完了すると、ログに「ドメインを再起動する必要のある変更が行われました。すべてのドメイン・サーバーを再起動してください。」
というメッセージが表示されます。
「実行中: IntegratedWeblogicServer - ログ」
ビューの「終了」をクリックして、アプリケーション・サーバーを停止します。
シャットダウンが完了すると、「プロセスが終了しました。」
というメッセージが表示されます。その後、手順2cの操作を行ってサーバーを再起動できます。
アプリケーション・サーバーのパーソナライズ・コンダクタ・コンポーネントへのアプリケーションURL接続を構成します。
「アプリケーション」メニューから「アプリケーション・プロパティ」
を選択します。
「アプリケーション・プロパティ」ダイアログが表示されます。
図67-20 「アプリケーション・プロパティ」ダイアログ - パーソナライズ・サーバー接続の構成
「パーソナライズ・サーバー」
カテゴリを選択し、「URL接続」ドロップダウン・リストから<新しいURL接続...>
を選択します。
「URL接続の作成」ダイアログが表示されます(図67-21を参照)。
(デフォルトの)データ・エントリ・フィールドに、次のように値を入力して、接続を作成します。
フィールド名 | 値 |
---|---|
名前 |
Conductor |
URLエンドポイント |
http://localhost:7101/wcps/api/conductor/resourceIndex |
認証タイプ |
基本 |
ユーザー名 |
weblogic |
パスワード |
weblogic1 |
レルム |
WCPS |
「接続のテスト」をクリックします。
「ステータス」に「接続が正常に確立されました。」
と表示されます。
「OK」をクリックしてコンダクタのURL接続を作成します。
「パーソナライズ・サーバー」ページで、デフォルトのシナリオ・ネームスペースをアプリケーション名(Hello_Application
)に設定したままにし、「アプリケーション・プロパティ」ダイアログで「OK」をクリックして設定を受け入れます。
アプリケーションでパーソナライズ・サービス(WCPS)ライブラリを使用できるように、Hello_Application
のサーバー・デプロイメント・ディスクリプタを構成します。
アプリケーション・ナビゲータで、Portal/Web Content/WEB-INF
フォルダを開きます。
weblogic.xml
デプロイメント・ディスクリプタをダブルクリックして開きます。
WebLogicディスクリプタ・エディタが表示されます。
「ライブラリ」
カテゴリを選択します。
プラス(+)アイコンをクリックして、新しいライブラリ・エントリを作成します。
表の「ライブラリ名」列に、次のライブラリ名を入力します。
wcps-services-client-web-lib
完了したら、「ファイル」メニューから「保存」
を選択して、weblogic.xml
ディスクリプタを保存します。
パーソナライズ・コンダクタによって呼び出されたときに文字列Hello World
を戻す、単純なhello_world
シナリオを作成します。
アプリケーション・ナビゲータでPortal
プロジェクトを右クリックし、「新規」を選択します。
「新規ギャラリ」が表示されます。
「現在のプロジェクト・テクノロジ」タブから、「パーソナライズ」
カテゴリを選択します。
「コンダクタ・シナリオ」
を選択し、「OK」をクリックします。
「新規コンダクタ・シナリオ」ダイアログが表示されます。
「新規コンダクタ・シナリオ・ファイルを作成する」
オプションを選択し、新しいシナリオ・ファイル名をhello_world.scenarios_diagram
と入力し、「OK」をクリックしてシナリオを作成します。
シナリオ・エディタの「ダイアグラム」ビューで「開始」ノードを右クリックし、「次の文を追加」→「戻る」
を選択します。
「戻る」ノードが追加および接続されます。
「戻る」ノードを右クリックし、「式の設定」
を選択します。
シナリオ式ビルダーが表示されます(図67-24を参照)。
「式」のテキスト領域に次のEL式を入力し、「OK」をクリックします。
${'Hello World'}
シナリオの図は、図67-25のようになります。
「ファイル」メニューから「保存」
を選択して、hello_world.scenarios_diagram
を保存します。
hello_world
シナリオを呼び出して結果を表示するJSPページを作成します。
JSPページを作成する前に、JSPページに必要なリソースを含むいくつかのライブラリをPortal
プロジェクトに追加する必要があります。
アプリケーション・ナビゲータでPortal
プロジェクトを右クリックし、「プロジェクト・プロパティ」を選択します。
「プロジェクト・プロパティ」ダイアログが表示されます。
「ライブラリとクラスパス」
カテゴリを選択し、「ライブラリの追加」をクリックします。
「ライブラリの追加」ダイアログが表示されます(図67-26を参照)。
リストから次の拡張ライブラリを選択し、「OK」をクリックして追加します。
Webcenter Personalization Client
完了したら、「プロジェクト・プロパティ」ダイアログで「OK」をクリックします。
これで、パーソナライズ・コンダクタ上でhello_world
シナリオを実行して結果を表示するJSPページを作成できるようになります。
アプリケーション・ナビゲータでPortal
プロジェクトを右クリックし、「新規」を選択します。
「新規ギャラリ」が表示されます。
「現在のプロジェクト・テクノロジ」タブから、「JSP」カテゴリを選択します。
アイテム・リストから「JSP」を選択し、「OK」をクリックします。
「JSPの作成」ダイアログが表示されます(図67-27を参照)。
「ファイル名」にhello_world.jsp
と入力し、「OK」をクリックしてJSPページを作成します。
JSPエディタが起動したら、「ソース」ビューを選択し、テンプレート・テキストを次のJSPコードで置換します。
c:out
コマンド内で、パーソナライズ・コンテキストBeanp13nContext
がどのように使用されているかに注目してください。ここでは、「アプリケーション・プロパティ」ダイアログで指定したシナリオ・ネームスペースHello_Application
を使用して作成したコンダクタ接続(Conductor
)を呼び出し、hello_world
というシナリオを呼び出した後、結果を表示しています。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@ page contentType="text/html;charset=UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>hello_world</title> </head> <body> <jsp:useBean id="p13nContext" class="oracle.wcps.client.PersonalizationContext" scope="session"/> <%((oracle.wcps.client.PersonalizationContext)session.getAttribute("p13nContext")).reset(); %> <c:out value="${p13nContext.conductor['Conductor'].namespaces['Hello_ application'].scenario['hello_world'].results}"/> </body> </html>
注意: 手順3の説明に従ってシングル・サインオンとトラスト・サービスを構成していない場合、ページの実行時に、ここで指定した
これを |
「ファイル」メニューから「保存」を選択して、hello_world.jsp
を保存します。
最後に、Hello_Application
を構築してデプロイするために、アプリケーション・ナビゲータでhello_world.jsp
ページの実行可能アーティファクトを右クリックし、「実行」を選択します。
JDeveloperによって、次のようないくつかのバックグラウンド・プロセスが順番に開始されます。
アプリケーションの構築
統合サーバーの起動(まだ起動していない場合)
デフォルト・ドメインへのアプリケーション・アーティファクト(パーソナライズ・アーティファクトを含む)のデプロイ
外部Webブラウザの起動によるアーティファクトhello_world.jsp
の表示
生成されたhello_world.jsp
JSPページがブラウザに表示されます。
図67-29 ブラウザに表示されたHello_Applicationのhello_world.jspページ
この項では、カスタム・プロバイダおよびロケータを追加することによって、どのようにアプリケーション・フローまたはコンテンツの新しいパーソナライズ方法を提供できるかについて説明します。
この項の内容は、次のとおりです。
プロバイダによって提供されるパーソナライズの拡張ポイントを使用すると、カスタム・ファンクション・プロバイダやカスタム・データ・プロバイダを追加できます。表67-2は、ファンクション・プロバイダとデータ・プロバイダに使用できる拡張ポイントを示しています。
表67-2 拡張ポイント
拡張 | 説明 |
---|---|
oracle.wcps.provider.IFunctionProvider |
データの操作と変換、ビジネス・ルールの計算などの用途に使用でき、EL式を使用して呼び出すことができるユーティリティ・メソッドの作成を目的とした、コンダクタ用のファンクション・プロバイダ拡張ポイントです。単純な例は、${strings:concat('string1','string2')}です。 |
oracle.wcps.provider.IDataProvider |
コンダクタ用のデータ・プロバイダ拡張ポイントです。カスタム・データ・プロバイダを記述して、従来のシステムや外部データ・ストアとの統合を実現できます。 |
AnnotatedConfiguration
クラスでは、データ・プロバイダに必要な接続パラメータが記述されます。このクラスは次の場所にあります。
場所: \Oracle\Middleware\jdeveloper\webcenter\modules\wcps-services_11.1.1.4.0\connections-service-1.0.jar
このクラスを拡張し、カスタム・プロバイダで必要になる可能性がある他のプロパティを追加する必要があります。まずこのクラスを作成し、それに基づいて他のコンポーネントを作成します(例67-3を参照)。
例67-3 HelloWorldConnectionConfig
import oracle.wcps.connection.annotation.ConnectionProperty; import oracle.wcps.connection.configuration.AnnotatedConfiguration; @ConnectionConfiguration (connectionType="hello.world.provider.connection") @L10n (bundle="demo.provider.resources.HelloWorldProviderResources") public class HelloWorldConnectionConfig extends AnnotatedConfiguration { @ConnectionProperty(propertyName="sampleProperty", required=true) String sampleProperty; }
IMetadata
場所: \Oracle\Middleware\jdeveloper\webcenter\modules\wcps-services_11.1.1.4.0\conductor-server-1.0.0.0.jar
public interface IMetadata { public String getName(); public Set<? extends IMetadata> getMetadata(); }
次に、IMetadataインタフェースを実装します。これにより、接続パラメータを表示するための情報がツールに提供されます。基本的には、HelloWorldConnectionConfig
クラス内の情報がメタデータとして表されます(例67-4を参照)。HelloWorldConnectionConfig
クラス内の各プロパティは、子メタデータ・オブジェクトになります。これは、構造が単純な場合はそれほど直感的ではありませんが、接続構成にモデル内の他のコンポーネントに関連するネストされたクラスが含まれる可能性がある場合は役立ちます。
例67-4 HelloWorldConfigMetadata
public class HelloWorldConfigMetadata implements IMetadata { private String name; private Object value ; private Map<String, IMetadata> childMDataMap = new HashMap<String, IMetadata>(); public HelloWorldConfigMetadata(HelloWorldConnectionConfig config) { name = config.name; } public HelloWorldConfigMetadata(String name, Object value) { this.name = name; this.value = value; } public void addMetadata(IMetadata childMetadata) { childMDataMap.put(childMetadata.getName(), childMetadata); } public String getName() { return name; } public Object getValue() { return value; } public Object getProperty(String propName) { IMetadata md = childMDataMap.get(propName); if (md != null) { return ((HelloWorldConfigMetadata)md).getValue(); } return null; } public Set<IMetadata> getMetadata() { Set<IMetadata> rv = new HashSet<IMetadata>(); Set<String> childKeySet = childMDataMap.keySet(); for (String key : childKeySet) { rv.add(childMDataMap.get(key)); } return rv; } public Properties getProperties() { Properties props = new Properties(); Set<String> childKeySet = childMDataMap.keySet(); for (String key : childKeySet) { HelloWorldConfigMetadata cmd = (HelloWorldConfigMetadata)childMDataMap.get(key); props.put(key, cmd.getValue()); } return props; } @Override public String toString() { return (name + ", properties: " + getProperties()); } }
IExecutableResource
実行可能リソースは、コンダクタによる実行が可能なメソッドとして指定するための注釈が付いたpublicメソッドを含むクラスです。これらのメソッドは、直接コードを実行する場合もあれば、コールを外部RESTサービスに委任する場合もあります。
場所:
\Oracle\Middleware\jdeveloper\webcenter\modules\wcps-services_11.1.1.4.0\conductor-server-1.0.0.0.jar
public interface IExecutableResource { public Object execute(); }
ExecutableResources
では、この注釈により、実行するその他のメソッドを指定できます。リソース・バンドルの使用方法に注意してください(詳細は、リソース・バンドルに関する項を参照)。任意の数のExecutableResources
を作成し、それらを接続に追加できます(例67-5を参照)。
例67-5 SayHelloExecutableResource
package demo.provider; import oracle.wcps.annotation.PublicFunction; import oracle.wcps.annotation.PublicParameter; import oracle.wcps.provider.IExecutableResource; public class SayHelloExecutableResource implements IExecutableResource { // This method will execute if no specific method is given public Object execute() { return "Hello from my custom provider"; } // This method can be named explicitly in a Scenario to be invoked @PublicFunction(functionName = "sayHello", descriptionBundleKey = "provider.method.sayHello.description") public String sayHello(@PublicParameter(parameterName = "user", descriptionBundleKey = "provider.parameter.sayHello.user.description") String user) { return "Hello, " + user + ". Enjoy using the new Personalization feature!"; } }
IConnection
IExecutableResources
とIMetadata
を実装したら、次は実際の接続オブジェクトを構成できます。接続ごとに特定の構成パラメータ・セットがあるため、プロバイダは複数の接続オブジェクトを保持する可能性があります(例67-6を参照)。
場所:
\Oracle\Middleware\jdeveloper\webcenter\modules\wcps-services_11.1.1.4.0\conductor-server-1.0.0.0.jar
public interface IConnection { public void setScenarioContext(IScenarioContext context); public Map<String, IExecutableResource> getNamedResources(); public IExecutableResource getDefaultResource(); public Map<String, IMetadata> getConnectionMetadata(); }
例67-6 HelloWorldConnection
package demo.provider; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import oracle.wcps.provider.IConnection; import oracle.wcps.provider.IExecutableResource; import oracle.wcps.provider.IMetadata; import oracle.wcps.scenario.IScenarioContext; public class HelloWorldConnection implements IConnection { private IScenarioContext scenarioContext; private Map<String, IExecutableResource> executableResources = new ConcurrentHashMap<String, IExecutableResource>(); private IExecutableResource defaultResource; private HelloWorldConfigMetadata configMetadata; private Map<String, IMetadata> metadataMap = new HashMap<String, IMetadata>(); /** * Create metadata about this connection from the incoming config * @param config */ public HelloWorldConnection(HelloWorldConnectionConfig config) { configMetadata = new HelloWorldConfigMetadata(config); // Loop over config properties and add as child metadata Iterator<Map.Entry<String, Object>> iter = config.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<String, Object> entry = iter.next(); String key = entry.getKey(); Object value = entry.getValue(); if (value != null) { configMetadata.addMetadata(new HelloWorldConfigMetadata(key, value)); } } metadataMap.put(config.name, configMetadata); // Now create the executable resources for this connection createExecutableResources(config); } public void setScenarioContext(IScenarioContext scenarioContext) { this.scenarioContext = scenarioContext; } public Map<String, IExecutableResource> getNamedResources() { return executableResources; } public IExecutableResource getDefaultResource() { return defaultResource; } public Map<String, IMetadata> getConnectionMetadata() { return metadataMap; } /** * Create the IExecutableResources for this connection. An executable resource * is a class having one or more public methods. * @param config */ private void createExecutableResources(HelloWorldConnectionConfig config) { // NOTE: you may or may not need to use the config information with your executable resources IExecutableResource helloResource = new SayHelloExecutableResource(); IExecutableResource addingResource = new AddingExecutableResource(); executableResources.put("HelloResource", helloResource); executableResources.put("AddingResource", addingResource); // Make one of them the default defaultResource = helloResource; } }
HelloWorldConnection
のインスタンスは、HelloWorldConnectionConfig
内で指定した接続タイプ(connectionType="hello.world.provider.connection"
)に対応する、provider-connections.xml
ファイル内のエントリごとにインスタンス化されます。
IDataProvider
これで、すべてをトップレベルのプロバイダ・クラスHelloWorldProvider
に入れる準備が整いました。これは、コンダクタが接続を構成し、IExecutableResource
を呼び出すためのアクセス・ポイントです。
場所:
\Oracle\Middleware\jdeveloper\webcenter\modules\wcps-services_11.1.1.4.0\conductor-server-1.0.0.0.jar
「プロジェクト・プロパティ」→「ライブラリとクラスパス」→「Jar/ディレクトリの追加」→(前述のconductor-server-1.0.0.0.jarを指定)
例67-7 IDataProvider
public interface IDataProvider { /** * Returns a map of connections keyed by connection name */ public Map<String, ? extends IConnection> getNamedConnections(); /** * Returns the "default" connection to use */ public IConnection getDefaultConnection(); /** * Called by the framework to set the current scenario context. */ public void setScenarioContext(IScenarioContext scenarioContext); /** * Return the annotated class used to house connection configuration. * * <p> * Returning null disables this feature. */ public Class<?> getConnectionConfigClass(); /** * If getConnectionConfigClass returns a valid configuration class, * configurations are provided through this method, if any exist. * @param configurations The collection of configurations. */ public void setConnectionConfigurations(List<?> configurations); }
必要な注釈:
@ContextualProvider ( contextName="HelloWorldProvider", resourceBundle="demo.provider.resources.HelloWorldProviderResources", nameBundleKey="provider.name", descriptionBundleKey="provider.description" )
詳細は、次のリソース・バンドルに関する例67-8を参照してください。
例67-8 リソース・バンドル
package demo.provider; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import oracle.wcps.annotation.ContextualProvider; import oracle.wcps.provider.IConnection; import oracle.wcps.provider.IDataProvider; import oracle.wcps.scenario.IScenarioContext; @ContextualProvider ( contextName="HelloWorldProvider", resourceBundle="demo.provider.resources.HelloWorldProviderResources", nameBundleKey="provider.name", descriptionBundleKey="provider.description" ) public class HelloWorldProvider implements IDataProvider { // Never used, but there is a required public method to set this. private IScenarioContext scenarioContext; // ConnectionConfigurations may come in via classes/META-INF/connection-providers.xml private List<HelloWorldConnectionConfig> connectionConfigurations; // Each IConnection is uniquely identified via the AGConnectionConfig private static Map<String, HelloWorldConnection> connections = new ConcurrentHashMap<String, HelloWorldConnection>(); // One of the connections will become the default private IConnection defaultConnection; public HelloWorldProvider() { super(); } /** * Return a map of all our Connections, keyed by config.name. * @return */ public Map<String, HelloWorldConnection> getNamedConnections() { return connections; } /** * One of the connections will be designated the default * @return */ public IConnection getDefaultConnection() { return defaultConnection; } /** * Used to hold parameters specific to a given scenario * @param scenarioContext */ public void setScenarioContext(IScenarioContext scenarioContext) { this.scenarioContext = scenarioContext; } /** * The config class is specific to each data provider * @return */ public Class<HelloWorldConnectionConfig> getConnectionConfigClass() { return HelloWorldConnectionConfig.class; } /** * Create a HelloWorldConnection instance from each of the incoming configs. * These configs are created when the provider-connections.xml file is loaded. * @param configs */ public void setConnectionConfigurations(List<?> configurations) { List<HelloWorldConnectionConfig> configs = (List<HelloWorldConnectionConfig>)configurations; for (HelloWorldConnectionConfig config : configs) { // Create a HelloWorldConnection from the config HelloWorldConnection connection = new HelloWorldConnection(config); if (config.isDefault) { defaultConnection = connection; } connections.put(config.name, connection); } } }
これらのファイルも、クラスと同じディレクトリに格納されるため、最終的なJARファイルに追加されます。ファイルの場所は、HelloWorldProvider:bundle="demo.provider.resources.HelloWorldProviderResources"
で指定したパッケージ名に対応している必要があります。
File name: HelloWorldProviderResources.properties File contents: provider.name=Hello World provider.description=Data provider for Hello World provider.parameter.sayHello.user.description=Method to say hello to a named user provider.parameter.addTwoIntegers.int1.description=First number to add provider.parameter.addTwoIntegers.int2.description=Second number to add
説明に従って接続を構成します。
META-INF/services
ディレクトリ内にファイルを作成する(最終的なjarファイルに追加されるように、クラスと同じディレクトリ構造にします)ことによって、コンダクタのプロバイダを指定します。
file name: oracle.wcps.provider.IDataProvider file contents: demo.provider.HelloWorldProvider (fully-qualified name of your provider)
リソース名がHelloWorldConnections
のソース・コード内と同じであることに注意してください。
例67-9 プロバイダをコールするシナリオ
<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>HelloWorldProvider</provider-name> <connection-name>HelloWorldConnection</connection-name> <resource-name>HelloResource</resource-name> <method-name>sayHello</method-name> <variable>providerResults</variable> <input> <parameter> <common:name>user</common:name> <common:value>cindymc</common:value> </parameter> </input> </call-provider> <return> <expression>${providerResults}</expression> </return> </body> <name>TestMyProviderScenario</name> </scenario:scenario>
この項では、カスタム・ロケータを追加することによって、パーソナライズされたWebCenter Portalアプリケーションを拡張する方法について説明します。
この項の内容は、次のとおりです。
プロパティ・ロケータは、プロパティ・サービスによって起動され、プロパティの外部ストアにアクセスします。たとえば、パーソナライズによって提供される、デフォルトのPeoplePropertyLocator
は、ピープル・コネクションRESTサービスを使用して、ユーザーのプロファイル情報にアクセスします。ロケータはコンダクタやシナリオによって直接起動されませんが、プロパティ・セット・サービスによってインスタンス化されます。その後、このサービスは、基礎となるロケータの実装に、プロパティとプロパティ・セットを取得するためのコールを委任します。
次の項の例では、独自のBookPropertyLocator
を作成して、図書館内の本をタイトルで検索し、その属性を、Bookオブジェクトを表すために作成したプロパティ・セット内にロードする方法について説明します。
この例の実装手順は、主に2つあります。
Bookのプロパティ・セットを定義し、その情報をプロパティ・セット・サービスに通知します。
IPropertyLocator
を実装して、Bookオブジェクトからプロパティをロードします。
場所:
\Oracle\Middleware\jdeveloper\webcenter\modules\wcps-services_11.1.1.4.0\properties-common-1.0.0.0.jar
public interface IPropertyLocator { public void loadProperties(IContext context, IPropertySet propertySet, IPropertySetDefinition propertySetDefinition, List<IPropertyName> propertyNames); public void storeProperties(IContext context, propertySet, IPropertySetDefinition propertySetDefinition, List<IPropertyName> propertyNames); public void removeProperties(IContext context, propertySet, List<IPropertyName> propertyNames); public void removeProperties(IContext context, nameSpaceName, IPropertySetDefinitionName name); public IPagedList<IPropertySet> filter(IContext context, nameSpaceName, IPropertySetDefinitionName setDefinitionName, PropertySetFilterContext filterContext); public int count(IContext context, nameSpaceName, PropertySetExpression expression); }
認証に使用されるIContext
オブジェクトは、プロパティ・サービスから渡されます。資格証明にアクセスする2つの方法を、次に示します。
リクエストの使用: HttpServletRequest request = context.getProperty(IContext.HTTP_REQUEST_KEY)
ユーザーとパスワードの使用: String user = context.getProperty(IContext.USERNAME_KEY); String pw = context.getProperty(IContext.PASSWORD_KEY);
この項では、ロケータとともに使用するPropertySetDefinition
の作成方法について説明します。
次の手順に従って、PropertySetDefinition
を作成します。
ソース・ファイルに対する新しいJDeveloperプロジェクトを作成します。
必要なパーソナライズ・クラスをプロジェクト・クラスパスに追加します。
プロジェクト名を右クリックし、「プロジェクト・プロパティ」を選択します。
「ライブラリとクラスパス」を選択し、「ライブラリの追加」を選択します。
検索するライブラリの名前を入力し(IPropertyLocatorなど)、表示されたらその名前を選択します。
ソース・コードから参照する必要があるその他のクラスに対して、これらの手順を繰り返します。
プロジェクトをコンパイルし、それをJARファイルにデプロイします。
JARファイルを、/DefaultDomain/locator-extensions-library/WEB-INF/lib
にあるパーソナライズ拡張ディレクトリにコピーします。
この項では、プロパティ・ロケータ、データ・オブジェクトおよびデータ層を実装する方法について説明します。
IPropertyLocatorの実装
(デモを簡素化するために、読取り専用になっています)
/** * Our locator will be read-only */ public class BookPropertyLocator implements IPropertyLocator { // Let's delegate all the hard work to a BookPropertyDAO private BookPropertyDAO dao; // Must have a public default constructor, since the Property Service instantiates // this public BookPropertyLocator() { // todo: show how connection properties could be initialized and passed in dao = new BookPropertyDAO(); } /** * Load property values, optionally returning only a subset of those. * @param iPropertySet The PropertySet into which the retrieved values will be loaded * @param iPropertySetDefinition The PropertySetDefinition defining the 'shape' of the properties * @param list List of PropertyNames to load. If null, all will be loaded. */ public void loadProperties(IContext context, IPropertySet iPropertySet, IPropertySetDefinition iPropertySetDefinition, List<IPropertyName> list) { try { // Delegate to BookProperDAO dao.loadProperties(iPropertySet, list); } catch (Exception e) { throw new RuntimeException("Cannot load properties ", e); } } /** * Filter properties; load/return those properties that only match the filter criteria. * @param iNameSpaceName * @param iPropertySetDefinitionName * @param propertySetFilterContext * @return */ public IPagedList<IPropertySet> filter(IContext context, INameSpaceName iNameSpaceName, IPropertySetDefinitionName iPropertySetDefinitionName, PropertySetFilterContext propertySetFilterContext) { return null; // todo: possibly implement for demo } public int count(IContext context, INameSpaceName iNameSpaceName, PropertySetExpression propertySetExpression) { return 0; } // 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"); } }
プロパティ値を取得するためのデータ・アクセス・オブジェクトを実装します。
/** * Data access class, to load books from a backing store (perhaps a database or * some REST service) */ class BookPropertyDAO { // Generate the library that will provide our backing store. static { Library.generateLibrary(); } /** * Assume the name of the PropertySet is the title of the book. * @param propertySet * @param list */ void loadProperties(IContext context, IPropertySet propertySet, List<IPropertyName> list) throws Exception { String title = propertySet.getPropertySetName().getName(); Book book = Library.getBook(title); loadProperties(book, propertySet, list); } private void loadProperties(IContext context, Book book, IPropertySet propertySet, List<IPropertyName> propertyNames) throws Exception { // Loop over all property names, create a Property value, and add it to the Property set for (IPropertyName pname : propertyNames) { // System.err.println("Getting property: " + pname + ", with name: " + pname.getName()); String value = book.getProperty(pname.getName()); if (value != null) { addProperty(value, pname, propertySet); } } } private void addProperty(IContext context, String value, IPropertyName pname, IPropertySet propertySet) { IProperty<String> ps = Property.<String>builder().withProperty(pname, value).buildWithOutValidation(); propertySet.putProperty(pname, ps); } }
データ層(図書館内の本)を実装します。
/** * Simple class to demonstrate loading properties. It could be improved by adding * support for non-String attributes (Date, arrays, etc) and using Java Bean * Introspection/Reflection to get the property values. */ 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) { // Here, we could use introspection on the Book class, but since there are only // three properties, we can code it simpler if (propName.equals("ISBN")) { return getISBN(); } if (propName.equals("title")) { return getTitle(); } if (propName.equals("author")) { return getAuthor(); } return null; // todo: perhaps throw Exception here } }
/** * Class to generate a library of Books */ 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); } }
PropertyLocator
はプロパティ・サービスによって起動され、それ自体がPropertiesServiceProvider
の一部として機能します。次のように、シナリオ内でこのプロバイダに対してGetProperties
メソッドを呼び出すことができます。
<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>