[InterSystems IRIS for the First Time] Interoperability: Creating Components (Business Services)
Tags: beginners, programming, tutorial, interoperability
Published: 2022-11-29 19:52:16

**This article is a continuation of <a href="https://community.intersystems.com/post/intersystems-iris-first-time-interoperability-creating-components-business-process" target="_blank">this post</a>.**

In the <a href="https://community.intersystems.com/post/intersystems-iris-first-time-interoperability-creating-components-business-process" target="_blank">previous article</a>, we discussed the development of business processes, which are part of the components required for system integration and serve as a production coordinator.

This article will discuss creating a business service, which is the information input window for production.

* <a href="https://community.intersystems.com/post/intersystems-iris-first-time-interoperability-what-prodction" target="_blank">Production</a>
* <a href="https://community.intersystems.com/post/intersystems-iris-first-time-interoperability-message" target="_blank">Message</a>
* **<span style="background-color:#f1c40f;">Components</span>**
  * **<span style="background-color:#f1c40f;">Business services</span>**
  * <a href="https://community.intersystems.com/post/intersystems-iris-first-time-interoperability-creating-components-business-process" target="_blank">Business processes（previous post）</a>
  * <a href="https://community.intersystems.com/post/intersystems-iris-first-time-interoperability-creating-components-business-operation" target="_blank">Business operation</a>

And finally, the last component of “Let's Use Interoperability!”

The business service provides a window of input for information sent from outside IRIS, with or without using the adapter for external I/F.

There are three types of business services in the sample (links in parentheses are links to the sample code):

  1. [Business services for files using inbound adapters](#fileinboundadapter)（<a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/FileBS.cls" target="_blank">Start.FileBS</a>）
  2. [Business services for Web services using the SOAP inbound adapter](#soapinboundadapter)（<a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/WS/WebServiceBS.cls" target="_blank">Start.WS.WebServiceBS</a>）
  3. [Business service called by stored procedure or REST without using an adapter](#nonadapter)（<a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/NonAdapterBS.cls" target="_blank">Start.NonAdapterBS</a>）

Different connection methods used for inputting information will only increase the number of business services; however, the processing done within a business service is

<h3 style="text-align: center;">
  <strong><span style="background-color:#f1c40f;">Create a request message to be sent</span></strong><br /><strong><span style="background-color:#f1c40f;">using externally inputted information and </span></strong><br /><strong><span style="background-color:#f1c40f;">simply call the business component</span></strong>
</h3>

It's effortless.

Now, let's outline how to create components that use file-inbound adapters.

Business services are written in scripts, which can be created in VSCode or Studio (see <a href="https://jp.community.intersystems.com/node/482976" target="_blank">this article</a> on using VSCode).

### <a id="fileinboundadapter" name="fileinboundadapter"></a>1. Business services for files using inbound adapters（<a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/FileBS.cls" target="_blank">Start.FileBS</a>）

If you create a class in VSCode, you should create a class that inherits from Ens.BusinessService. As for adapters, you can use the **ADAPTER** parameter as ADAPTER class name (e.g., specify a file-inbound adapter class).  
If you do not use the adapter, no configuration is required.

```objectscript
Class Start.FileBS Extends Ens.BusinessService
{
Parameter ADAPTER = "EnsLib.File.InboundAdapter";
```

In the file-inbound adapter, you can specify the directory to be monitored in Settings→File Path for the production's business service.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s88iemr6cx93uqde3028.png)



 If the file located in the "File Path" matches the information specified in the "File Spec," it opens the file as a stream object. It defines it as the first variable when calling the business service **ProcessInput()**.

When **ProcessInput()** is started, **OnProcessInput()** is automatically called. OnProcessInput() is passed directly to **OnProcessInput()** with the parameters passed to ProcessInput().


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ssije2zcqrkrwm5ie0rn.png)


In **<span style="background-color:#f1c40f;">OnProcessInput()</span>** the initial statement gets the information from the file stream object, which is passed as the first parameter, then creates a message to be given to the next component, writes the process of calling the next component, and completes the basic logic.

* * *

<p style="margin-left: 40px;">
  【Memo】<br />For Studio, launch the Business Services Wizard in the New Creation menu, select the adapter and press the Finish button.
</p>


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/12q0qs61obxtwvyle8fv.png)

* * *

The **<span style="background-color:#f1c40f;">OnProcessInput()</span>** method definition is as follows:

```objectscript
Method OnProcessInput(pInput As %Stream.Object, Output pOutput As %RegisteredObject) As %Status
```

**pInput**  is provided with an instance of the **%Stream.FileCharacter** class for text files or the **%Stream.FileBinary** class for binary files.

In the sample, a file in text format will be inputted, and we have written it to accept multi-line requests and one request per line.

**AtEnd property** is set to 1 when EndOfFile is deteced. You can use this property to stop loop.

In a loop, we read the lines using the **ReadLine()** method, which enables us to obtain information about the contents of the file one line at a time (<a href="https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=EFIL" target="_blank">see the documentation</a> for file adapter details).

Compose the message, retrieving information line by line. Then, we execute the <span style="color:#16a085;"><strong>..SendRequestAsync()</strong> </span> method, which calls the other components.

When executing the method, the first parameter should be the name of the component you want to call as a string, and the second parameter should be the request message you have created.

Note that the <span style="color:#16a085;"><strong>..SendRequestAsync()</strong></span> is an asynchronous call and does not wait for a response.

<p style="margin-left: 40px;">
  Memo：There is also SendRequestSync() for synchronous calls.。
</p>

The sample code is as follows:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fc2crpli8bwfhnv8wlg.png)


