Salesforce Connectを使って外部のRDBMSからデータを取得して外部オブジェクトとして表示する方法

# はじめに

## 概要

Salesforceには、Salesforce ConnectというSalesforce 外に保存されているデータの表示、検索、変更を可能にするフレームワークがあります。今回は、このSalesforce Connectの機能を使ってMySQLやSQL Databaseといった外部データソースおよび外部オブジェクトとして定義することでRDBMS内のデータにリアルタイムにデータアクセスする方法をご紹介します。これにより、Salesforce外で管理されているRDBMSに格納されている最新の在庫データなどにSalesforceの画面からシームレスに取得することが出来るようになります。

## 前提として必要なアプリ- サービス

- [Salesforce](https://www.salesforce.com/jp/)アカウントを取得済であること
- [CData API Server](http://www.cdata.com/jp/apiserver/)　※30日間利用可能な無償評価版あり
- [Heroku](https://www.heroku.com/home)や[Azure App Service](https://azure.microsoft.com/ja-jp/services/app-service/)などJavaか.NETのWebアプリケーションをホストできる環境
- 上記Webアプリケーションサーバから接続可能なRDBMS（[Heroku Postgres](https://devcenter.heroku.com/articles/heroku-postgresql)や[SQL Database](https://azure.microsoft.com/ja-jp/services/sql-database/)）

## 実現イメージ

Salesforce Connectは、REST APIの[OData規格](http://www.odata.org/)のデータを読み込むことが出来ます。ただし、RDBMS標準ではODataフォーマットのデータを出力できないため、RDBMSをREST APIとしてアクセス出来るようにする[CData API Server](http://www.cdata.com/jp/apiserver/)を中継することでODataフォーマットでのレスポンスを受け取ることができるようになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/d276c5c5-602c-366b-7208-6b6740642ac1.png)

# 実際にやってみよう

## CData API Serverをインストールおよびローカルマシン環境で確認

まずはじめに、CData API Serverをローカルの環境で試してみるのがよいでしょう。以下の記事に、Windows環境×MySQLの環境ですが、マウス操作だけでRDBMS内のテーブルデータをREST APIとして公開する手順が書かれてますがご参考ください。
(Qiita記事) [MySQL のデータをCData API Server でポチポチだけでREST API として公開する](https://qiita.com/jonathanh/items/fcd9aca3c1eb52206102)
 
## CData API Server を Heroku や Azure App Service へデプロイする

上記手順で一度ローカルで動作確認したCData API Serverを次の手順でクラウド上のWebサーバーにデプロイします。以下CData社のKBにHerokuやAzure App Serviceへデプロイする手順がありますのでご参考ください。

- [API Server をAzure でホストする方法](https://www.cdata.com/jp/kb/articles/odata-azure.rst)
- [API Server をHeroku でホストする方法](https://www.cdata.com/jp/kb/articles/odata-heroku.rst)

## CData API ServerからRDBMSに接続してREST APIとして公開してみる

それでは、Webサーバにアクセスしてみましょう。下記のようなURLでアクセスできます。

Azure App Serviceの場合：https://[your sub domain].azurewebsites.net/
Herokuの場合：https://[your sub domain].herokuapp.com/

admin アカウントで管理コンソールにログインします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/6b88adcd-50f0-4e5e-7672-5eea8f89a448.png)
※adminのパスワードについて：Windows版の場合はインストール時に設定、マルチプラットフォーム版（Java版）の場合は、Java ApplicationServer毎に異なるので[こちらの製品マニュアル](http://cdn.cdata.com/help/KWC/odata/pg_servertomcatmft.htm)をご参照ください。

「設定」タブからRDBMSに接続するコネクションを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/98e6d828-7c56-5e43-4d70-745783427780.png)
※RDBMSとの接続は、内部的には、ADO.NET Providerもしくは、JDBCのインタフェースで接続しているので、DBのポート(Postgresだとデフォルト5432、SQLDatabaseだと1433)で接続する必要がありますので必要に応じてポートの設定をおこなってください。

「リソース」タブを開き、コネクションを選択して、Salesforceの外部オブジェクトとして設定したいデータベースのテーブルを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/5566c9da-9638-c8c3-9685-38557c73f81b.png)
「ユーザ」タブに移り、公開するREST APIへのアクセスを許可するユーザを作成します。作成するとパスワードに相当するトークンが発行されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/1745fb6f-75c9-74b5-0171-232b9ec1660f.png)

「サーバー」タブを開き、「信頼されたIPアドレス」にて、APIServerにアクセス可能なIPアドレスを指定します。「クロスオリジンリソースシェアリング（CORS）を有効にする」をチェックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/90d174b7-36c0-b110-3a1b-747ed0f2578b.png)
※本例では「信頼されたIPアドレス」に「*」すべてのIPアドレスとしていますが、Salesofrceの外部IPアドレスのみに絞ることが出来ます
「サーバー」タブの下のほうに移動して、ODataのデフォルトフォーマット、および、バージョンを「XML(Atom) 4.0」に設定します。設定したら「変更内容を保存」してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/cc4fd2de-237e-58af-407d-5abc9944dfa7.png)

以上でCData API Server側の設定は完了です。「API」タブを開くと、左側の「リソース」一覧に追加したリソース名（DBのテーブル名）が追加されます。本リソース名をクリックすると、右側のペインに各HTTPメソッドでのアクセス方法が記載されたAPIリファレンスを見ることができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/9fbf750d-eaa8-ed8e-955b-d978473c9333.png)

## CData API Serverで公開したREST APIのエンドポイントにアクセスしてみる

CData API ServerのアクセスしているブラウザからAPIのエンドポイント（例：https://[your sub domain].azurewebsites.net/api.rsc/SalesLT_Product/）にアクセスすると、認証が通った状態なので認証不要で済なので、HTTP GetメソッドがリクエストされてAtom形式のXMLフォーマットでRDBMS内のデータがレスポンスされていればOKです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/04e5e878-cff8-0274-9162-febe58a7bbbc.png)

PostmanなどのツールからAPIアクセスする場合には、HTTPヘッダーにx-cdata-authtokenにトークンの値をセットしてください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/80027f0f-01c2-fe93-5f72-4a0513807a4d.png)

## Salesforce Connectを使った外部データソースおよび外部オブジェクトの作成

Salsforce にログインし、［設定］→［開発］→［外部システムへの接続を管理する］をクリックします。「外部データソース」画面で「新規外部データソース」ボタンをクリックします。
「外部データソースの編集」画面にて、以下の項目を設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/3d6602bd-30cf-3d9e-4cba-01781b4c18e6.png)


