この章では、カスタム・アダプタをコーディングして登録する方法について説明します。内容は次のとおりです。
アダプタの主な役割の1つには、マーケット・データ・フィードなどのチャネルからのデータをOracle CEPイベントに変換する作業があります。これらのイベントはその後、プロセッサなどのアプリケーションの他のコンポーネントに渡されます。通常、アダプタはOracle CEPアプリケーションへのエントリ・ポイントです。アダプタは中間コンポーネントからのイベントを受信し、外部アプリケーションで読取り可能な形式にデータを変換し、それらのデータを送信するためアプリケーションの出口ポイントになる場合もあります。
『Oracle Complex Event Processingスタート・ガイド』のFXサンプルの説明には、通貨データ・フィードからデータを読み込み、ネットワークの次のコンポーネントであるプロセッサに特定のイベント・タイプの形式でデータを渡す3つのアダプタが示されています。
着信データの形式およびアダプタ・コードで変換に使用される技術に応じて、さまざまなタイプのアダプタを作成できます。最も一般的なタイプのアダプタは、以下のとおりです。
Reuters、Wombat、またはBloombergなどのデータ・ベンダーAPIを使用します。
標準のJMS APIを使用して着信JMSメッセージを変換します。
TIBCO Rendezvousなどの他のメッセージング・システムを使用します。
顧客独自のデータ・プロトコルへのソケット接続を使用します。
アダプタは、特定のOracle CEPインタフェースを実装するJavaクラスです。アプリケーション全体を記述するEPNアセンブリ・ファイルでアダプタ・クラスを登録します。
オプションで、アダプタのデフォルト構成を変更できます。また、構成を拡張したり、新しい構成要素および属性を追加することもできます。
構成データをアダプタに渡す方法は2つあります。デプロイの後で構成を動的に変更するかどうかに応じて選択する方法が異なります。
アダプタのデプロイ後に構成データを変更しない場合、アダプタをEPNアセンブリ・ファイルで構成できます。
ただし、構成要素を動的に変更する場合は、構成をアダプタ固有のコンポーネント構成ファイルに配置する必要があります。
この項では次について説明します:
アダプタは、イベント・ソース、イベント・シンク、またはその両方に使用できます。イベント・ソースはイベントを生成し、イベント・シンクはイベントを受信します。
com.bea.wlevs.ede.api.StreamSource
またはRelationSource
APIを実装して、EPN内のアダプタ・コンポーネントがイベント・ソースであることを指定します。
イベント・ソースであるカスタム・アダプタの実装クラスは、アプリケーションのプライベートとして指定するか、または他のアプリケーションによる再利用が可能な公開されたOSGIサービスとして指定できます。
wlevs:adapter
要素を使用してEPNアセンブリ・ファイルにアダプタを登録します。例:
<wlevs:adapter id="myAdapterSource" class="com.acme.MySourceAdapter"> </wlevs:adapter>
この例では、JavaクラスMySourceAdapter.java
がcom.bea.wlevs.ede.api.StreamSource
またはRelationSource
APIを実装します。
詳細は、14.2.2.1項「カスタム・アダプタをイベント・ソースとして実装」を参照してください。
カスタム・アダプタのイベント・シンクはcom.bea.wlevs.ede.api.StreamSink
またはRelationSink
APIを実装する必要がある以外はイベント・シンクとしてのカスタム・アダプタの機能はイベント・ソースによく似ています。
イベント・シンクはアクティブではないため、Runnable
インタフェースを実装している場合、Oracle CEPではこれらを個別のスレッドで実行しません。
wlevs:listener
要素を使用してEPNアセンブリ・ファイルでイベント・シンクを参照します。
<wlevs:adapter id="myAdapterSink" class="com.acme.MySinkAdapter"> </wlevs:adapter><wlevs:channel id="myStream" >
<wlevs:listener ref="myAdapterSink" />
</wlevs:channel>
この例では、JavaクラスMySinkAdapter.java
がcom.bea.wlevs.ede.api.StreamSink
またはRelationSink
APIを実装します。
詳細は、14.2.2.2項「カスタム・アダプタをイベント・シンクとして実装」を参照してください。
アダプタが単一のOracle CEPアプリケーションによってのみ使用される場合は、ファクトリを作成する必要はありません。ただし、同一のアダプタが複数のアプリケーションで使用される場合は、ファクトリもプログラミングする必要があります。この場合、それぞれのアプリケーションで固有のアダプタ・インスタンスが取得されます。
アダプタのファクトリはcom.bea.wlevs.ede.api.Factory
インタフェースを実装する必要があります。このインタフェースには、アダプタまたはイベントBeanのインスタンスを作成するために実装する単一のメソッドcreate
が含まれています。
wlevs:factory
要素を使用してEPNアセンブリ・ファイルにファクトリを登録します。
<wlevs:factory provider-name="myprovider" class="my.Implementation"/>
サービスのプロパティを指定する必要がある場合は、osgi:service
要素を使用してファクトリを登録する必要があります。
デフォルトでは、アダプタはシングルスレッドです。つまり、アダプタは、シングルスレッドを使用してデータ・ソースからメッセージを読み取ります。
アダプタがシングルスレッドであると、イベント順序が保証されます。
スケーラビリティを向上させるために、アダプタでマルチスレッドを使用してデータ・ソースから読み取るように構成できます。このように構成する場合、最も簡単な方法はワーク・マネージャを使用してアダプタを構成することです。アダプタだけが使用する専用のワーク・マネージャを指定するか、他のアダプタやJettyなどのいくつかのコンポーネントでワーク・マネージャを共有できます。
アダプタがマルチスレッドであると、イベント順序は保証されません。
詳細については、次を参照してください。
作成するJavaクラスにカスタム・アダプタを実装します。このJavaクラスを作成するには、次のどちらかの手順を実行します。
14.2.1項「Antを使用したカスタム・アダプタの実装方法」で説明するように、Antを使用して完全に機能する空のアダプタを作成し、この生成されたクラスをアプリケーションに適合するように修正します。
14.2.2項「カスタム・アダプタを手動で構成する方法」で説明するように、アダプタJavaクラスを手動で作成します。
詳細は、14.1項「カスタム・アダプタの概要」を参照してください。
次の手順は、Oracle CEP AntタスクTBD
を使用して、完全に機能する空のアダプタを生成する方法について説明します。
Antを使用してカスタム・アダプタを実装するには、次の手順を実行します。
オプションとして、ファクトリ・クラスをプログラミングします。
多数のアプリケーションでカスタム・アダプタを使用する場合に限りこの処理が必要です。
14.2.3項「カスタム・アダプタ・ファクトリの実装」を参照してください。
オプションとして、デフォルトのコンポーネント構成が適切でない場合に、カスタム・アダプタのコンポーネント構成を拡張します。
第19章「コンポーネント構成の拡張」を参照してください。
カスタム・アダプタを構成します。
詳細については、次を参照してください。
次の手順は、カスタム・アダプタを手動で作成するための一般的なステップを示します。
注意: 次の手順では、プロセッサ、ストリーム、ビジネス・ロジックPOJOなどのイベント・ネットワークの他のコンポーネントが含まれている同一のアプリケーションJARファイルにカスタム・アダプタがバンドルされると想定しています。複数のアプリケーションで共有できるようにカスタム・アダプタを固有のJARファイルにバンドルする必要がある場合は、24.2.4.1項「カスタム・アダプタの固有のバンドルでのアセンブリ方法」を参照してください。 |
カスタム・アダプタを実装するには、次の手順を実行します。
カスタム・アダプタJavaクラスをプログラミングします。
カスタム・アダプタがイベント・ソースである場合は、14.2.2.1項「カスタム・アダプタをイベント・ソースとして実装」を参照してください。
カスタム・アダプタがイベント・シンクである場合は、14.2.2.2項「カスタム・アダプタをイベント・シンクとして実装」を参照してください。
カスタム・アダプタがイベント・ソースおよびイベント・シンクの両方である場合は、両方の項を参照してください。
カスタム・アダプタがデータ・フィード・プロバイダを使用して自身を認証する必要がある場合は、14.3項「アダプタからデータ・フィード・プロバイダへのログイン資格証明の受け渡し」を参照してください。
オプションとして、ファクトリ・クラスをプログラミングします。
多数のアプリケーションでカスタム・アダプタを使用する場合に限りこの処理が必要です。
14.2.3項「カスタム・アダプタ・ファクトリの実装」を参照してください。
オプションとして、デフォルトのコンポーネント構成が適切でない場合に、カスタム・アダプタのコンポーネント構成を拡張します。
第19章「コンポーネント構成の拡張」を参照してください。
カスタム・アダプタを構成します。
詳細については、次を参照してください。
この項では、イベント・ソースとして動作するカスタム・アダプタを作成する方法について説明します。このカスタム・アダプタは着信データを受け取り、それをEPNの次のコンポーネントに送信するイベントを生成します。
着信カスタム・アダプタ・クラスは、通常マーケット・データ・フィードなどからの着信データのストリームを読み込み、アプリケーションの残りの部分によって認識されるOracle CEPイベント・タイプに変換し、ネットワークの次のコンポーネントにイベントを送信します。
次の例は、空間サンプルのカスタム・アダプタ・クラスを示します。Javaコードの太字部分に対応するコーディングのガイドラインについては、例の後で説明しています。
package com.oracle.cep.sample.spatial; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.bea.wlevs.ede.api.EventProperty; import com.bea.wlevs.ede.api.EventRejectedException; import com.bea.wlevs.ede.api.EventType; import com.bea.wlevs.ede.api.EventTypeRepository; import com.bea.wlevs.ede.api.RunnableBean; import com.bea.wlevs.ede.api.StreamSender; import com.bea.wlevs.ede.api.StreamSink; import com.bea.wlevs.ede.api.StreamSource; import com.bea.wlevs.util.Service; import java.lang.RuntimeException; import oracle.spatial.geometry.JGeometry; import com.oracle.cep.cartridge.spatial.Geometry; public class BusStopAdapter implements RunnableBean, StreamSource, StreamSink { private final static String APP_NAME = "spatial_sample"; ... private String m_eventTypeName; private EventType m_eventType; private StreamSender m_eventSender; ... public BusStopAdapter() { super(); } ... @Service(filter = EventTypeRepository.SERVICE_FILTER) public void setEventTypeRepository(EventTypeRepository etr) { m_etr = etr; } public void setShow(boolean b) { m_show = b; } public void run() { m_stopped = false; // Need to store running thread so that it can be interrrupted in case of // suspend. m_runningThread = Thread.currentThread(); if (m_etr == null) { throw new RuntimeException("EventTypeRepoitory is not set"); } m_eventType = m_etr.getEventType(m_eventTypeName); if (m_eventType == null) { throw new RuntimeException("EventType(" + m_eventType + ") is not found."); } s_logger.info("fileSource " + m_filePath); if (m_initialDelay > 0) { try { s_logger.info("Sleeping for : " + m_initialDelay); Thread.sleep(m_initialDelay); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (this) { while (!m_start) { try { this.wait(); } catch (InterruptedException e) { } } } BufferedReader reader = null; System.out.println("Sending " + m_eventType + " from " + m_filePath); while ((m_repeat != 0) && (!m_stopped)) { try { s_logger.info("Starting fileSource " + m_filePath); m_lineno = 0; reader = new BufferedReader(new FileReader(m_filePath)); } catch (Exception e) { s_logger.warn(e.toString()); m_stopped = true; break; } while (!isStopped()) { try { Object ev = null; ev = readLine(reader); if (ev == null) { reader.close(); break; } m_eventSender.sendInsertEvent(ev); if (m_show) { System.out.println(ev.toString()); } } catch (Exception e) { s_logger.fatal("Failed to get tuple from " + m_filePath + ":" + m_lineno + "\n" + e.toString() + "\n"); m_stopped = true; break; } if (m_sleep > 0) { try { synchronized (this) { // We need to save thread so that it can be interrupted in case of // suspend. wait(m_sleep); } } catch (InterruptedException e) { s_logger.warn(e); break; } } } // while if (m_repeat > 0) m_repeat--; } // while s_logger.info("FileAdaptor " + hashCode() + " stopped. " + m_filePath); } public void setEventSender(StreamSender sender) { m_eventSender = sender; } ... }
アダプタJavaクラスのプログラミングでは、次のガイドラインに従います。上記の例でガイドラインのコード例は太字で示されています。
Oracle CEP APIのインタフェースおよびクラスをインポートします。
import com.bea.wlevs.ede.api.StreamSender; import com.bea.wlevs.ede.api.StreamSource; import com.bea.wlevs.ede.api.RunnableBean;
アダプタはイベント・ソースであるため、StreamSource
インタフェースを実装する必要があります。アダプタをスレッドで実行する必要がある場合は、RunnableBean
も実装します。StreamSender
インタフェースは、イベント・タイプをアプリケーション・ネットワークの次のコンポーネントに送信します。これらのAPIの完全な詳細は、Oracle Fusion Middleware Oracle Complex Event Processing Java APIリファレンスを参照してください。
アダプタ・クラスはイベント・ソースであり、固有のスレッドで実行されるため、StreamSource
およびRunnableBean
インタフェースを実装する必要があります。
public class BusStopAdapter implements RunnableBean, StreamSource, StreamSink
StreamSource
インタフェースではイベントの送信に使用されるStreamSender
が提供されます。
RunnableBean
インタフェースが実装されるため、アダプタではrun
メソッドを実装する必要があります。
public void run() {...
ここに、マーケット・フィードなどからの着信データを読み込み、Oracle CEPイベント・タイプに変換し、ネットワークの次のコンポーネントにイベントを送信するコードを配置する必要があります。着信データの読込み方法の詳細については、データ・フィード・プロバイダのドキュメントを参照してください。サード・パーティJARファイルにパッケージ化されているベンダーAPIに確実にアクセスできるための情報は、24.2.2.2項「サード・パーティJARファイルへのアクセス」を参照してください。
空間サンプルでは、readLine
保護メソッドを使用してアダプタ自体が着信データを生成します。これは説明のためであり、実際のシナリオではありません。
詳細は、第2章「Oracle CEPイベント・タイプの作成」を参照してください。
アダプタではStreamSource
が実装されるため、イベントの送信に使用されるStreamSender
を渡すsetEventSender
メソッドを実装する必要があります。
public void setEventSender(StreamSender sender) { ...
通常のケースと同様、アダプタでSuspendableBean
が実装される場合は、たとえばアプリケーションがアンデプロイされた場合などにアダプタを停止するsuspend
メソッドを実装する必要があります。
public synchronized void suspend() throws Exception { ...
次のコード例は、HelloWorldアプリケーションでイベント・シンクとして動作するSpring Beanです。太字部分のコードについては、例の後で説明しています。
次の例は、空間サンプルのカスタム・アダプタ・クラスを示します。Javaコードの太字部分に対応するコーディングのガイドラインについては、例の後で説明しています。
package com.oracle.cep.sample.spatial; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.bea.wlevs.ede.api.EventProperty; import com.bea.wlevs.ede.api.EventRejectedException; import com.bea.wlevs.ede.api.EventType; import com.bea.wlevs.ede.api.EventTypeRepository; import com.bea.wlevs.ede.api.RunnableBean; import com.bea.wlevs.ede.api.StreamSender; import com.bea.wlevs.ede.api.StreamSink; import com.bea.wlevs.ede.api.StreamSource; import com.bea.wlevs.util.Service; import java.lang.RuntimeException; import oracle.spatial.geometry.JGeometry; import com.oracle.cep.cartridge.spatial.Geometry; public class BusStopAdapter implements RunnableBean, StreamSource, StreamSink { private final static String APP_NAME = "spatial_sample"; ... private String m_eventTypeName; private EventType m_eventType; private StreamSender m_eventSender; ... public BusStopAdapter() { super(); } ... @Service(filter = EventTypeRepository.SERVICE_FILTER) public void setEventTypeRepository(EventTypeRepository etr) { m_etr = etr; } public void setShow(boolean b) { m_show = b; } public void run() { m_stopped = false; // Need to store running thread so that it can be interrrupted in case of // suspend. m_runningThread = Thread.currentThread(); if (m_etr == null) { throw new RuntimeException("EventTypeRepoitory is not set"); } m_eventType = m_etr.getEventType(m_eventTypeName); if (m_eventType == null) { throw new RuntimeException("EventType(" + m_eventType + ") is not found."); } s_logger.info("fileSource " + m_filePath); if (m_initialDelay > 0) { try { s_logger.info("Sleeping for : " + m_initialDelay); Thread.sleep(m_initialDelay); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (this) { while (!m_start) { try { this.wait(); } catch (InterruptedException e) { } } } BufferedReader reader = null; System.out.println("Sending " + m_eventType + " from " + m_filePath); while ((m_repeat != 0) && (!m_stopped)) { try { s_logger.info("Starting fileSource " + m_filePath); m_lineno = 0; reader = new BufferedReader(new FileReader(m_filePath)); } catch (Exception e) { s_logger.warn(e.toString()); m_stopped = true; break; } while (!isStopped()) { try { Object ev = null; ev = readLine(reader); if (ev == null) { reader.close(); break; } m_eventSender.sendInsertEvent(ev); if (m_show) { System.out.println(ev.toString()); } } catch (Exception e) { s_logger.fatal("Failed to get tuple from " + m_filePath + ":" + m_lineno + "\n" + e.toString() + "\n"); m_stopped = true; break; } if (m_sleep > 0) { try { synchronized (this) { // We need to save thread so that it can be interrupted in case of // suspend. wait(m_sleep); } } catch (InterruptedException e) { s_logger.warn(e); break; } } } // while if (m_repeat > 0) m_repeat--; } // while s_logger.info("FileAdaptor " + hashCode() + " stopped. " + m_filePath); } @Override public void onInsertEvent(Object event) throws EventRejectedException { if (!m_start) { m_start = true; synchronized (this) { notify(); } } } ... }
上記の例に示したプログラミングのガイドラインは、次のとおりです。
カスタム・アダプタはcom.bea.wlevs.ede.api.StreamSink
インタフェースを実装する必要があります。
public class BusStopAdapter implements RunnableBean, StreamSource, StreamSink
StreamSink
インタフェースは、実装する必要のあるonInsertEvent (java.lang.Object)
という単一のメソッドがあります。このメソッドは、イベントを受信するためのコールバック・メソッドです。メソッドパラメータはオブジェクト
であり、イベントを送信したコンポーネントからBeanが受信した実際のイベントを表現します。
public void onInsertEvent(Object event)
この項で説明しているOracle CEP APIの完全なAPIリファレンス情報については、Oracle Fusion Middleware Oracle Complex Event Processing Java APIリファレンスを参照してください。
アダプタ・ファクトリ・クラスはcom.bea.wlevs.ede.api.AdapterFactory
インタフェースを実装する必要があり、これには1つのメソッドcreate
が含まれていますが、ここに特定のアダプタ・クラスを作成するコードを作成します。イベントBeanはFactory
を実装します。
次の例は、HelloWorldのサンプルで使用可能なアダプタ・ファクトリ・クラスです。
package com.bea.adapter.wlevs.example.helloworld; import com.bea.wlevs.ede.api.Adapter; import com.bea.wlevs.ede.api.AdapterFactory; public class HelloWorldAdapterFactory implements Factory { public HelloWorldAdapterFactory() { } public synchronized Adapter create() throws IllegalArgumentException { return new HelloWorldAdapter(); } }
これらのAPIの詳細は、Oracle Fusion Middleware Oracle Complex Event Processing Java APIリファレンスを参照してください。
外部データ・フィードにアクセスする場合、アダプタはユーザー認証のためログイン資格証明(ユーザー名とパスワード)をデータ・フィードに渡す必要がある場合があります。
最も簡単で安全性の低い方法は、アダプタのJavaコード内に暗号化されていないログイン資格証明をハード・コード化することです。ただし、この方法ではパスワードを暗号化することができず、アダプタのJavaコードを再コンパイルせずに後からログイン資格証明を変更することもできません。
次の手順では、これらの問題が考慮された異なる方法について説明します。この手順では、データ・フィードにアクセスするユーザー名にjuliet
、パスワードにsuperSecret
を想定しています。
ログイン資格証明をEPNアセンブリ・ファイルで静的に構成するか、アダプタの構成を拡張して動的に構成するかを指定する必要があります。EPNアセンブリ・ファイルで資格証明を静的に構成する方が簡単ですが、後から資格証明が変更された場合は、EPNアセンブリ・ファイルへの更新が反映されるようにアプリケーションを再起動する必要があります。アダプタの構成を拡張する方法では、アプリケーションを再起動せずに資格証明を動的に変更できますが、構成の拡張には、XSDファイルの作成や、JAXBオブジェクトへのコンパイルなどの追加の手順が必要になります。
この項では次について説明します:
詳細は、第19章「コンポーネント構成の拡張」を参照してください。
この手順では、EPNアセンブリ・ファイルで静的に構成したログイン資格証明を渡す方法について説明します。
データ・フィード・プロバイダへ静的ログイン資格証明を受け渡すには、次の手順を実行します。
コマンド・ウィンドウを開き、『Oracle Complex Event Processingスタート・ガイド』の開発環境の設定に関する項の説明に従って、環境を設定します。
アプリケーションのEPNアセンブリ・ファイルがあるディレクトリに移動します。
任意のXMLエディタを使用し、EPNアセンブリ・ファイルを編集して、アダプタを宣言しているwlevs:adapter
要素を更新します。
特に、ログイン資格証明のユーザー名とパスワードに対応する2つのインスタンス・プロパティを追加します。ここで、cleartextのパスワード値を指定します。後からこの値は暗号化されます。また、一時password
要素を追加し、その値はcleartextパスワードにします。例:
<wlevs:adapter id="myAdapter" provider="myProvider"> <wlevs:instance-property name="user" value="juliet"/> <wlevs:instance-property name="password" value="superSecret"/> <password>superSecret</password> </wlevs:adapter>
EPNアセンブリ・ファイルを保存します。
EPNアセンブリ・ファイルのpassword
要素の値を暗号化するためにencryptMSAConfig
コマンドを実行します。
prompt> ORACLE_CEP_HOME/ocep_11.1/bin/encryptMSAConfig . epn_assembly_file msainternal.dat_file
ORACLE_CEP_HOME
は、d:\oracle_cep
などのOracle CEPのインストール先のメイン・ディレクトリです。2番目の引数はEPNアセンブリ・ファイルが含まれているディレクトリです。この手順では実際にそのディレクトリに移動しているため、例では「.
」と示されています。epn_assembly_file
パラメータはEPNアセンブリ・ファイルの名前です。最後に、msainternal.dat_file
パラメータは、ドメインに関連付けられている.msainternal.dat
ファイルの場所です。デフォルトでは、このファイルはDOMAIN_DIR
/servername
ディレクトリにあります。DOMAIN_DIR
は、/oracle_cep/user_projects/domains/mydomain
などのドメイン・ディレクトリで、servername
はサーバー・インスタンスです。
詳細は、『Oracle Complex Event Processing管理者ガイド』のencryptMSAConfigコマンドライン・ユーティリティに関する項を参照してください。
コマンドを実行すると、EPNアセンブリ・ファイルのpassword
要素の値が暗号化されます。
EPNアセンブリ・ファイルを編集します。
password
要素の暗号化された値をpassword
インスタンス・プロパティのvalue
属性にコピーします。
password
要素をXMLファイルから削除します。
例:
<wlevs:adapter id="myAdapter" provider="myProvider">
<wlevs:instance-property name="user" value="juliet"/>
<wlevs:instance-property name="password"
value="{Salted-3DES}B7L6nehu7dgPtJJTnTJWRA=="/>
</wlevs:adapter>
構成されたログイン資格証明のプロパティにアクセスしてパスワードを復号化するよう、アダプタのJavaコードを更新します。
14.3.1項「データ・フィード・プロバイダへの静的ログイン資格証明の受け渡し」を参照してください。
アプリケーションのMANIFEST.MF
ファイルを編集し、Import-Package
ヘッダーにcom.bea.core.encryption
パッケージを追加します。24.2.2.1項「MANIFEST.MFファイルの作成」を参照してください。
アプリケーションを通常通り再アセンブルしてデプロイします。第24章「Oracle CEPアプリケーションのアセンブルおよびデプロイ」を参照してください。
この手順では、アダプタの構成を拡張して動的に構成したログイン資格証明を渡す方法について説明します。
データ・フィード・プロバイダへ動的ログイン資格証明を受け渡すには、次の手順を実行します。
String
型の2つの新しい要素user
およびpassword
を追加してアダプタの構成を拡張します。
たとえば、HelloWorldのサンプルのアダプタを拡張した場合、XSDファイルは次のようになります。
<xs:complexType name="HelloWorldAdapterConfig"> <xs:complexContent> <xs:extension base="wlevs:AdapterConfig"> <xs:sequence> <xs:element name="message" type="xs:string"/> <xs:element name="user" type="xs:string"/> <xs:element name="password" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType>
詳細は、第19章「コンポーネント構成の拡張」を参照してください。
コマンド・ウィンドウを開き、『Oracle Complex Event Processingスタート・ガイド』の開発環境の設定に関する項の説明に従って、環境を設定します。
アダプタのコンポーネント構成XMLファイルがあるディレクトリに移動します。
任意のXMLエディタを使用してこのコンポーネント構成XMLファイルを編集し、<user>
および<password>
要素を使用して必要なログイン資格証明を追加します。ここでは、クリア・テキストのパスワード値を指定します。これは後から暗号化されます。例:
<?xml version="1.0" encoding="UTF-8"?> <myExample:config xmlns:myExample="http://www.bea.com/xml/ns/wlevs/example/myExample"> <adapter> <name>myAdapter</name> <user>juliet</user> <password>superSecret</password> </adapter> </myExample:config>
アダプタの構成ファイルを保存します。
アダプタ構成ファイルのpassword
要素の値を暗号化するためにencryptMSAConfig
コマンドを実行します。
prompt> ORACLE_CEP_HOME/ocep_11.1/bin/encryptMSAConfig
. adapter_config_file msainternal.dat_file
ORACLE_CEP_HOME
は、d:\oracle_cep
などのOracle CEPのインストール先のメイン・ディレクトリです。2番目の引数はアダプタの構成ファイルが含まれているディレクトリです。この手順では実際にそのディレクトリに移動しているため、例では「.
」と示されています。adapter_config_file
パラメータはアダプタ構成ファイルの名前です。最後に、msainternal.dat_file
パラメータは、ドメインに関連付けられている.msainternal.dat
ファイルの場所です。デフォルトでは、このファイルはDOMAIN_DIR
/servername
ディレクトリにあります。DOMAIN_DIR
は、/oracle_cep/user_projects/domains/mydomain
などのドメイン・ディレクトリで、servername
はサーバー・インスタンスです。
詳細は、『Oracle Complex Event Processing管理者ガイド』のencryptMSAConfigコマンドライン・ユーティリティに関する項を参照してください。
コマンドを実行すると、password
要素の値が暗号化されます。
構成されたログイン資格証明のプロパティにアクセスしてパスワードを復号化するよう、アダプタのJavaコードを更新します。
14.3.1項「データ・フィード・プロバイダへの静的ログイン資格証明の受け渡し」を参照してください。
アプリケーションのMANIFEST.MF
ファイルを編集し、Import-Package
ヘッダーにcom.bea.core.encryption
パッケージを追加します。24.2.2.1項「MANIFEST.MFファイルの作成」を参照してください。
アプリケーションを通常通り再アセンブルしてデプロイします。第24章「Oracle CEPアプリケーションのアセンブルおよびデプロイ」を参照してください。
この項では、拡張されたアダプタ構成から動的にユーザーとパスワードの値を取得し、com.bea.core.encryption.EncryptionService
APIを使用して暗号化されたパスワードを復号化するようにカスタム・アダプタのJavaコードを更新する方法について説明します。
次に示すコード・スニペットは、14.2.2.1項「カスタム・アダプタをイベント・ソースとして実装」に示したアダプタのJavaコードのHelloWorldを基に作成されます。
実行時にログイン資格証明プロパティにアクセスするには、次の手順を実行します。
暗号化されたパスワードの複合化に必要な追加のAPIをインポートします。
import com.bea.core.encryption.EncryptionService; import com.bea.core.encryption.EncryptionServiceException; import com.bea.wlevs.util.Service;
@Service
注釈を使用してEncryptionService
への参照を取得します。
private EncryptionService encryptionService; ... @Service public void setEncryptionService(EncryptionService encryptionService) { this.encryptionService = encryptionService; }
@Prepare
コールバック・メソッドで、拡張されたアダプタ構成のuser
およびpassword
プロパティの値を通常どおり取得します(password
値のコードのみ示しています)。
private String password;
...
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
...
@Prepare
public void checkConfiguration(HelloWorldAdapterConfig adapterConfig) {
if (adapterConfig.getMessage() == null
|| adapterConfig.getMessage().length() == 0) {
throw new RuntimeException("invalid message: " + message);
}
this.password= adapterConfig.getPassword();
...
}
拡張されたアダプタ構成へのアクセスに関する情報は、19.3項「カスタム・アダプタまたはイベントBeanの構成へのプログラムからのアクセス」を参照してください。
@Prepare
コールバック・メソッドでEncryptionService.decryptStringAsCharArray
メソッドを使用して暗号化されたパスワードを複合化します。
@Prepare public void checkConfiguration(HelloWorldAdapterConfig adapterConfig) { if (adapterConfig.getMessage() == null || adapterConfig.getMessage().length() == 0) { throw new RuntimeException("invalid message: " + message); } this.password= adapterConfig.getPassword(); try { char[] decrypted = encryptionService.decryptStringAsCharArray(password); System.out.println("DECRYPTED PASSWORD is "+ new String(decrypted)); } catch (EncryptionServiceException e) { throw new RuntimeException(e); } }
decryptStringAsCharArray
メソッドのシグネチャは次のとおりです。
char[] decryptStringAsCharArray(String encryptedString) throws EncryptionServiceException
ベンダーAPIを使用してこれらの資格証明をデータ・フィード・プロバイダに渡します。
次の項で説明しているように、アダプタおよびアダプタ・ファクトリ(使用する場合)をEPNアセンブリ・ファイルに登録する必要があります。
アプリケーションの他のコンポーネントの登録を含む、構成ファイルの完全な説明は、4.3項「EPNアセンブリ・ファイルの作成」を参照してください。
wlevs:factory
要素を使用してEPNアセンブリ・ファイルにファクトリを登録します。
<wlevs:factory provider-name="myprovider" class="my.Implementation"/>
サービスのプロパティを指定する必要がある場合は、osgi:service>
要素を使用して、EPNアセンブリ・ファイルにOSGIサービスとしてファクトリを登録する必要があります。OSGIサービス・レジストリのスコープはOracle CEP全体です。このため、指定のサーバーにデプロイされた複数のアプリケーションが同じアダプタ・ファクトリを使用する場合は、アダプタ・ファクトリをOSGIサービスとして登録するのが必ず一度きりになるようにします。
エントリを追加して、サービスをcom.bea.wlevs.ede.api.AdapterFactory
インタフェースの実装として登録します。key
属性のtype
、およびこのアダプタ・プロバイダを参照する名前を使用して、プロパティを指定します。最後に、ネストされた標準のSpring bean
要素を追加して、Springアプリケーション・コンテキストで特定のアダプタ・クラスを登録します。
たとえば、EPNアセンブリ・ファイルの次の部分では、HelloWorldAdapterFactory
をタイプhellomsgs
のプロバイダとして登録します。
<osgi:service interface="com.bea.wlevs.ede.api.AdapterFactory"> <osgi:service-properties> <entry key="type" value="hellomsgs"</entry> </osgi:service-properties> <bean class="com.bea.adapter.wlevs.example.helloworld.HelloWorldAdapterFactory" /> </osgi:service>
type
でファクトリを参照する方法については、14.4.2項「アプリケーションのカスタム・アダプタ・コンポーネントの宣言」を参照してください。
EPNアセンブリ・ファイルでは、wlevs:adapter
要素を使用してアダプタをイベント・プロセッサ・ネットワークのコンポーネントとして宣言します。例:
<wlevs:adapter id="recplayEventSink" class="com.bea.wlevs.example.recplayRecplayEventSink"> <wlevs:listener ref="playbackHttpPublisher"/> </wlevs:adapter>
オプションのファクトリをOSGIサービスとして登録した場合は、provider
属性を使用して、osgi:service
エントリでtype
として指定した名前を参照します。例:
<wlevs:adapter id="helloworldAdapter" provider="hellomsgs"/>
これにより、アダプタはタイプhellomsgs
で登録されたファクトリによってインスタンス化されます。
wlevs:adapter
のwlevs:instance-property
子要素を使用して、アダプタBeanの静的プロパティを設定することもできます。静的プロパティはアダプタのデプロイ後に動的に変更されないプロパティです。
たとえば、アダプタ・クラスにsetPort
メソッドが含まれている場合は、次のようにポート番号を渡すことができます。
<wlevs:adapter id="myAdapter" provider="myProvider"> <wlevs:instance-property name="port" value="9001" /> </wlevs:adapter>
アプリケーションの各アダプタにはデフォルトの構成があり、オプションで拡張コンポーネント構成を持つものがあります。
アプリケーションに複数のアダプタが含まれている場合は、各アダプタごとに個別のコンポーネント構成XMLファイルを作成するか、すべてのアダプタのコンフィグレーションが含まれた単一のコンポーネント構成XMLファイルを作成するか、またはアプリケーションのすべてのコンポーネント(アダプタ、プロセッサ、およびストリーム)が含まれたファイルを作成できます。開発環境に最も適した方法を選択します。
次の手順では、アダプタの構成ファイルを作成する主なステップについて示します。簡略化のため、この手順ではアプリケーションのすべてのコンポーネントを1つのXMLファイルに構成することを想定しています。
詳細については、次を参照してください。
次の手順では、カスタム・アダプタを手動で構成する方法について説明します。
カスタム・アダプタ・コンポーネント構成ファイルを構成するには、次の手順を実行します。
お気に入りのXMLエディタを使用してXMLファイルを作成します。
このXMLファイルの名前は自分で決定しますが、その拡張は.xml
で終了することが必要です。
構成ファイルのルート要素はconfig
であり、次のステップに示すネームスペース定義を使用します。
アプリケーションの各アダプタは、config
のadapter
子要素を追加します。
name
子要素で各アダプタを一意に識別します。この名前は、アプリケーションのイベント処理ネットワークを定義するEPNアセンブリ・ファイルのwlevs:adapter
要素のid
属性の値と一致している必要があります。このように指定することで、Oracle CEPでは、このアダプタ構成が適用されるEPNアセンブリ・ファイル内の特定のアダプタ・コンポーネントを認識します。詳細は、4.3項「EPNアセンブリ・ファイルの作成」を参照してください。
たとえば、アプリケーションに2つのアダプタがある場合、構成ファイルは最初に次のようになります。
<?xml version="1.0" encoding="UTF-8"?> <helloworld:config xmlns:helloworld="http://www.bea.com/xml/ns/wlevs/example/helloworld"> <processor> ... </processor> <adapter> <name>firstAdapter</name> ... </adapter> <adapter> <name>secondAdapter</name> ... </adapter> </helloworld:config>
この例では、構成ファイルにfirstAdapter
とsecondAdapter
の2つのアダプタが含まれています。このため、EPNアセンブリ・ファイルには同じ識別子を持つアダプタが少なくとも2つ登録されている必要があります。
<wlevs:adapter id="firstAdapter" ...> ... </wlevs:adapter> <wlevs:adapter id="secondAdapter" ...> ... </wlevs:adapter>
注意: XMLファイルの識別子と名前は大/小文字が区別されるため、EPNアセンブリ・ファイルでコンポーネントの識別子を参照するときは、必ず大/小文字を同一にします。 |
次のXMLファイルの例は、firstAdapter
およびsecondAdapter
の2つのアダプタを構成する方法を示します。
<?xml version="1.0" encoding="UTF-8"?> <sample:config xmlns:sample="http://www.bea.com/xml/ns/wlevs/example/sample"> <adapter> <name>firstAdapter</name> </adapter> <adapter> <name>secondAdapter</name> </adapter> </sample:config>