<u>Reference：explanation of the usage of the $piece() function in the above example text</u>

<p style="margin-left: 40px;">
  <strong>$piece(“string”, ”delimiter mark”, ”position number”)</strong>
</p>

<p style="margin-left: 40px;">
The function to set/get a string with a delimiter, in the sample, to get the first and second value of comma-separated data, is written with the following syntax:
  </p>


```objectscript
set request.Product=$piece(record,",",1)
set request.Area=$piece(record,",",2)
```


Now, let's check the function of <a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/FileBS.cls" target="_blank">Start.FileBS</a> as it appeared in the above description.

In the sample production, the "File Path" was set to **/irisdev/src**, and the "File Spec" was set to **check.txt**.  Either prepare the same directory or change it to a different directory and register the sample data in the check.txt file using the following format: purchased product name, name of the city.

※If you are using the sample container, please rename [Test-check.txt] in the src directory under the directory created by the git clone.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jsqdfgcvb0qiikw42pvm.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aoa1u7ojroyp58ee1og1.png)


### <a id="soapinboundadapter" name="soapinboundadapter"></a>2. Business services for Web services using the SOAP inbound adapter （<a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/WS/WebServiceBS.cls" target="_blank">Start.WS.WebServiceBS</a>）

Next, we will outline the creation of business services for Web services.

The Business Service Class for Web Services acts as a Web Service Provider = Web Service Server.

In the sample, we have two parameters in the Web service method for this sample production to have information sent from the Web service client.  The web method uses the data entered in the parameters to create a message class and call other components.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6qikatsjh2vpu8ajnk1.png)


When you define a Web service class, a test screen is created. However, it is not shown by default.

Log in to IRIS (or start a terminal), go to the namespace where the production is located and do the following:

For your reference：<a href="https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GSOAP_WebService#GSOAP_service_catalog_page" target="_blank">Access to the Catalog and Test Pages</a>

Here is a <a href="https://github.com/Intersystems-jp/selflearning-interoperability" target="_blank">sample code</a> configuration in the setting where the container was started with <span style="color:#8e44ad;"><strong>docker-compose up -d</strong></span> (run in the %SYS namespace)

<pre>set $namespace="%SYS"
set ^SYS("Security","CSP","AllowClass","/csp/user/","%SOAP.WebServiceInfo")=1
set ^SYS("Security","CSP","AllowClass","/csp/user/","%SOAP.WebServiceInvoke")=1</pre>

<p style="margin-left: 40px;">
  <br /><strong><span style="background-color:#f1c40f;">【Attention】</span></strong>Please note that the sentence is case-sensitive and should be written with care. Also, depending on the namespace in which the product is used, the specified script changes. The example sentence is written on the assumption that the sample is imported into the USER namespace.<br />If you import the sample code into the ABC namespace, the fourth subscript should be "/csp/abc/."<br />
</p>

Once the configuration is complete, go to the following URL:
<p style="margin-left: 40px;">
  <strong>http://localhost:52773/csp/user/Start.WS.WebServiceBS.cls</strong>
</p>


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etsn6lg0n0iu8t90tvve.png)


If you want to provide the WSDL to your Web services client, specify WSDL=1 at the end of the following URL

<p style="margin-left: 40px;">
  <strong>http://localhost:52773/csp/user/Start.WS.WebServiceBS.cls?WSDL</strong>
</p>

### <a id="nonadapter" name="nonadapter"></a>3. Business services called by stored procedures or REST without using adapters（<a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/NonAdapterBS.cls" target="_blank">Start.NonAdapterBS</a>）

Next, we will introduce the Business Service without adapters (Start.NonAdapterBS).


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cing01ln0163irwoyqul.png)


