この記事は CData Software Advent Calendar 2021 の6日目の記事です。
ローコード開発プラットフォームのOutSystems上で、CData Connectを使ったスマレジとのデータ連携を試してたので、その方法とOutSystems上でCDataを活用するポイントについて書きます。
なお、OutSystemsもCDataもスマレジも無料で試せるので、記事を読みながらハンズオンすることも可能です。
また、割と細かいハンズオンステップまで書いているので記事が長いです。連携方法の詳細は端折ってサマリだけ見たいという方は振り返りをご参照ください。
OutSystems について
OutSystems知らないよ、という方はこちらの「2分でわかるOutSystems」をご確認ください。
OutSystemsの外部連携パターン
OutSystemsでは、プラットフォーム上で独自にDBを構築・管理することもできますが、既存のシステム(のDB)や外部サービスと連携をすることもできます。ザックリ以下の3パターンの連携方法があります。
1. 外部DBとの連携
外部のデータベース連携やカスタムコードを利用したい場合に、Integration Studioというツールを使って拡張モジュールを作ることができます。SQL Server、OracleやMySQL等の外部DBとの接続を定義して、列スキーマのマッピング、キーやIndex設定等が行えます。アプリを開発する際には、作成したコネクタを通じて外部DBにアクセスします。
2. Web API連携
RESTやSOAPでAPIを簡単に公開することも利用することもできます。例えばSales Forceやスマレジ等のSaaS上のデータを利用したい場合、各SaaSベンダーが公開しているWeb APIをOutSystems上で定義・登録することで連携を実現します。この際、OpenAPI(Swagger)などスペックが公開されていれば、数クリックで各APIメソッドを登録してロジックを組む際に利用できるようになるのですが、独自の機構をもつAPIへアクセスする場合は、APIの仕様書を読んでリクエストのパラメタやレスポンスの構造を見ながら1つづつメソッド登録する必要があり、手間がかかるし管理も大変です。<- CDataの使いどころ
3. コネクタの利用
OutSystemsではForgeというOSSのコンポーネントリポジトリがあり、そこで様々な部品が公開されています。SalesForceやSAPなどのSaaSやエンタープライズシステムと簡単に連携するためのコネクタや外部DBとの連携コネクタが用意されています。(これらは基本的には上記#1, #2の仕組みを使って再利用可能なモジュール化されたものです。)
また、最近ではIntegration Builder(OutSystemsが提供しているサービスの一つ)上で、簡単に外部SaaS(例えばSalesForceやDynamics 365、Microsoft Dataverse、SAP OData)との接続コネクタを作成できる仕組みがあり、今後はこのサービス上で外部DB連携のためのコネクタも簡単に定義できるようになります。
なぜスマレジ連携?
上記の通り、グローバルで割とニーズのある外部サービスや外部DBとの連携については、すでにOutSystemsプラットフォーム上にコネクタが存在していたり今後Integration Builder上での対応コネクタが増えていくと思われます。
OutSystems上でのCData製品の使いどころを考えたときに、以下のポイントを考慮してスマレジ連携を試してみようと思いました。
- プラットフォーム自体でコネクタの提供が今後も見込みづらい
- 自力で連携するのが面倒くさいけどCDataがコネクタ提供している
- ローコードプラットフォームと連携ニーズがありそうなもの
スマレジはPOSレジ周辺の機能を一通り提供していますが、例えば企業会計や予約管理、在庫系のシステムなどの連携するようなニーズはありそうです。また、自社業務にマッチしない周辺システムをローコードで作るといったシナリオも考えられそうです。
CData Connectを使ってスマレジ連携
CData Connectを使って、スマレジの商品データを参照・更新するような仕組みを作ります。
1.スマレジアカウントの作成とAPI利用のための下準備
CData 杉本さんがスマレジのアカウント作成~APIを使うための一連の設定方法をBlog記事にまとめていただいているので、以下記事を参考にしてセットアップします。
スマレジは初期状態で商品マスタにサンプルデータを入れてくれているので、APIのテストをすぐに始められます。これは助かる。
2. CData Connect 環境の構成手順
次に CData Connect の環境を準備します。
CData Connect (旧CloudHub) のページからトライアルアカウントを取得します。
CData Connect はSaaS ですので、アカウントを取得したらインストールやホスティングなどなく、ブラウザからログインすることですぐに使用開始です。
早速ブラウザからCData Connect にログインします。「DATABASE」タブから仮想データベースを設定していきます。まずは接続するデータソースであるスマレジのアイコンをクリックします。
1.スマレジアカウントの作成とAPI利用のための下準備で発行・確認したスマレジの契約IDとアクセストークンを設定し、保存します。
次に、ODATAタブに移動して、
Add Tables... から先ほど登録したDataBaseであるSmaregiを選択します。
次の画面で対象のTableを選択します。今回は商品マスタの取得や更新を行いたいので Products を選択します。
続いて、Productsテーブルの中で取得・更新したい項目を選択します。不要な項目を間引くことで CData Connect <=> アプリ間での通信を最低限に抑えることができます。今回はID, Price, ProductCode, ProductName, ProductNameKana の5項目に絞ります。
これでODATAのエンドポイントの設定が完了しました。
APIタブに移動するとAPIの詳細が確認できます。CData ConnectがODataエンドポイントのドキュメントを自動生成してくれます。
画面左側メニューのOpen APIリンクをクリックし、OutSystems側でAPIの仕様を取り込むためにOpen APIのスペック(jsonファイル)を以下画像の赤下線のリンクより保存しておきましょう。
最後にUSERSタブでユーザと権限の設定を行います。今回は新たにユーザを1つ追加し、Define Permissionsより追加ユーザーに全権限を付与しました。
この画面で確認できるIDとアクセストークンはOutSystems側でAPIアクセスする際に利用します。
3. OutSystemsで新規アプリ作成
OutSystems上でアプリケーションを作成する際にはService Studioというツールを使います。OutSystemsではPersonal Environmentという無料のクラウドベースバージョンを使って試すことができるので、もし実際にハンズオンしてみたい方は、アカウント作成して試してみてください。
Service Studioを開いて、New Application => From scratch -> Reactive Web App を順に選択し、スマレジのロゴを拝借して新規アプリを作ります。
デフォルトのModule nameのまま、[CREATE MODULE]ボタンをクリックしてモジュールを作成し、新規作成したモジュールを開きます。
これで開発の準備ができました。ここから、先ほどCData Connect上で定義したエンドポイントにアクセスして、スマレジ上の商品データの参照・更新を行う機能を作ります。
4. OutSystems上でREST APIの登録
先ほどCData Connect上で登録したエンドポイントを、OutSystems上で利用できるREST APIとして登録していきます。
Logicタブ => Integrations => REST を右クリック => Consume REST API
ここでは、CData Connectより先ほど取得したスペック(2. CData Connect 環境の構成手順でダウンロードしたjsonファイル)を利用できるので、右側の選択肢(ADD MULTIPLE METHODS)を選択して簡単にメソッド登録できます。
CData無しのケース、スマレジAPIに直接接続する場合は、スマレジはOpenAPIではないので左側の選択肢(ADD SINGLE METHOD)を選択して、1つづつAPI仕様書を確認しながらメソッドを登録する必要があります。後述しますがここが割と面倒です。
2. CData Connect 環境の構成手順で取得したOpen APIのスペック(jsonファイル)をアップロードし、ADD METHODSを行います。
スペックファイルから読み取った利用可能なAPIメソッドを自動的に作成することができます。今回はすべてチェックがついた状態でFINISHをクリックしてすべてのメソッドをOutSystems上に登録します。
上の画像のように利用可能なAPIメソッドが登録されました。また、認証が通さなければいけないので、先程Cdata Connectで登録したユーザーのIDとTokenをBasic Authentication の Username と Password に登録します。
APIの登録時に、OutSystems上で利用できるStructure(データモデルのようなもので、APIコールの結果やAPIから取得したデータを受け取るための型定義)が自動作成されます。DataタブのStructureフォルダより確認できます。
5. OData利用時に必要なAPI設定
OutSystems上でODataを利用する場合、最後にもう一つだけ設定が必要となります。ODataを通じてデータを取得する際、$selectや$filterなど条件の絞り込みや取得項目を調整するためのパラメタが用意されています。これらのパラメタ名はODataの規格で決まっているものです。
OutSystemsは、以下のようにAPIのパラメタも自動的に作成してくれるのですが、$記号は内部的にパラメタ名として利用できない規約があるためODataのAPI作成時には$記号が削られた状態でパラメタ定義されてしまいます。
これを補うために、リクエストが投げられる直前のイベントを拾って、$記号をODataの予約パラメタに付加するようなロジックを加える必要があります。
以下画像のように、On Before Requestイベントを新たに定義します。
On Before Requestイベント内では、以下のようにロジックを組みます。このイベントはAPIのリクエストを投げる直前にパラメタを改変したい場合などに利用できるもので、以下でやっていることはパラメタをループで回して、filterやselectなどODataの予約パラメタの場合には$記号を先頭に追加するといったものです。
If条件の設定値
(Request.URLQueryParameters.Current.Name = "top")
or (Request.URLQueryParameters.Current.Name = "filter")
or (Request.URLQueryParameters.Current.Name = "skip")
or (Request.URLQueryParameters.Current.Name = "orderby")
or (Request.URLQueryParameters.Current.Name = "select")
or (Request.URLQueryParameters.Current.Name = "expand")
これで、APIを利用するための準備が整いました。
6.画面作成
先ほど登録したAPIメソッドとStructure定義を使って商品マスタを一覧表示する画面を作成します。
Interfaceタブ => MainFlowを右クリック => Add Screen => Emptyを選択して CREATE SCREEN
Product List画面をEmpty Screenで作成しました。作成した画面を右クリックして、Add Local Variableを選択し、PrudctListという変数を作成します。Data Typeには先ほど自動生成されたSmaregi_ProductのList型を選択します。
更に、商品名で部分一致検索をさせるために、検索条件を格納する変数SearchTextを同じ要領で作成します。Data TypeはTextでOKです。
続いて、画面をデザインします。画面右側のツールボックスからSearch要素をMain Contentに配置し、幅をドラッグで4Colぐらいに縮めて、右側にボタン要素を配置します。
次に、ProductList変数をドラッグ&ドロップでMain Contentへ落とし込むと、自動的にTable要素が追加され、一覧表示のためのUIが作成されます。初期状態では適当なカラムが表示されているため、ID例を削ったりProductName列をドラッグ&ドロップで追加したり、Cellの順序を入れ替えるなどして以下のように列を設定します。
Table要素のMarginを20pxに設定します。
これで画面デザインは完成です。
7. 参照APIをコールしてデータを取得
検索ボタン押下時に登録したAPIをコールする処理を定義します。SearchボタンをダブルクリックしてSearchOnClickのロジックを開きます。
Logicタブよい登録したAPIを展開し、getAllSmaregi_Productsをドラッグ&ドロップでロジックに配置します。
検索条件として入力された文字列を商品名で部分一致検索したいので、filterパラメタには"substringof('" + SearchText + "', ProductName)"を設定します。※substringofは部分一致判定に利用できるODataのクエリ関数です。
続いて、ツールバーからAssign要素を配置し、以下図のようにProductListに取得結果を格納します。
最後に、If要素とメッセージを配置し、以下のように設定します。
これで検索ロジックは完成です。実行してみましょう。
画面上部中央の緑のアイコンをクリックすると、One click Publishが始まります。作成したAPIや画面の設計情報がサーバーへアップロードされ、コンパイル後にWebサーバーへ配備されます。
緑のアイコンが青に変わったら準備完了。青いアイコンをクリックして実行結果を確認してみましょう。
うまく動作していますね!
8.詳細画面に商品データを表示
まずは、商品の詳細画面を作成します。
Interfaceタブ => MainFlowを右クリック => Add Screen => Emptyを選択して CREATE SCREEN
Product Detail 画面をEmpty Screenで作成しました。作成した画面を右クリックして、Add Input Variableを選択し、PrudctIdという画面引数を定義します。Data TypeにはLong Integerを選択します。
続いて、渡されたIDからAPI経由で商品マスタの対象商品のデータを取得するための処理を定義します。ProductDetailを右クリックして Fetch Data from Other Source を選択します。
GetProductByIdという名前を付けた後、更にOutputパラメタ名をProductsとして、DataTypeにSmaregi_Prudctを設定します。
LogicタブのAPIよりgetSmaregi_Productsをロジックに配置します。getSmaregi_Productsは、引数にProductIDを渡して、商品マスタの中でIDが一致する商品を取得する関数なので、プロパティウィンドウ上で引数のProductIdに、画面引数のProductIdを設定します。
Assign要素を配置してOutputパラメタのProductに、getSmaregi_Productsのレスポンス結果を格納します。
データ取得ロジックは完了。
続いて、詳細画面のUIを構成します。画面を開き、Form要素をMain Content領域へ配置します。
Form要素の中に、GetProductByIdをドラッグドロップします。すると入力項目やSaveボタンが自動的に生成されます。
PrudctIDの項目を削除したり、他項目の順序を入れ替えて調整します。この際、Widget Tree表示を利用すると項目の入れ替え操作などを簡単に行うことができます。
最後に、作成した詳細画面へ、一覧画面から遷移できるように設定します。ProductList画面を開いて、一覧上のProductCodeのセルのExpressionを右クリックし、Link to => MainFlow/ProductDetail を選択すると画面の紐づけを行うことができます。
画面遷移にはProductIdを引数として渡す必要があるので、ProductList.Current.ProductIdを設定します。(選択されたレコードのProductIdが渡されるようになります。)
これで画面設定は完成しました。
9. 更新APIをコールして商品データを更新
SaveボタンをダブルクリックしてSaveOnClickのロジックを開きます。デフォルトの状態でフォームのバリデーション(必須項目のチェックなど)は行われるようになっており、エラーがある状態では先の処理に進ませないような判定が入っています。
バリデーション判定の後ろに、LogicタブからupdateSmaregi_Productsメソッドを配置します。引数にはそれぞれProductIdとGetProductById.Productを設定します。※GetProductByIdのレスポンス結果をそのまま流用して画面項目にバインドしているため、ユーザが値変更を行った場合はGetProductById.Productが更新される仕組みになっています。きれいに作るのであれば別途画面変数を用意しても良いです。
その後、更新完了のメッセージを配置してロジックは完成です。
One Click Pubslish(緑のボタン)をクリックして実行結果を確認します。
検索結果よりProductCodeのリンクをクリック
詳細画面遷移後の状態
値を変更してSaveボタンをクリック
スマレジのサービス上で結果の確認
更新されていくことが確認できました!
CData抜きでスマレジ連携した場合
CDataのありがたみを感じるためにも、CData抜きでスマレジ連携やろうとするとどうなるのか、検証しました。
画面のUI作成など同じ部分は端折って、異なる点だけを簡単にまとめます。
スマレジAPIの登録
スマレジのAPIをOutSystemsから直接叩きたい場合、まずはスマレジのAPIドキュメントを調べます。
スマレジのPOSアプリに入って、設定 => システム連携 => スマレジAPI設定 よりAPIの仕様書をダウンロードすることができます。
仕様書自体は一般公開されているものではないので、ここでは載せられませんが、今回の目的に照らし合わせた場合に必要な情報は以下のようなものとなります。
- 認証はリクエストヘッダに契約ID(X-contract-id)とアクセストークン(X-access-token)を設定
- HTTPメソッドはすべてPOST(参照系も更新・追加系も)
- リクエストパラメタ(Body部)はproc_nameに処理名を指定し、paramsに検索条件やソート条件など各種パラメタを設定
リクエスト例
[Header]
X-contract-id: XX0000
X-access-token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
[Body]
proc_name=category_ref¶ms={
"fields":["categoryId","categoryName"],
"conditions":[{"categoryName like":"%テ%"}],
"order":["categoryId desc"],
"limit":100,
"page":1,
"table_name":"Category"
}
少し独特ですね、、、参照も含めて全てPOSTでリクエストBodyの中にURLパラメタ形式の設定とJson形式の設定が混在しています。
かなりのクセモノです。
それでは上記のリクエスト例をもとにREST APIのメソッドをOutSystems上で登録していきます。
Logicタブ => Integrations => REST を右クリック => Consume REST API
スマレジはOpenAPIではないので左側の選択肢(ADD SINGLE METHOD)を選択して、1つづつAPI仕様書を確認しながらメソッドを登録する必要があります。。。
まず、APIのエンドポイント(~webapi.smaregi.jp/access/)を設定し、リクエストタイプはPOSTに変更します。今回は商品マスタの情報を取得したいので、Requestには、以下を設定します。※商品テーブルを取得するための対象の処理名やテーブル名は[外部インターフェース仕様書(POS)_ver_XXX]で確認できます。
次に、リクエストヘッダのパラメタを設定します。ここは上記リクエスト例の項目に倣って設定します。
最後に、Testタブでパラメタに値を設定してTESTボタンで結果確認。※ここで設定する契約IDやアクセストークンはスマレジのスマレジAPI設定画面にて確認できます。
レスポンス 200 OK。ちゃんと商品情報のレコードも取得できています。ここで、TESTボタンの下にある COPY TO RESPONSE BODY というリンクをクリックするとBodyタブのResponseに取得結果が格納されます。この状態でFinishボタンを押してAPIメソッドを定義し終えると、自動的にこのレスポンスを受け取るためのStructure(データモデルのようなもの)が、DataタブのStructureフォルダの下に定義されます。
これを使ってデータをAPI経由で受け取り、画面に適用していく流れとなります。
最後に、APIメソッドのRequest FormatをPlain Textに設定します。
ここがポイントで、確認したスマレジのAPIリクエストでは、URLパラメタ形式とJSON形式が混在していましたが、こういったケースではパラメタの設定が複雑になります。
どちらかの形式ですべて統一されていれば、Request Formatの設定において、対応するものを選択することでパラメタの引き渡しが非常に楽になります。例えば、JSON形式で統一されている場合、リクエストパラメタにはJSONオブジェクトをそのまま引き渡してあげてば、良しなにAPI通信してくれるのですが、フォーマットが混在している場合、自分でリクエスト文字列を組み立てる必要が出てきます。
今回のケースではProductNameで部分一致検索させたいので、パラメタは以下のような感じになります。
proc_name=product_ref
¶ms={
"table_name":"Product",
"conditions":[{"productName like":"%検索文字%"}]}
こういったパラメタを渡すために、Request FormatはPlain Textを選択し、自分でクエリ文字列を組み立てる必要があります。
データ参照APIメソッドの利用
Searchボタン押下時のロジックは以下のような感じになります。
大きな流れは変わりませんが、認証回りと検索に使うパラメタは設定方法が異なります。契約IDとアクセストークンをリクエストヘッダのパラメタとして設定、検索対象となるテーブルや検索条件などはRequestパラメタにすべて設定します。
今回は検索条件が商品名の部分一致検索のみなので、SearchTextを決め打ちでクエリパラメタ内に組み込んだためそこまでパラメタ文字列の組み立ては複雑ではありませんが、もし検索条件の項目量が多かったり、AND / ORの条件が複雑になるような場合、このクエリ文字列の組み立てでかなり苦労しそうです。
データ更新系APIについて
さて、続いてデータ更新のAPIですが、スマレジのAPI仕様書を見ると...
なるほど、更新対象の商品データをJSON形式の文字列にパースして、そのほかパラメタも文字列連結、、、
急に睡魔に襲われてきたのでこの辺で止めておきます。
もちろん、この更新APIと連携させることは可能ですが、パラメタ設定が少し面倒なのは想像に容易いです。
振り返り
OutSystems上でスマレジとのデータ連携を、CData Connect経由のパターンと無しのパターンでそれぞれ試しました。
CData Connectの活用利点
今回CData Connect経由でスマレジ上の商品マスタを参照・更新する画面を作成しましたが、CData Connect側の設定も含めて30分~1時間ほどでできました。
RESTful APIのベストプラクティスであるODataでの連携ができたので、APIの登録もワンクリックだし、条件の絞り込みなどパラメタ設定も簡単にできました。
一方、自力でAPI連携をしようとした場合、スマレジのAPI仕様書を読解してその形式にあったAPIメソッドを1つずつ登録。リクエストのパラメタ設定もスマレジ独自の規格に合わせて文字列を組み立てる必要があり、手間がかかります。商品データの検索画面だけでも様々な試行錯誤・トライ&エラーがありCData Connect経由時の3倍以上の時間がかかりました。
独自APIを資料読解して、実際につつきながら作るのは時間かかりますが、CData Connect経由だとその手間がすべて省けます。
また、一度構築したデータ連携をメンテナンスしていく際にも、連携先のAPI変更への対応や複数の連携先へのロジックの統一など、CDataによるAPI規格および管理場所の統一は利点となりそうです。
CData Connect利用時の注意点
1つ気になったのがレスポンス速度。
スマレジAPI直叩きの場合は、検索ボタン押してからの一覧表示されるまでのレスポンスは0.2秒ほどでしたが、CData Connect経由の場合、私の環境では一覧表示までに2秒ほどかかりました。
CData Connectがスマレジからデータを取得し、更にODataのクエリ処理などを行っているところで少々時間がかかっているようです。また、経由するサーバーが1つ増える以上、多少の遅延は仕方ありません。
レスポンスをどうしても改善したい場合には以下のオプションが考えられます。
- CData Connectを自社内サーバーでたてる
- CDataのドライバを利用して(Integration Builder上で).NETのカスタムコネクタを作成する
が、1は若干のパフォーマンス改善にはなるものの、独自API<=>ODataの変換処理は走るので、劇的な改善にはならなそうです。2は割と大変なので、そもそも直接API連携したほうが楽そうです。
ということで、パフォーマンスが求められるようなトランザクション処理での利用は注意が必要です。
一方、例えばデータ分析用のダッシュボード構築のために様々な外部サービスと連携する、といたシナリオでは力を発揮できそうです。
まとめ
OutSystems(ローコード)上でのCData Connectを使ったサービス連携について、ポイントをまとめると
- 連携先サービスのAPIドキュメントの読み込み不要、楽だし(開発が)早い
- 連携先が多くなってもAPIの規格を統一できるのでロジック管理しやすい
- 連携先のAPI変更への対応が楽(CDataが対応してくれるはず)
- レスポンス速度は落ちるので、使用頻度の高いトランザクション処理での利用等には注意が必要