[SOA] Fanning Out Events on the Oracle SOA Suite 11g Event Delivery Network
Kamis, 20 Juni 2013
0
komentar
http://www.oracle.com/technetwork/articles/soa/jellema-events-soasuite-1902429.html
著者について
Lucas Jellemaは、1994年以来(Oracleと共に)ITで活躍してきました。 Oracle Fusion MiddlewareのOracle ACE DirectorであるLucasは、Oracle Database(SQL、PL/SQL)、サービス指向アーキテクチャ、ADF、およびJavaを含む多様な分野でのコンサルタント、トレーナー、およびインストラクターです。彼はOracle SOA Suite 11g Handbookの著者であり、JavaOne、Oracle Open World、ODTUG Kaleidoscope、Devoxx、その他のコンファレンスでたくさんの発表を行っています。
Oracle SOA Suite 11g Handbook / By Lucas Jellema (Oracle Bookstore)
http://astore.amazon.com/oraclebooks-20/detail/0071608974
サンプルはこちら。
Sample code for this article (zip, 54kb)
http://www.oracle.com/technetwork/articles/soa/fanoutevent-sources-1903159.zip
Overview
この記事ではOracle SOA Suite 11gでイベントを使い、最大限分断しつつ、意味のある形で相互にビジネスプロセスが影響を与える方法をご説明します。具体的には、この記事ではEvent Delivery Network (EDN)イベントをよりきめ細かいレベルに広げるためのソリューションです。これを使うと、一つのイベントが複数の実行中のBusiness Process Execution Language (BPEL)プロセスのインスタンスに影響を及ぼすことができます。この記事では以下のOracle SOA Suite 11gコンポーネントを利用します。- BPEL
- Mediator
- Event Delivery Network
- Spring
- Locator API
- Composite Sensors
Introduction
イベントとはメッセージですが、特定のコンシューマをターゲットにしていません。SOA環境においては、コンポーネント間の依存性を減らし、再利用性や柔軟性を増すためにdecoupling(分断)が主要な目的の一つであるため、イベントは極限まで分断して情報を共有するための価値ある方法です。イベントのパブリッシャーは潜在的に他のコンポーネントが関心を持っているビジネスの状況を知るコンポーネントです。コンポーネントが責任をもって、関連する詳細情報と共に汎用的なイベントハンドラ基盤に対しイベントを渡します。パブリッシャーはイベントのサブスクライバーのことは認識していません。パブリッシャーはイベントで何が起こり、誰がイベントを消費するのか知っている必要はありません。
特定のビジネス·イベントに関心を持つすべてのコンポーネントが、イベントハンドラインフラストラクチャを使い、これらのイベントのリスナーとして登録できます。特定のビジネスイベントタイプのイベントがイベントハンドラに渡されるたびに、サブスクライブしているすべてのリスナーにイベントが発行されます。イベントのコンシューマーは、どこでイベントが発生し、どのように配信されるのかを知る必要はありません。
図1 |
Events in the Oracle SOA Suite: EDN and BPEL
Oracle SOA Suite 11gはイベントハンドラ基盤を備えており、この基盤はビジネスイベントのパブリッシャーにとって仲介者であるとともに、こうしたイベントのコンシューマーでもあります。この基盤をEvent Delivery Network (EDN)と呼んでいます。(注意)SCAコンポジットアプリケーションでイベントと共にJMSやAQを利用できます。
EDNで特定のイベントをサブスクライブ可能なコンポーネントの一つにBPELがあります。MediatorやBPMNもEDNイベントをサブスクライブできます。BPELプロセスはEDNイベントを次の2方法のうち1方法で受け取ることができます。
- イベントで新しいBPELプロセスインスタンスを生成する
- イベントが実行中のBPELプロセスインスタンスに消費される
ビジネスの条件が事前に定義されたビジネスイベントに対応するものと認識されているならば、イベントを発行します。イベントに反応して何が起こるか、どこで誰によって起こるかは目に見えないし、イベントのパブリッシャーにとっては無関係です。
この記事では、Termination of Customer(顧客の終了)というイベントを検討します。このイベントは、会社が顧客とのすべての取引を中止するべきであることを意味します。任意のセールスサイクルが中止され、全く出荷が行われず、保留中の注文がキャンセルされます。この影響力のあるイベントは、例えば顧客が破産を申請したとか、特定の連邦政府の調査対象であるような場合にパブリッシュされます。先ほど述べたように、イベントの発生元とその原因はイベントコンシューマーにとっては無関係です。終了対象の顧客のIDというシンプルなペイロードでイベントを流す必要があります。
図2 |
図3 |
図4 |
The challenge at hand
すでにこの記事で直面している課題に目星がついていることでしょう。一つのTerminateCustomerイベントが多くのProcessOrderというBPELインスタンスに影響を与える可能性がある、ということです。しかし、これらのインスタンスは、その一意の識別子に基づいて着信イベントと相関させることができます。それゆえ、EDNの任意のイベントをせいぜい一つのBPELプロセスのインスタンスが消費できるのです。同じ顧客に対して同時に処理されている複数のオーダーが存在し得るので、ProcessOrderインスタンスをCustomerIDで一意に識別することができません。その代わりに、ProcessOrderインスタンスはそのOrderIDで識別されています。
イベントを発行し、現在その取引を停止する顧客のために処理されているすべての注文のために、一つのTerminateCustomerイベントを複数のAbortOrderForCustomerイベントに変換する解決策を見つける必要があります。 AbortOrderForCustomerイベントのペイロードには、OrderIDが含まれており、これを使ってProcessOrderというBPELプロセスの1つのインスタンスに正確に関連付けることができます。
図5 |
Addressing the challenge
やるべきことは明確で、ビジネスイベントと紐付けるきめ細かい詳細情報を見つけ出し、その各々の詳細情報に対し、適切なイベントを発行する、ということです。この場合、ビジネス·オブジェクトのCustomerに詳細Orderオブジェクトが関連付けられています。TerminateCustomerイベントの場合、当該顧客の実行中の受注を検索し、その後、各注文に対しAbortOrderForCustomerイベントを発行する必要があります。イベントの発行は簡単です。Oracle SOA SuiteでMediatorが完璧にうまくやってくれます。本当の問題は、実行中のProcessOrderインスタンスを検索する方法です。ここでは、Oracle SOA SuiteのAPIを利用して、プログラムでインスタンスを問い合わせることができます。APIを使うと、Composite Sensorの値でインスタンスをフィルタリングすることができます。ProcessOrderコンポジットがComposite SensorとしてCustomerIDが公開されている場合、特定のCustomerIDに紐付くインスタンスだけをAPIで取得することができます。このような各インスタンスのために、OrderIDが必要です。APIを使って簡単にインスタンスのセンサー値を取得できるため、OrderIDを含む2個目のComposite Sensorが役に立ちます。
これを念頭に置いて、この課題に対する解決策の案を図6に作ってみました。最初の1枚は、Oracle OpenWorld期間中に開催されたOracle SOA Suite Customer Advisory Boardでナプキンに走り書きしたものです。明らかに思いつきですね。この案は以下の手順を含んでいます。
- 様々な顧客に対応する一つ以上のProcessOrderのBPELプロセス·インスタンスを開始する。このBPELプロセスを含むSOAコンポジット·アプリケーションには、2つのComposite Sensor(CustomerIDとOrderID)がある。
- TerminateCustomerイベントをEvent Delivery Network(EDN)発行する。ペイロードにはCustomerIDを含む。
- (不可能な手順):取引停止の顧客に対し実行しているすべてのProcessOrderインスタンスに、単一のイベントを渡す。
- 手順3のかわりに、Mediatorコンポーネントを使ってTerminateCustomerイベントを消費し、イベントからCustomerIDを抽出する。
図6 |
- (CustomerIDを渡して)Spring Contextコンポーネントを呼びだす…
- このSpring Contextコンポーネントは、Oracle SOA SuiteのJava APIを使ってComposite Sensorを使ってCustomerIDと紐付くProcessOrderのすべての実行中インスタンスを識別し、第2のComposite Sensorの値からこれらのインスタンスのOrderIDを収集する。
- 各OrderIDに対しMediatorを呼び出す
- MediatorはOrderIDをペイロードとして持つAbortOrderForCustomerイベントをEDNに対し発行する。
- 各AbortOrderForCustomerイベントはOrderIDと相関を持つProcessOrder BPELプロセスの一つの実行中インスタンスが消費する。BPELプロセスインスタンスは事前に定義されているロジックに従い終了する。
図7 |
Implementation Steps
この記事の残りの部分では、上述のSOAコンポジットアプリケーションを実装するための手順を詳細に説明しますが、ここには、ProcessOrderビジネスプロセスを実行するためのBPELプロセスが含まれています。また、顧客に関連付けられた各注文のイベントにTerminateCustomerイベントを発行するMediatorとSpringコンポーネントが含まれています。EDNのイベントを定義し、最後に、アプリケーションを実際に動かしてご覧にいれましょう。もちろん、この記事で説明したBPELプロセスは実際の運用環境で使うプロセスよりもずっとシンプルになっていますが、主要な要素とイベント発行メカニズムの価値を損なうわけではありません。
Implementing the ProcessOrder BPEL process
作業は新しいSOAコンポジットアプリケーションを(SOA Extensionインストール済みの)JDeveloper 11gで作成するところから始まります。このアプリケーションをFanoutEventと呼びます。現在のところ、プロジェクトにはSOAコンポジットが含まれています。これ以後記載のソースや成果物はこの記事からダウンロード可能なソースからご利用いただけます。サンプルコード
http://www.oracle.com/technetwork/articles/soa/fanoutevent-sources-1903159.zip
Develop BPEL Process component ProcessOrder
ProcessOrder.wsdlファイルには、ProcessOrderというBPELプロセスが公開するWebサービスが記述されています。このサービスにはProcessOrderというportTypeがあり、一つの非同期オペレーションプロセスがあります。このオペレーションはProcessOrderRequestMessageという、一つのメッセージパートを持つ入力メッセージを取ります。このメッセージパートはProcessOrder.xsdファイルのOrder要素に定義されています。図8 |
サービスは非同期であるため、Callbackポートタイプが定義されています。このポートタイプには一つのオペレーション(processResponse)があり、ProcessOrderResponse要素を基にしたシンプルなシングルパートのメッセージを取ります。ところで、この記事の説明上、このレスポンスメッセージは全く無関係です。
図9 |
図10 |
Add Composite Sensors for CustomerIdentifier and OrderIdentifier
以前、イベントレベルの不一致に対する解決策を議論した際に、2個のComposite Sensorを導入しました。これらのセンサーを使うと管理者はOracle Enterprise Manager Fusion Middleware Controlのコンソールでコンポジットインスタンスを検索し抽出することができます。また、Java APIを使ってプログラムでインスタンスを検索することも可能です。センサーアイコンを使うComposite Editorで、Composite Sensor Editorを使って最初のComposite Sensorを定義します。これをCustomerIdentifierと呼び、BPELが公開するSCA Serviceに接続しています。このセンサー値はリクエストメッセージ中のOrder要素のCustomerIdentifier要素から導出されます。言い換えると、このセンサー値はCustomerIdentifierに一致します。Process Orderインスタンスを作成するインスタンスのCustomerIdentifierに等しい、ということです(図11)。
図11 |
図12 |
Create AbortOrderForCustomer Event
XMLスキーマ定義ファイルのevents.xsdには AbortOrderForCustomerEventタイプがあり、ここでAbortOrderForCustomerというEDNイベントのペイロードを説明しています(図13)。図13 |
このAbortOrderForCustomerEvent定義を基にして、AbortOrderForCustomerイベントをCustomerEvents.edlファイルで定義します。次の図はこのイベント定義を説明しています(図14)。
図14 |
Subscribe the ProcessOrder BPEL process to the AbortOrderForCustomer Event
この時点での状況は以下のようになっています。非同期Webサービスと2個のコンポジットセンサーを公開するコンポジット。
さらに、コンポジット(もしくはコンポジットが包含するBPELコンポーネント)はEDNイベントAbortOrderForCustomerにサブスクライブされています。
図15 |
Setup Correlation
イベントをProcessOrderの実行中インスタンスに取り込むため、イベントの消費に対する相関を設定する必要があります。つまり、(OrderIDを使って)どのようにProcessOrderインスタンスを識別しすべきか、いつ、どのように一意のキーをインスタンスに割り当てるべきか、いつ、どのようにインバウンドメッセージやイベントをこの一意のキーと照合するか、を指定します。まず、OrderIdentifierと呼ばれるプロパティに基づいて、相関セットOrderIdentifierCorrelationSetを作成します。
図16 |
次は、インバウンドメッセージやイベントと相関セット内のプロパティをマッピングするためのプロパティエイリアスを定義します。図17では、プロパティOrderIdentifierをインバウンドメッセージのProcessOrderRequestMessageのOrder要素に含まれるOrderIdentifierという子要素とマッピングしています。このプロパティをAbortOrderForCustomerEventペイロードのOrderIdentifier要素ともマッピングします。これにより、ProcessOrderRequestMessageとAbortOrderForCustomerEventの両方がProcessOrderインスタンスを一意に識別するために必要な情報を含んでおり、それらが相関の関係にある、ということをBPELエンジンに指示しています。
図17 |
Associate Receive and Message Handler with CorrelationSet
まだBPELプロセスから欠けているものが一つあります。我々は、一意のキーがインスタンスに設定されている場合、そしてその一意のキーを使って既存のインスタンスに着信イベントまたはメッセージを供給する場合、BPELエンジンに指示する必要があります。ProcessOrderRequestMessage(および第作成されたインスタンス)を受信した場合、このプロセスで、相関セットを初期化します。ProcessOrderRequestMessageを受信し(インスタンスが最初に作成され)た際に、相関セットを開始します。最初のReceiveアクティビティで、相関セットOrderIdentifierCorrelationSetは[相関]タブに表示され、開始プロパティが[はい]に設定されています。
相関セットを使って着信するAbortOrderForCustomerイベントを既存のProcessOrderインスタンスに取り込みます。これはDoAllTheWorkスコープで定義されたonMessageイベントリスナーで起こります。OnMessageアクティビティもまた同じOrderIdentifierCorrelationSetを使って相関が構成されています。こんどは、インスタンスIDに割り当てたくなく、この値を使ってイベントを実行中のインスタンスにマッピングしたいため、開始プロパティが[いいえ]に設定されています。
図18ではReceiveアクティビティとOnMessageアクティビティの両方で相関を設定する方法を説目いしています。
図18 |
Implement the Event Fan Out machinery
TerminateCustomerイベントをCustomerevents.edlファイルに定義します。Fan-out mediatorがこのイベントをインターセプトする必要があります。このMediatorはTerminateCustomerイベントをEvent Delivery Networkを使ってサブスクライブします。イベントが到着すると、Mediatorがアクティブになり、Springコンポーネントを呼び出します。SpringコンポーネントはTerminateCustomerイベントのペイロードに含まれる顧客IDを使って、正しい値を持つコンポジットセンサーCustomerIdentifierを出力する、すべての実行中のProcessOrderインスタンスを(SOA SuiteやJava APIを使って)検索します。Springコンポーネントは各インスタンスのコンポジットセンサーOrderIdentifierの値を抽出し、各インスタンスについてもう一つのMediatorを呼びだし、その特定のOrderIDの値について、AbortOrderForCustomerイベントをEDNにパブリッシュします。
Definition of the TerminateCustomer event
XMLスキーマ定義ファイルのEvents.xsdには、TerminateCustomerイベントのペイロードを定義するために使用される、TerminateCustomerタイプが含まれています。このペイロードは、少なくともcustomerIdentifierを含める必要があります。子要素motivationはおまけとして追加されています。図20 |
図21 |
「イベントのサブスクライブ」テンプレートを基に、ConsumeTerminateCustomerというMediatorコンポーネントを作成します。イベント定義ファイルCustomerEvents.edlからこのコンポーネントがサブスクライブするイベントとして、TerminateCustomerイベントを選択します。
図22 |
図23 |
Create the event publishing Mediator for AbortOrderForCustomer
次に追加するコンポーネントは、AbortOrderForCustomerイベントをパブリッシュするMediatorコンポーネントです。このMediatorのインターフェースを定義する簡単なWSDLドキュメントを設定しました。AbortOrderForCustomerイベントのペイロード定義を基にした入力要素を持つ、一方向のオペレーション(publishAbortOrderEvent)を含んでいます。図24 |
図25 |
Create and wire the Spring Component
SpringコンポーネントTerminateCustomerToAbortOrderEventTranslatorをコンポジット中に作成します。MediatorコンポーネントPublishAbortOrderEventをSpringコンポーネントとつなぎます。このMediatorはSpringコンポーネントが要求するイベントを発行します。
図26 |
これはSpring bean定義ファイルで作成された任意のbeanに後で注入できるSpringコンポーネントでsca.referenceを作成します。
図27 |
図28 |
図29 |
図30 |
図31 |
Implementing the Spring Bean
JavaクラスCustomerToOrderEventProcessorImplはCustomerToOrderEventProcessorインタフェースの実装で、processTerminateCustomerEventとsetPublishAbortOrderEventInterfaceの両メソッドを実装しています。このクラスに基づくSpring Beanを次のように設定できます。
図32 |
クラスそのものは非常に簡単です。AbortOrderForCustomerEventオブジェクト、いわゆる"ペイロード"をメディエータに渡しイベントを発行する準備をします。このクラスは、customerIdentifierに対応する現在実行中のProcessOrderインスタンスからすべてorderIdentifierの一覧を取得します。その後、これらのorderIdentifierを反復処理し、それぞれに対応したMediatorを呼び出します。
図33 |
図34 |
図35 |
Reviewing the work
これまで説明したすべての最終結果を図36に示します。通常のビジネスフローはBPELプロセスProcessOrderをアクティベートするProcessOrder_epサービスへの呼び出しです。このインスタンスは、その存続期間中いつでもAbortOrderForCustomerイベントを消費するような状態になっています。そのイベントは、Order IDに基づいてインスタンスに関連付けることができます。.例外的なフローは、TerminateCustomerイベントを消費するMediatorから始まります。 Mediatorは、イベントのペイロードからCustomer IDを取得し、そのCustomer IDを渡してSpringコンポーネントTerminateCustomerToAbortOrderEventTranslatorを呼び出します。このコンポーネントは、Oracle SOA Suite Java APIを使い、Composite Sensorで設定されたCustomer IDを持つすべてのコンポジットインスタンスを見つけようとします。すべてのこれらのインスタンスのOrder IDは対応するセンサから取得され、各インスタンスについて、Order IDを渡してメディエータPublishAbortOrderEventを呼びだします。このMediatorはAbortOrderForCustomerイベントを発行します。
このイベントは、Order IDに基づいて、イベントと相関を持つBPELプロセスProcessOrderのインスタンスが消費します。その後、インスタンスが終了します。
図36はCompositeでイベント転送を可視化しています。ただし、イベントを発行するメディエータとイベントを消費するBPELプロセスの間には直接のリンクが存在しないことにご注意下さい。:この相互作用は完全にコンシューマからパブリッシャを分離するイベント配信ネットワークを介して実施されています。
図36 |
And... action!
SOAコンポジットアプリケーションは完全に自己完結しています。アプリケーションをOracle SOA Suiteランタイム環境に通常の方法でデプロイできます。図37 |
Run ProcessOrder instances
デプロイが終了したら、ProcessOrderプロセスのインスタンスを起動します。FanoutEventコンポジットをOracle Enterprise Manager Fusion Middleware Controlで選択し、[テスト]ボタンを押します(図38)。図38 |
図39 |
図40 |
図41 |
Publish the TerminateCustomer event
シナリオ:顧客XYZは、もはや信頼できるビジネスパートナーではなく、すべての関係をすぐに切断するべきです。 TerminateCustomerイベントをこの顧客のために発行するべきです。このイベント発行の間接的な結果として、現在、顧客XYZのために実行しているProcessOrderのすべての5インスタンスを終了させたいと考えています。テスト目的で、Enterprise Manager FMW ControlからEDNイベントを発行できます。soa-infraノードのコンテキストメニューから、[ビジネスイベント]を選択します。
図42 |
図43 |
このイベントを発行することによって生じる効果を見る前に、CustomerIdentifier Composite Sensorからの値をXYZでフィルタリングした実行中のインスタンスの概要を見てみましょう(図44)。これにより、何が起こるか予想がつくと思います。記載されているこの5個のインスタンスは、終了しているはずです。
図44 |
Inspecting the event consequences
EDNにはTerminateCustomerイベントの一つのサブスクライバがあります。それがFanoutEventコンポジットのメディエータConsumeTerminateCustomerです。このMediatorは、顧客XYZのイベントを消費し、SpringコンポーネントのTerminateCustomerToAbortOrderEventTransformerを起動します。このコンポーネントは、顧客XYZに対応する、実行中のすべてのProcessOrderインスタンスを見つけ(図44から少なくとも5個あることがわかります)、特定のOrder IDのために、EDNに対しAbortOrderForCustomerEventを発行するPublishAbortOrderEventメディエータを呼び出します。メッセージフロートレースの検査時に、いったい何が起こったのかが明確になります。5個の呼び出しはメディエータPublishAbortOrderEventに対してなされました。この結果、5つ実行中の注文に対応するAbortOrderForCustomerイベントになりました。メッセージフロートレースから、これらのイベントのいずれかが、ProcessOrderインスタンスをどのように終了させているかがわかります(図45)。
図45 |
図46 |
当然ながら、他の顧客のためのすべてのProcessOrderインスタンスは、この時点では実行されています。顧客XYZを扱うものだけが終了しました。
Conclusion
ビジネスイベントを使用すると、組織は、新しいいレベルの疎結合を導入することができます。潜在的に興味深いものと認識されている状況にある任意のパーティー(システム、サービス、アプリケーション、プロセス)は、汎用的なイベントハンドラーに対してイベントを発行することで世間に伝える必要があります。これらの認識されているビジネスイベントの一つ以上に関心を持つ当事者は、イベント発生時に、通知するイベントハンドラを購読することができます。イベントのコンシューマやパブリッシャがお互いについて何も知らないにもかかわらず、曲がりなりにもまだ協力しています。Oracle SOA SuiteのEvent Delivery Networkはイベントハンドラの一例です。その他もご利用いただけますし、JMSやAQを含めて、比較的単純な手段を使って作成することができます。
ビジネスイベントは、例えば、BPMやBPELといった実行中のプロセスに影響を与える必要がある場合、こうしたイベントを特定のコンポジットインスタンスと相関を持たせる必要があります。しかし、ビジネスイベントが意図された効果とは異なるレベルにあるとき、例えば顧客のすべての注文を停止するような場合、私たちは課題に直面します。通常は、実行中の一つのプロセスインスタンスと相関を構成します。
この記事では、イベントをより高いレベルで捕捉し、期待するレベルの実行中のインスタンスにイベントを発行できることをご説明しました。Composite Sensor、Springコンポーネント、相関を持つインスタンスを発見するためのOracle SOA SuiteのJava API、そして、2番目のタイプの適切なレベルに調整したイベントを使って実施しています。
Resources
- How to correlate one event into multiple instances of the same composite (BPEL or BPM)
http://technology.amis.nl/2011/10/07/soa-suite-11g-event-delivery-network-how-to-correlate-one-event-into-multiple-instances-of-the-same-composite-bpel-or-bpm/
この記事で議論した課題と解決策を説明したオリジナルのブログエントリです。 - Correlate one event into multiple instances of the same composite in SOA 11g
http://sridhar-oraclefusion.blogspot.nl/2011/11/correlate-one-event-into-multiple.html
実装を提供してくれたShrdiharによるエントリです。 - Correlate an Event into Multiple BPEL Prrocess Instances
http://www.slideshare.net/lucasjellema/soa-suite11g-fanout-events-to-correlate-into-multiple-instances
この記事を基にしたSlideShareのプレゼンテーションです - Integrating the Spring Framework in SOA Composite Applications
http://docs.oracle.com/cd/E15586_01/integration.1111/e10224/sca_spring.htm
Oracle SOA SuiteのSpring Componentに関するドキュメントです。 - Using the new 11g SOA Suite API - changes to 10.1.3x
https://blogs.oracle.com/soabpm/entry/using_the_new_11g_soa_suite_ap
Oracle SOA Suite APIの概要を説明しているエントリです。 - Keeping your process clean: Hiding technology complexity behind a service
http://technology.amis.nl/2011/06/21/keeping-your-process-clean-hiding-technology-complexity-behind-a-service/
Oracle SOA Suite APIを使ってインスタンスを発見する方法のサンプルです。
TERIMA KASIH ATAS KUNJUNGAN SAUDARA
Judul: [SOA] Fanning Out Events on the Oracle SOA Suite 11g Event Delivery Network
Ditulis oleh Unknown
Rating Blog 5 dari 5
Semoga artikel ini bermanfaat bagi saudara. Jika ingin mengutip, baik itu sebagian atau keseluruhan dari isi artikel ini harap menyertakan link dofollow ke https://apk-zipalign.blogspot.com/2013/06/soa-fanning-out-events-on-oracle-soa.html. Terima kasih sudah singgah membaca artikel ini.Ditulis oleh Unknown
Rating Blog 5 dari 5
0 komentar:
Posting Komentar