For business services that use adapters, the adapter calls the business service's ProcessInput() method to detect the information.

If you don't use adapters, you can still call the ProcessInput() method, but this method is not public. Therefore, if you implement a business service that does not use adapters, you will need to consider ProcessInput().

The sample utilizes the following two methods:

* Stored procedures（<a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/Utils.cls" target="_blank">Start.Utils</a>）
* Dispatch Class for REST（<a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/REST.cls" target="_blank">Start.REST</a>）→This is the service we ran in <a href="https://community.intersystems.com/post/intersystems-iris-first-time-interoperability-what-prodction#datasend" target="_blank">this article.</a>

Now, here's an example of a stored procedure.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eue5va463av48q524po9.png)


After adding a business service (<a href="https://github.com/Intersystems-jp/selflearning-interoperability/blob/master/src/Start/NonAdapterBS.cls" target="_blank">Start.NonAdapterBS</a>) that does not use adapters to the production (state added in the sample), run the following stored procedure

<p style="margin-left: 40px;">
  <strong>call Start.Utils_CallProduction('piroshki','Russia')</strong>
</p>


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pb9wq4fb5twg0gwwqyu.png)


A resulting trace of the running result is as follows:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e011aya778rwt3wq0hdl.png)


Next, here is an example of creating a dispatch class for REST:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r9kvvquc29l6jpcvo0ee.png)



The XML described in the XData Url Map defines which methods are called in response to the URL at the time of the REST call.  
The example describes a definition that calls the **WeatherCheck()** method when the URL of the **/weather/first parameter (purchased product name)/ second parameter (name of the city)** are provided in the **GET request**.

```objectscript
<Route Url="/weather/:product/:arecode" Method="GET" Call="WeatherCheck"/>
```

Then, define the base URL for the above URL in the Management Portal's Web Application Path Settings screen, and it is complete.

See <a href="https://community.intersystems.com/post/intersystems-iris-first-time-interoperability-what-prodction#local" target="_blank">this article</a> for more details on the configuration.

Once it is ready, try to run the information using a business service that allows you to send the REST information.

Example）<a href="http://localhost:52773/start/weather/%E3%81%A1%E3%81%8F%E3%82%8F/%E8%B1%8A%E6%A9%8B%E5%B8%82" rel="nofollow" target="_blank">http://localhost:52773/start/weather/Takoyaki/Osaka</a>


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xds5edaq6tr2g24j8pqo.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kwdoyffd11fvhq8e68vc.png)

If you do not use an adapter, as ProcessInput() cannot be called directly from outside, we have created an object for the business service in the logic executed through REST or stored procedures (using the CreateBusinessService() method of the Ens.Director class) and called ProcessInput()

If you use an adapter, the adapter detects the input and stores the information in a unique object and passes it to the business service. In contrast, if you don't use an adapter, the rest is pretty much the same, only the difference is in the above-mentioned part of the process.

<p style="margin-left: 40px;">
  <img src="https://community.intersystems.com/sites/default/files/inline/images/images/image(1078).png" />The business service is simply designed to use the information entered outside IRIS to create request messages and call business components.
</p>

<p style="margin-left: 40px;"></p>

Throughout the sample production, we were able to see the following:

<p style="margin-left: 40px;">
  <strong><span style="background-color:#f1c40f;">Different components play different roles in making a production run (business services, business processes, business operations).</span></strong>
</p>

<p style="margin-left: 40px;">
  <strong><span style="background-color:#f1c40f;">To transmit information between components, use the message.</span></strong>
</p>

<p style="margin-left: 40px;">
  <strong><span style="background-color:#f1c40f;">Messages are stored in the database unless deleted and thus can be traced at any time.</span></strong>
</p>

<p style="margin-left: 40px;">
  <strong><span style="background-color:#f1c40f;">Some adapters simplify the process of around the connection.</span></strong><br /> 
</p>

These are the basic operations on how to use Interoperability in IRIS.

There are also record maps (see: <a href="https://faq.intersystems.co.jp/csp/faq/result.csp?DocNo=404" target="_blank">FAQ TOPIC</a>) and data conversion tools that are useful for input and output of CSV files and other format-specific files.

As well as this series, there is also an article on <a href="https://codezine.jp/article/corner/795" target="_blank">simple IoT applications developed with InterSystems IRIS using Interoperability</a>. Please check it out.

Besides, IRIS for Health also supports FHIR and HL7 (including SS-MIX2) transmissions.

I would be pleased to explain it in another post. If you have something of interest to share, please leave a comment!

Finally, training courses are also available to learn how to use Interoperability.

If you'd like to take the time to try it out with an instructor, please consider joining one of our training courses!