- 外部データソース：CDataAPIServer（任意）
- 名前：CDataAPIServer（任意）
- 種別：Salesforce Connect:OData4.0
- URL：https://[Your Sub domain].azurewebsites.net/api.rsc（左記の例はAzureの場合）
- 形式：JSON
- ID種別：ユーザ
- 認証プロトコル：パスワード認証
- 管理者ユーザ名：CData API Serverで追加したユーザ名
- 管理者パスワード：CData API Serverで追加したユーザのトークン

設定したら「保存」して「検証して同期」ボタンをクリックします。状況が「成功」になり、CData API Serverで公開したAPIエンドポイント（更にたどるとRDBMSのテーブル名）が表示されれば成功です。該当テーブルを選択して「同期」します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/ca4b48b6-5f3c-b742-1f83-becff8c52bb9.png)

［設定］→［開発］→［外部オブジェクトを管理する］を開くと、外部オブジェクトが追加されていることを確認します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/5a1fc341-c375-0a77-3283-0a5c413e8d73.png)

外部オブジェクトの「編集」ボタンをクリックするとプロパティ値を確認します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/657c9e2a-b494-1762-60c0-0752efbb49f1.png)
外部オブジェクト名のリンクを開くと外部オブジェクトのメタデータ定義を確認できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/a363c840-c648-c323-7960-c005fa138034.png)
特に問題なければ、次は、本カスタムオブジェクトにSalesforceのタブからアクセスできるようにカスタムタブを作成します。
［設定］→［作成］→［タブ］を選択して「カスタムオブジェクトタブ」の「新規」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/61a5a084-3e5c-d00f-e9b4-9aee87c1b516.png)
作成が完了すると
「新規カスタムタブ」画面にて、オブジェクトには、作成したカスタムオブジェクトを選択して、適当なタブスタイルを選択して後はウィザード形式でデフォルト値にてカスタムタブを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/47076bf5-1cc7-3815-b2a3-7d800c9dec7c.png)
カスタムタブが追加されたことを確認します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/7d79e8fc-e3b6-d368-e4d1-dfdd9cdc5685.png)
ビューで、「すべてを選択」して「Go!」ボタンをクリックすると下記のような「外部オブジェクト認証エラー 外部システムの認証設定 にある個人設定に外部データソースエントリを追加またはすべて入力します。サポートが必要な場合は、システム管理者にお問い合わせください。」エラーが表示されます。これは、使用しているSalesofrceのアカウントが外部データアクセスする権限がないため表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/0edd1058-df79-de2d-6102-8f4a24d84da0.png)
(ご参考)[Salesforce Connect の設定](https://trailhead.salesforce.com/ja/modules/lightning_connect/units/lightning_connect_setup)より
各ユーザの認証設定を行います。ユーザに、自分の個人設定で外部システムの認証を設定、管理する方法を伝えます。または、各ユーザに対してこのタスクを実行することもできます。

［私の設定］→［個人用］→［外部システムの認証設定］から「新規」で認証設定を作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/48ca5024-2c93-ce40-f277-9bcc3971cf68.png)

