WCF サービス モデルでストアド プロシージャを使用して Oracle E-Business Suite をポーリングする
ストアド プロシージャを使用して Oracle データベースを定期的にポーリングすることで、定期的なデータ変更メッセージを受信するように Oracle E-Business アダプターを構成できます。 Oracle データベースをポーリングするためにアダプターが定期的に実行するポーリング ステートメントとしてストアド プロシージャを指定できます。
ポーリングを有効にするには、このトピックで説明するように特定のバインド プロパティを指定する必要があります。 アダプターがポーリングをサポートする方法の詳細については、「 ポーリングを使用した受信呼び出しのサポート」を参照してください。
Oracle E-Business Adapter のバインド プロパティを使用したポーリング操作の構成
次の表は、データ変更メッセージを受信するようにアダプターを構成するために使用する Oracle E-Business アダプター バインド プロパティをまとめたものです。 ポーリング アプリケーションの実行中に、これらのバインド プロパティを指定する必要があります。
Binding プロパティ | 説明 |
---|---|
InboundOperationType | ポーリングまたは通知の受信操作を実行するかどうかを指定します。 既定値は ポーリングです。 |
PolledDataAvailableStatement | ポーリングに使用できるデータがあるかどうかを判断するためにアダプターが実行する SQL ステートメントを指定します。 レコードが使用可能な場合にのみ、 PollingInput バインド プロパティに指定したストアド プロシージャが実行されます。 |
PollingInterval | Oracle E-Business アダプターが PolledDataAvailableStatement バインディング プロパティに指定されたステートメントを実行する間隔を秒単位で指定します。 既定値は 30 秒です。 ポーリング間隔は、連続するポーリング間の時間間隔を決定します。 ステートメントが指定された期間内に実行された場合、アダプターはその間隔の残りの時間スリープ状態になります。 |
PollingInput | ポーリング ステートメントを指定します。 ストアド プロシージャを使用してポーリングするには、このバインド プロパティの要求メッセージ全体を指定する必要があります。 要求メッセージは、ストアド プロシージャを送信操作として呼び出すためにアダプターに送信するメッセージと同じである必要があります。 既定値は null です。 ポーリングを有効にするには、 PollingInput バインド プロパティの値を指定する必要があります。 ポーリング ステートメントは、ポーリングに使用できるデータがある場合にのみ実行されます。これは、 PolledDataAvailableStatement バインディング プロパティによって決定されます。 |
PollingAction | ポーリング操作のアクションを指定します。 操作用に生成されたサービス インターフェイスからポーリング アクションを決定するには、アダプター サービス参照の追加 Visual Studio プラグインを使用します。 |
PostPollStatement | PollingInput バインディング プロパティで指定されたステートメントが実行された後に実行されるステートメント ブロックを指定します。 |
PollWhileDataFound | ポーリング対象のテーブルでデータが使用可能な場合に、Oracle E-Business アダプターがポーリング間隔を無視し、ポーリング ステートメントを継続的に実行するかどうかを指定します。 テーブルに使用可能なデータがない場合、アダプターは、指定されたポーリング間隔でポーリング ステートメントを実行するように戻ります。 既定値は false です。 |
これらのプロパティの詳細については、「 BizTalk Adapter for Oracle E-Business Suite のバインド プロパティについて」を参照してください。 Oracle E-Business アダプターを使用してポーリングする方法の詳細については、次のセクションを参照してください。
このトピックでポーリングを示す方法
このトピックでは、Oracle E-Business アダプターがストアド プロシージャを使用したデータ変更メッセージの受信をサポートする方法を示すために、GET_ACTIVITYS ストアド プロシージャを使用して Oracle データベースの ACCOUNTACTIVITY テーブルをポーリングします。 このストアド プロシージャは、ACCOUNT_PKG パッケージで使用できます。 サンプルに付属の SQL スクリプトを実行して、これらのオブジェクトをデータベースに作成できます。
Note
このトピックの例では、サンプルで提供されるスクリプトを実行して作成されたベース データベース テーブルである ACCOUNTACTIVITY テーブルをポーリングします。 インターフェイス テーブルを含む他のテーブルをポーリングするには、このトピックの説明と同様の手順を実行する必要があります。
ポーリング操作を示すために、次の操作を行います。
PolledDataAvailableStatement バインド プロパティの SELECT ステートメントを指定して、ポーリングされるテーブル (ACCOUNTACTIVITY) にデータが含まれる場所を決定します。 この例では、このバインド プロパティを次のように設定できます。
SELECT COUNT (*) FROM ACCOUNTACTIVITY
これにより、ACCOUNTACTIVITY テーブルに一部のレコードがある場合にのみ、アダプターでポーリング ステートメントが実行されるようになります。
PollingInput バインド プロパティの一部として要求メッセージを指定して、ストアド プロシージャGET_ACTIVITYS実行します。 このストアド プロシージャは ACCOUNTACTIVITY テーブル内のすべての行を取得し、アダプターから応答メッセージを受け取ります。
PostPollStatement バインド プロパティの一部として PL/SQL ブロックを実行します。 このステートメントは、ACCOUNTACTIVITY テーブルからデータベース内の別のテーブルにすべてのデータを移動します。 この処理が行われると、次に PollingInput が実行されると、データはフェッチされないため、GET_ACTIVITYSストアド プロシージャは空の応答メッセージを返します。
ACCOUNTACTIVITY テーブルに追加されたデータが増えるまで、引き続き空の応答メッセージが表示されるため、ACCOUNTACTIVITY テーブルに新しいレコードを入力し直す必要があります。 これを行うには、サンプルに付属のmore_activity_data.sql スクリプトを実行します。 このスクリプトを実行すると、次のポーリング操作によって、テーブルに挿入された新しいレコードがフェッチされます。
WCF サービス モデルでのポーリングの構成
WCF サービス モデルを使用して Oracle E-Business アダプターでストアド プロシージャを使用してポーリングするには、次の操作を行う必要があります。
ポーリングに使用するストアド プロシージャの WCF サービス コントラクト (インターフェイス) を生成します。 この例では、GET_ACTIVITYS ストアド プロシージャの WCF サービス コントラクトを受信 操作として生成する必要があります。 これを行うには、アダプター サービス参照の追加プラグインを使用できます。
このインターフェイスから WCF サービスを実装します。
サービス ホスト (System.ServiceModel.ServiceHost) を使用して、この WCF サービスをホストします。
このトピックで使用する例について
このトピックの例では、GET_ACTIVITYS ストアド プロシージャを使用して ACCOUNTACTIVITY データベース テーブルをポーリングします。 テーブルとストアド プロシージャを生成するスクリプトがサンプルと共に提供されます。 サンプルの詳細については、「 Oracle EBS アダプターのサンプル」を参照してください。 このトピックに基づく サンプル StoredProcPolling_ServiceModelは、Oracle E-Business アダプターのサンプルでも提供されています。
WCF サービス コントラクトとクラス
アダプター サービス参照の追加プラグインを使用して、 GET_ACTIVITYS受信操作 の WCF サービス コントラクト (インターフェイス) とサポート クラスを作成できます。 WCF サービス コントラクトの生成の詳細については、「 Oracle E-Business Suite ソリューション成果物の WCF クライアントまたは WCF サービス コントラクトを生成する」を参照してください。
WCF サービス コントラクト (インターフェイス)
次のコードは、 GET_ACTIVITYS 受信操作用に生成された WCF サービス コントラクト (インターフェイス) を示しています。
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/", ConfigurationName="PollingPackageApis_APPS_ACCOUNT_PKG")]
public interface PollingPackageApis_APPS_ACCOUNT_PKG {
// CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/OracleEBS/2008/05/PollingPackageApis/APPS/ACCOUNT_PKG) of message GET_ACTIVITYS
// does not match the default value (https://schemas.microsoft.com/OracleEBS/)
[System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="PollingPackageApis/APPS/ACCOUNT_PKG/GET_ACTIVITYS")]
void GET_ACTIVITYS(GET_ACTIVITYS request);
}
メッセージ コントラクト
GET_ACTIVITYS受信操作のメッセージ コントラクトを次に示します。
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="GET_ACTIVITYS", WrapperNamespace="http://schemas.microsoft.com/OracleEBS/2008/05/PollingPackageApis/APPS/ACCOUNT_PK" +
"G", IsWrapped=true)]
public partial class GET_ACTIVITYS {
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/2008/05/PollingPackageApis/APPS/ACCOUNT_PK" +
"G", Order=0)]
public schemas.microsoft.com.OracleEBS._2008._05.RecordTypes.APPS.ACCOUNT_PKG.GET_ACTIVITYS.OUTRECSRecord[] OUTRECS;
public GET_ACTIVITYS() {
}
public GET_ACTIVITYS(schemas.microsoft.com.OracleEBS._2008._05.RecordTypes.APPS.ACCOUNT_PKG.GET_ACTIVITYS.OUTRECSRecord[] OUTRECS) {
this.OUTRECS = OUTRECS;
}
}
WCF サービス クラス
アダプター サービス参照の追加プラグインは、サービス コントラクト (インターフェイス) から実装された WCF サービス クラスのスタブを持つファイルも生成します。 ファイルの名前は OracleEBSBindingService.cs です。 ロジックを挿入して 、GET_ACTIVITYS 操作をこのクラスに直接処理できます。 次のコードは、アダプター サービス参照プラグインの追加によって生成された WCF サービス クラスを示しています。
namespace OracleEBSBindingNamespace {
public class OracleEBSBindingService : PollingPackageApis_APPS_ACCOUNT_PKG {
// CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/OracleEBS/2008/05/PollingPackageApis/APPS/ACCOUNT_PKG) of message GET_ACTIVITYS
// does not match the default value (https://schemas.microsoft.com/OracleEBS/)
public virtual void GET_ACTIVITYS(GET_ACTIVITYS request) {
throw new System.NotImplementedException("The method or operation is not implemented.");
}
}
}
ストアド プロシージャを使用したポーリング用の受信メッセージの受信
このセクションでは、Oracle E-Business アダプターを使用して受信ポーリング メッセージを受信する .NET アプリケーションを作成する方法について説明します。
ストアド プロシージャを使用してポーリング メッセージを受信するには
アダプター サービス参照の追加プラグインを使用して、 GET_ACTIVITYS 受信操作の WCF サービス コントラクト (インターフェイス) とヘルパー クラスを生成します。 詳細については、「 Oracle E-Business Suite ソリューション成果物の WCF クライアントまたは WCF サービス コントラクトを生成する」を参照してください。 必要に応じて、サービス コントラクトとヘルパー クラスの生成中にバインド プロパティを指定できます。 これにより、生成された構成ファイルに正しく設定されます。
手順 1 で生成されたインターフェイス クラスとヘルパー クラスから WCF サービスを実装します。 このクラスの GET_ACTIVITYS メソッドは、 GET_ACTIVITYS操作から 受信したデータの処理でエラーが発生した場合に、ポーリング トランザクションを中止する例外をスローできます。それ以外の場合、メソッドは何も返しません。 WCF サービス クラスを次のように属性化する必要があります。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
GET_ACTIVITYS メソッド内では、アプリケーション ロジックを直接実装できます。 このクラスは OracleEBSBindingService.cs にあります。 この例のこのコードは、 OracleEBSBindingService クラスを サブクラスします。 このコードでは、ポーリング メッセージが受信され、コンソールに書き込まれます。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class PollingService : OracleEBSBindingNamespace.OracleEBSBindingService { public override void GET_ACTIVITYS(GET_ACTIVITYS request) { Console.WriteLine("\nNew Polling Records Received"); Console.WriteLine("*************************************************"); Console.WriteLine("Tx Id\tAccount\tAmount\tProcessed"); for (int i = 0; i < request.OUTRECS.Length; i++) { Console.WriteLine("{0}\t{1}\t{2}\t{3}", request.OUTRECS[i].TID, request.OUTRECS[i].ACCOUNT, request.OUTRECS[i].AMOUNT, request.OUTRECS[i].PROCESSED); } Console.WriteLine("*************************************************"); Console.WriteLine("\nHit <RETURN> to stop polling"); } }
URI の一部として資格情報を渡さないようにするには、次のクラスを実装する必要があります。 アプリケーションの後半では、このクラスをインスタンス化して資格情報を渡します。
class PollingCredentials : ClientCredentials, IServiceBehavior { public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { bindingParameters.Add(this); } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } protected override ClientCredentials CloneCore() { ClientCredentials clone = new PollingCredentials(); clone.UserName.UserName = this.UserName.UserName; clone.UserName.Password = this.UserName.Password; return clone; } }
OracleEBSBinding を作成し、バインド プロパティを指定してポーリング操作を構成します。 これは、コードで明示的に行うか、構成で宣言によって行うことができます。 少なくとも、 InboundOperationType、 PolledDataAvailableStatement、 PollingInput、および PollingAction バインディング プロパティを指定する必要があります。
OracleEBSBinding binding = new OracleEBSBinding(); binding.InboundOperationType = InboundOperation.Polling; binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM ACCOUNTACTIVITY"; binding.PollingInput = "<GET_ACTIVITYS xmlns='http://schemas.microsoft.com/OracleEBS/2008/05/PackageApis/APPS/ACCOUNT_PKG'><INRECS>OPEN ? FOR SELECT * FROM ACCOUNTACTIVITY</INRECS></GET_ACTIVITYS>"; binding.PollingAction = "PollingPackageApis/APPS/ACCOUNT_PKG/GET_ACTIVITYS"; binding.PostPollStatement = "BEGIN ACCOUNT_PKG.PROCESS_ACTIVITY(); END;";
Note
PollingInput バインド プロパティの値には、GET_ACTIVITYS ストアド プロシージャを送信操作として呼び出すための要求メッセージが含まれていることに注意してください。
重要
この例では、データベース テーブルをポーリングするため、アプリケーション コンテキストを設定する必要はありません。 ただし、インターフェイス テーブルをポーリングする場合は、 OracleUserName、 OraclePassword、 OracleEBSResponsibilityName バインディング プロパティを指定して、アプリケーション コンテキストを設定する必要があります。 アプリケーション コンテキストの詳細については、「アプリケーション コンテキストの設定」を参照してください。
手順 3 で作成 した PollingCredentials クラスをインスタンス化して、Oracle E-Business Suite の資格情報を指定します。
PollingCredentials credentials = new PollingCredentials(); credentials.UserName.UserName = "<Enter user name here>"; credentials.UserName.Password = "<Enter password here>";
手順 2 で作成した WCF サービスのインスタンスを作成します。
// create service instance PollingService service = new PollingService();
WCF サービスと基本接続 URI を使用して System.ServiceModel.ServiceHost のインスタンスを作成します。 指定した場合、基本接続 URI に受信 ID を含めることはできません。 資格情報もここで渡す必要があります。
// Enable service host Uri[] baseUri = new Uri[] { new Uri("oracleebs://ebs_instance_name") }; ServiceHost serviceHost = new ServiceHost(service, baseUri); serviceHost.Description.Behaviors.Add(credentials);
サービス エンドポイントをサービス ホストに追加します。 これを行うには、次の手順を実行します。
手順 4 で作成したバインディングを使用します。
資格情報と必要に応じて受信 ID を含む接続 URI を指定します。
コントラクトを "PollingPackageApis_APPS_ACCOUNT_PKG" として指定して、MS_SAMPLE_EMPLOYEE インターフェイス テーブルをポーリングします。
// Add service endpoint: be sure to specify PollingPackageApis_APPS_ACCOUNT_PKG as the contract Uri ConnectionUri = new Uri("oracleebs://ebs_instance_name"); serviceHost.AddServiceEndpoint("PollingPackageApis_APPS_ACCOUNT_PKG", binding, ConnectionUri);
ポーリング データを受信するには、サービス ホストを開きます。 アダプターは、クエリが結果セットを返すたびにデータを返します。
// Open the service host to begin polling serviceHost.Open();
ポーリングを終了するには、サービス ホストを閉じます。
重要
アダプターは、サービス ホストが閉じられるまでポーリングを続行します。
serviceHost.Close();
例
次の例は、GET_ACTIVITYS ストアド プロシージャを使用して ACCOUNTACTIVITY データベース テーブルをポーリングするポーリング アプリケーションを示しています。 PollingInput バインド プロパティには、ACCOUNTACTIVITY テーブルからすべてのデータを読み取るGET_ACTIVITYSストアド プロシージャを呼び出す要求メッセージが含まれており、ポーリング後ステートメントは ACCOUNTACTIVITY から ACTIVITYHISTORY テーブルにすべてのデータを移動します。
最初のポーリング メッセージは、ACCOUNTACTIVITY テーブルのすべてのレコードを示します。 後続のポーリング メッセージにはレコードは含まれません。これは、post poll ステートメントによってレコードが削除されるためです。 ACCOUNTACTIVITY テーブルに追加されたデータが増えるまで、ポーリング メッセージは表示されないため、ACCOUNTACTIVITY テーブルに新しいレコードを入力し直す必要があります。 これを行うには、サンプルに付属のmore_activity_data.sql スクリプトを実行します。
このスクリプトを実行すると、次のポーリング操作によって、テーブルに挿入された新しいレコードがフェッチされます。 を押 <RETURN>
してサービス ホストを閉じるまで、アダプターはポーリングを続行します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Adapters.OracleEBS;
using Microsoft.ServiceModel.Channels;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.Collections.ObjectModel;
namespace StoredProcPolling_ServiceModel
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class PollingService : OracleEBSBindingNamespace.OracleEBSBindingService
{
public override void GET_ACTIVITYS(GET_ACTIVITYS request)
{
Console.WriteLine("\nNew Polling Records Received");
Console.WriteLine("*************************************************");
Console.WriteLine("Tx Id\tAccount\tAmount\tProcessed");
for (int i = 0; i < request.OUTRECS.Length; i++)
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}",
request.OUTRECS[i].TID,
request.OUTRECS[i].ACCOUNT,
request.OUTRECS[i].AMOUNT,
request.OUTRECS[i].PROCESSED);
}
Console.WriteLine("*************************************************");
Console.WriteLine("\nHit <RETURN> to stop polling");
}
}
class PollingCredentials : ClientCredentials, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
bindingParameters.Add(this);
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{ }
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{ }
protected override ClientCredentials CloneCore()
{
ClientCredentials clone = new PollingCredentials();
clone.UserName.UserName = this.UserName.UserName;
clone.UserName.Password = this.UserName.Password;
return clone;
}
}
class Program
{
static void Main(string[] args)
{
ServiceHost serviceHost = null;
try
{
Console.WriteLine("Sample started...");
Console.WriteLine("Press any key to start polling...");
Console.ReadLine();
OracleEBSBinding binding = new OracleEBSBinding();
binding.InboundOperationType = InboundOperation.Polling;
binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM ACCOUNTACTIVITY";
binding.PollingInput = "<GET_ACTIVITYS xmlns='http://schemas.microsoft.com/OracleEBS/2008/05/PackageApis/APPS/ACCOUNT_PKG'><INRECS>OPEN ? FOR SELECT * FROM ACCOUNTACTIVITY</INRECS></GET_ACTIVITYS>";
binding.PollingAction = "PollingPackageApis/APPS/ACCOUNT_PKG/GET_ACTIVITYS";
binding.PostPollStatement = "BEGIN ACCOUNT_PKG.PROCESS_ACTIVITY(); END;";
// This URI is used to specify the address for the ServiceEndpoint
// It must contain the InboundId that was used to generate
// the WCF service callback interface
Uri ConnectionUri = new Uri("oracleebs://ebs_instance_name");
// This URI is used to initialize the ServiceHost. It cannot contain
// an InboundID; otherwise,an exception is thrown when
// the ServiceHost is initialized.
Uri[] baseUri = new Uri[] { new Uri("oracleebs://ebs_instance_name") };
PollingCredentials credentials = new PollingCredentials();
credentials.UserName.UserName = "<Enter user name here>";
credentials.UserName.Password = "<Enter password here>";
Console.WriteLine("Opening service host...");
PollingService service = new PollingService();
serviceHost = new ServiceHost(service, baseUri);
serviceHost.Description.Behaviors.Add(credentials);
serviceHost.AddServiceEndpoint("PollingPackageApis_APPS_ACCOUNT_PKG", binding, ConnectionUri);
serviceHost.Open();
Console.WriteLine("Service host opened...");
Console.WriteLine("Polling started...");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Exception :" + e.Message);
Console.ReadLine();
/* If there is an error it will be specified in the inner exception */
if (e.InnerException != null)
{
Console.WriteLine("InnerException: " + e.InnerException.Message);
Console.ReadLine();
}
}
finally
{
// IMPORTANT: you must close the ServiceHost to stop polling
if (serviceHost.State == CommunicationState.Opened)
serviceHost.Close();
else
serviceHost.Abort();
}
}
}
}