**この記事は[こちらの投稿](https://jp.community.intersystems.com/node/483171)の続きの内容です。** [前回の記事](http://jp.community.intersystems.com/node/483171)では、システム統合に必要なコンポーネントの中から、プロダクション内の処理の調整役となるビジネス・プロセスの作成について解説しました。 今回の記事では、プロダクションの情報入力窓口である、ビジネス・サービスの作成について解説します。 * [プロダクション](https://jp.community.intersystems.com/node/483041) * [メッセージ](https://jp.community.intersystems.com/node/483131) * **コンポーネント** * **ビジネス・サービス** * [ビジネス・プロセス(前回の記事)](http://jp.community.intersystems.com/node/483171) * [ビジネス・オペレーション](http://jp.community.intersystems.com/node/483136)   いよいよ「Interoperability(相互運用性)を使ってみよう!」の最後のコンポーネントです。 ビジネス・サービスは、IRIS 外部からの送信される情報の入力窓口で、外部 I/F に対してアダプタを使用する/しないを選択できます。 サンプルでは、3 種類のビジネス・サービスを用意しています(括弧内のリンクはサンプルコードへのリンク)。 1. [ファイルインバウンドアダプタを利用したファイル用ビジネス・サービス](#fileinboundadapter)([Start.FileBS](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/FileBS.cls))  2. [SOAP インバウンドアダプタを利用する Web サービス用ビジネス・サービス](#soapinboundadapter)([Start.WS.WebServiceBS](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/WS/WebServiceBS.cls)) 3. [アダプタを使用せず、ストアドプロシージャや REST で呼び出されるビジネス・サービス](#nonadapter)([Start.NonAdapterBS](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/NonAdapterBS.cls)) 情報入力に使用する接続方法が異なるだけ、ビジネス・サービス数が増えますが、ビジネス・サービス内で行う処理は

外部から入力された情報を利用して、
送信する要求メッセージを作成し、
ビジネス・コンポーネント を呼び出すだけ

とてもシンプルです。 それでは、ファイルインバウンドアダプタを使用するコンポーネントから作成方法概要を説明します。 ビジネス・サービスはスクリプトを記述するので、VSCode かスタジオで作成します(VSCodeの使い方については[こちらの記事](https://jp.community.intersystems.com/node/482976)もご参照ください。)。   ### 1、ファイルインバウンドアダプタを利用したファイル用ビジネス・サービス([Start.FileBS](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/FileBS.cls)) VSCode で作成する場合は、Ens.BusinessService を継承するクラスを作成します。アダプタについては、使用する場合は、以下のように **ADAPTER **パラメータにアダプタクラス名をしています(例はファイルインバウンドアダプタのクラスを指定しています)。 アダプタを使用しない場合は、設定は不要です。
Class Start.FileBS Extends Ens.BusinessService
{
Parameter ADAPTER = "EnsLib.File.InboundAdapter";
  ファイルインバウンドアダプタでは、監視対象ディレクトリの指定をプロダクションのビジネス・サービス用設定の「ファイル・パス」で指定できます。 ![](/sites/default/files/inline/images/images/image(1114).png) 「ファイル・パス」に置かれたファイルが「ファイル・スペック」に指定した情報と合致する場合、ファイルをストリームオブジェクトとしてオープンし、ビジネス・サービスの **ProcessInput()** を呼び出すときの第1引数に指定します。 **ProcessInput()** が起動すると自動的に **OnProcessInput()** が呼び出されます。この時、**OnProcessInput()** には、**ProcessInput() **で渡された引数がそのまま渡ります。 ![](/sites/default/files/inline/images/images/image(1111).png)   **OnProcessInput()** では、第1引数に渡されるファイルストリームオブジェクトから情報を取得し、次のコンポーネントへ渡すメッセージを作成し、次のコンポーネントを呼び出す処理を記述したら基本ロジックは終了です。 * * *

【メモ】
スタジオの場合は、新規作成メニューのビジネス・サービスウィザードを起動し、アダプタを選択して完了ボタンを押下します。

* * *   **OnProcessInput()** のメソッド定義は以下の通りです。
Method OnProcessInput(pInput As %Stream.ObjectOutput pOutput As %RegisteredObjectAs %Status
  **pInput** には、テキストファイルの場合 %Steam.FileCharacter クラス、バイナリファイルの場合 %Stream.FileBinary クラスのインスタンスが渡されます。 サンプルでは、テキスト形式のファイルが入力される予定で、1依頼1行として、複数行の依頼も受け付けるように記述しています。 End Of File を検知すると1を設定する **AtEnd プロパティ**を利用してループ処理を行います。 ループ内では、ファイルの中身を1行ずつ情報を取得できる** ReadLine() メソッド**を使い、行を読み取ります(ファイルアダプタ詳細は、[ドキュメント](https://docs.intersystems.com/irislatestj/csp/docbook/DocBook.UI.Page.cls?KEY=EFIL)をご参照ください)。 1行ずつ情報を取得しながらメッセージを作成し、他コンポーネントを呼び出す ..SendRequestAsync() メソッドを実行します。 メソッド実行時、第1引数に呼び出したいコンポーネント名を文字列で指定し、第2引数には作成した要求メッセージを指定します。 なお、..SendRequestAsync()は非同期呼び出し のため、応答を待ちません。

メモ:同期呼び出し用に SendRequestSync() もあります。

サンプルコードは以下の通りです。   ![](/sites/default/files/inline/images/images/image(1112).png)   ご参考:上記例文中の $piece()関数の使い方の解説

$piece(“文字列”,”区切りマーク”,”ポジション番号”)

区切りマーク付き文字列の設定/取得が行える関数で、サンプルでは、カンマ区切りデータの1番目と2番目の値を取得するため、以下の構文で記述されています。

set request.Product=$piece(record,",",1)

set request.Area=$piece(record,",",2)

  では、上記説明に登場した [Start.FileBS](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/FileBS.cls) の動作を確認します。 サンプルプロダクションでは「ファイル・パス」に **/irisdev/src**  「ファイル・スペック」に **check.txt** を指定しています。同じディレクトリをご用意いただくか、別ディレクトリに変更いただき、check.txtファイルに以下の形式(購入商品名,都市名)でサンプルデータを登録してください。 ※ サンプルのコンテナを利用されている場合は、git clone で作成したディレクトリ以下の src ディレクトリ以下にある [Test用-check.txt] をリネームしてご利用ください。 ![](/sites/default/files/inline/images/images/image(1113).png) ![](/sites/default/files/inline/images/images/image(1115).png)     ### 2、SOAP インバウンドアダプタを利用する Web サービス用ビジネス・サービス([Start.WS.WebServiceBS](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/WS/WebServiceBS.cls)) つづいて、Web サービス用ビジネス・サービスの作成概要をご説明します。 Web サービス用ビジネス・サービスクラスは、Web サービス提供側= Web サービスサーバとして動作します。 サンプルでは、Web サービスクライアントから情報を送信してもらうため、今回のサンプルプロダクションに合わせて Web サービスメソッドに2つの引数を用意しています。Web メソッドでは、引数に入力された情報を利用してメッセージクラスを作成し、他コンポーネントを呼び出しています。 ![](/sites/default/files/inline/images/images/image(1116).png)   Web サービスクラスを定義するとテスト用画面が用意されますが、デフォルトでは表示しない設定になっています。 IRIS へログインし(またはターミナルを起動し)、プロダクションがあるネームスペースに移動して以下実行してください。 ご参考:[https://docs.intersystems.com/irislatestj/csp/docbook/DocBook.UI.Page.cls?KEY=GSOAP\_service\_catalog_page](https://faq.intersystems.co.jp/csp/faq/result.csp?DocNo=281) 以下、[サンプルコード](https://github.com/Intersystems-jp/selflearning-interoperability)の docker-compose up -d でコンテナを開始した環境での設定例です(%SYS ネームスペースで実行します)。
set $namespace="%SYS"
set ^SYS("Security","CSP","AllowClass","/csp/user/","%SOAP.WebServiceInfo")=1
set ^SYS("Security","CSP","AllowClass","/csp/user/","%SOAP.WebServiceInvoke")=1


【注意】実行文には大文字小文字の区別がありますので、注意して記述してください。また、プロダクションを使用するネームスペースによって指定文字が変わります。例文はサンプルをUSERネームスペースへインポートした前提で記述しています。
もし、サンプルコードをABCネームスペースにインポートしている場合は、第4番目の添え字は "/csp/abc/" を指定します。
 

設定が完了したら、以下の URL にアクセスします。

http://localhost:52773/csp/user/Start.WS.WebServiceBS.cls

![](/sites/default/files/inline/images/images/image(1117).png) WSDL を Web サービスクライアントへ提示する場合は、以下のURLの末尾に WSDL=1 を指定してください。

http://localhost:52773/csp/user/Start.WS.WebServiceBS.cls?WSDL

  ### 3,アダプタを使用せず、ストアドプロシージャや REST で呼び出されるビジネス・サービス([Start.NonAdapterBS](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/NonAdapterBS.cls)) 次は、アダプタを使用しないビジネス・サービス(Start.NonAdapterBS)をご紹介します。 ![](/sites/default/files/inline/images/images/image(1118).png)   アダプタを使用するビジネス・サービスでは、アダプタが情報を検知すると、ビジネス・サービスの ProcessInput() メソッドを呼び出します。 アダプタを使用しない場合も、ProcessInput() メソッドを呼び出せばいいのですが、このメソッドは外部公開していないため、アダプタを使用しないビジネス・サービスを実装する場合、ProcessInput()を実行するための方法を検討する必要があります。 サンプルでは、以下2種類の方法を利用しています。 * ストアドプロシージャ([Start.Utilsクラス](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/Utils.cls)) * REST 用ディスパッチクラス([Start.REST](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/REST.cls))→ [こちらの記事](https://jp.community.intersystems.com/node/483041#datasend)で実行したサービスです。   では、ストアドプロシージャの例をご紹介します。 ![](/sites/default/files/inline/images/images/image(1119).png)   プロダクションにアダプタを使用しないビジネス・サービス([Start.NonAdapterBS](https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/NonAdapterBS.cls))を追加した後で(サンプルでは追加済に状態)以下ストアドプロシージャを実行します。

call Start.Utils_CallProduction('うなぎ','浜松市')

![](/sites/default/files/inline/images/images/image(1220).png)   実行結果のトレースは以下の通りです。 ![](/sites/default/files/inline/images/images/image(1122).png)   続いて、REST 用ディスパッチクラス作成例をご紹介します。 ![](/sites/default/files/inline/images/images/image(1123).png)   XData Url Map に定義されている XML は、REST 呼び出しのときの URL に対して、どのメソッドが呼び出されるかを定義しています。 サンプルは、**GET 要求で /weather/第1引数(購入商品名)/第2引数(都市名)**の URL が渡されると、WeatherCheck() メソッドを呼び出す定義を記述しています。
<Route Url="/weather/:product/:arecode" Method="GET" Call="WeatherCheck"/>
後は、 上記 URL を指定するためのベース URL を管理ポータルのウェブアプリケーションパス設定画面で定義したら完成です。 設定詳細については、[こちらの記事](https://jp.community.intersystems.com/node/483041#local)をご参照ください。   準備ができたら、REST で情報を送信できるビジネスサービスを利用して、情報を流してみます。 例)http://localhost:52773/start/weather/ちくわ/豊橋市 ![](/sites/default/files/inline/images/images/image(1124).png) ![](/sites/default/files/inline/images/images/image(1125).png)   アダプタを使用しない場合、直接外部から ProcessInput() が呼び出せないため、REST やストアドプロシージャを通して実行されるロジックの中でビジネス・サービス用オブジェクトを生成し(Ens.Director クラスの CreateBusinessService() メソッドを使用) ProcessInput() を呼び出しました。 アダプタを使用する場合は、アダプタが入力を検知し専用オブジェクトに情報を格納しビジネス・サービスに渡してくれますが、アダプタを使わない場合、その部分だけが異なるだけで後の処理はほとんど一緒です。  

ビジネス・サービスは、IRIS 外部から入力された情報を利用して要求メッセージを作成し、ビジネス・コンポーネントを呼び出すだけのシンプル設計です。

 

サンプルプロダクションを通して以下の内容が確認できました。

プロダクションを動作させるために役割が異なるコンポーネントがある(ビジネス・サービス、ビジネス・プロセス、ビジネス・オペレーション)

コンポーネント間で情報を伝達するためには、メッセージを使用する

メッセージは削除しない限りデータベースに保存されているので、いつでもトレースできる

接続周りの処理を簡単にしてくれるアダプタがある
 

IRIS の Interoperability(相互運用性)の使い方についての基本操作は以上の通りです。 この他、CSVファイルなどの形式の決まったファイルの入出力に便利なレコードマップ(ご参考:[FAQトピック](https://faq.intersystems.co.jp/csp/faq/result.csp?DocNo=404))や、データ変換ツールなどもあります。 また、このシリーズと同様にInteroperability を利用して [InterSystems IRISでシンプルに開発するIoTアプリケーション](https://codezine.jp/article/corner/795)の記事もあります。ぜひご参照ください。 この他、IRIS for Health では FHIR や HL7(SS-MIX2も含む)の送受信についてもサポートしています。 また別の記事でご説明できたらと思います。ご興味ある内容ありましたら、ぜひコメント欄にご記入ください! 最後に、Interoperability(相互運用性)の使い方についてはトレーニングコースもご用意しています。 講師と一緒にじっくり試してみたい方は、ぜひトレーニングコースへのご参加もご検討ください!