- 外部システム定義：外部データソース
- 外部データソース：作成した外部データソース名
- 外部システム定義：ログインしているSalesforceユーザ
- ユーザ名：CData API Serverで追加したユーザ名
- パスワード：CData API Serverで追加したユーザのトークン

「保存」したら再度、カスタムタブにアクセスして「すべて選択」で「Go!」ボタンをクリックします。今度は、データが表示されるようになりましたが、IDとURLだけのようです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/a0c58c33-0c26-9ad5-fb13-c448f5d8a8c8.png)

新たにビューを作成して表示したい項目（最大15個）を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/5baf4e78-3680-439f-0427-ee80a51dee3a.png)
もう一度作成したビューにアクセスしてみるとRDBMS内のデータ（本例だと、SQLDabase内の製品マスタ）の一覧が表示されるようになりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/123181/e4f32ecf-db65-f535-501b-02fe2acfd55f.png)

# まとめ

Salesforceの画面にアクセス時にRDBMS内のデータを表示することが出来ました。本方式を応用すると、SalesforceにRDBMSだけでなく[CData API Server](http://www.cdata.com/jp/apiserver/)がサポートする90を超えるクラウトサービスやNoSQLデータベースをOData形式で取り込むことが出来るので、マルチクラウド、オンプレ×クラウド環境に散らばっているデータをSalesforceの画面から透過的に参照できるようになります。CData API　Serverは[30日間ご利用頂ける評価版]((http://www.cdata.com/jp/apiserver/))がございますのでダウンロードして是非お試しください。

## 参考にした情報

- CData KnowleadBase : [MySQL 外部オブジェクトをSalesforce に設定して利用](https://www.cdata.com/jp/kb/tech/mysql-odata-salesforce-lightning-connect.rst)
- Trailhead : [Salesforce Connect の概要](https://trailhead.salesforce.com/ja/modules/lightning_connect/units/lightning_connect_introduction)、[Salesforce Connect の設定]
 (https://trailhead.salesforce.com/ja/modules/lightning_connect/units/lightning_connect_setup)