Salesforce Connectをマスターする:リアルタイム外部データ統合のためのアーキテクトガイド

背景と適用シナリオ

現代のエンタープライズシステム環境において、データは複数のシステムに分散して存在するのが一般的です。顧客情報はSalesforceに、注文履歴はERPシステムに、製品在庫は倉庫管理システムに、といった具合にデータはサイロ化しがちです。これら全てのデータをSalesforceに集約しようとすると、複雑なETL (Extract, Transform, Load) プロセス、データストレージコストの増大、そしてデータの鮮度の問題に直面します。

ここで登場するのが Salesforce Connect です。Salesforce Connectは、外部システムにあるデータをSalesforceにコピーすることなく、リアルタイムで統合するための強力なフレームワーク(枠組み)です。これはしばしばデータ仮想化(Data Virtualization)と呼ばれます。Salesforce内の外部オブジェクト(External Objects)を通じて、あたかもSalesforceの標準オブジェクトやカスタムオブジェクトのように外部データにアクセス、表示、さらには更新することが可能になります。

アーキテクトの視点から見た主な適用シナリオは以下の通りです。

シナリオ1:ERPシステムとの注文データ連携

取引先責任者の詳細ページで、その顧客に関連する注文履歴や請求情報をERPシステムからリアルタイムで表示します。営業担当者はSalesforceを離れることなく、最新の取引状況を把握できます。

シナリオ2:レガシーシステムとの連携

長年使用されているメインフレームやオンプレミスのデータベースに存在する重要な顧客データを、全面的なデータ移行を行わずにSalesforceから参照したい場合に活用します。これにより、移行リスクとコストを抑えつつ、360度の顧客ビューを実現します。

シナリオ3:大規模データセットの参照

IoTデバイスから送られてくる大量のログデータや、ビッグデータプラットフォームに格納された分析データなど、Salesforceのストレージ制限には収まらない、あるいは保存に適さない大規模なデータセットを参照する場合に有効です。

Salesforce Connectの核心的な価値は、「データを必要な時に、必要な場所から、コピーせずに利用する」という思想にあり、これによりシステム全体のアーキテクチャをよりシンプルで効率的なものに設計することが可能になります。


原理説明

Salesforce Connectは、外部システムへのライブ接続(Callout)を通じて機能します。ユーザーが外部オブジェクトのレコードを表示しようとすると、Salesforceプラットフォームはリアルタイムで外部システムにクエリを送信し、結果を取得してユーザーインターフェースに表示します。この一連のプロセスは、Salesforce Connectアダプタによって抽象化されています。

アーキテクチャの主要コンポーネントは以下の3つです。

1. 外部データソース(External Data Source)

外部システムへの接続情報(エンドポイントURL、認証情報、プロトコルなど)を定義する設定です。Salesforce Connectは主に以下のアダプタをサポートしています。

  • OData 2.0 / 4.0 Adapter: OData (Open Data Protocol) は、RESTful APIを構築・利用するためのISO/IEC承認のOASIS標準です。多くのエンタープライズアプリケーション(SAP、Microsoft Dynamicsなど)がODataをサポートしており、標準的な方法でデータ連携を実現するための最も一般的な選択肢です。
  • Cross-Org Adapter: 他のSalesforce組織のデータにアクセスするための専用アダプタです。複数の組織を持つ企業が、組織間でデータをリアルタイムに共有する際に非常に便利です。
  • Custom Adapter (Apex Connector Framework): ODataのような標準プロトコルをサポートしていないシステムや、より複雑なロジック(データ変換、複数APIコールの集約など)が必要な場合に、Apexコードを用いて独自のアダプタを開発するためのフレームワークです。これにより、ほぼ全てのREST/SOAPベースのAPIと連携する道が開かれます。

2. 外部オブジェクト(External Object)

外部データソースのテーブルやエンドポイントにマッピングされるSalesforceのオブジェクトです。API参照名(末尾が `__x`)を持つ点を除けば、カスタムオブジェクトと非常によく似た振る舞いをします。外部オブジェクトの項目は、外部システムのデータ構造に対応します。管理者は「検証して同期(Validate and Sync)」機能を使うことで、外部システムのスキーマから外部オブジェクトと項目を自動的に作成できます。

3. 連携の仕組み

ユーザーが外部オブジェクトのリストビューを開いたり、SOQLクエリを実行したりすると、以下のプロセスが発生します。

  1. Salesforceプラットフォームがリクエストを受け取ります。
  2. Salesforce Connectが、SOQLクエリを外部システムのプロトコル(例: ODataクエリ)に変換します。
  3. 外部データソースで定義された認証情報を用いて、外部システムのエンドポイントにリクエストを送信します。
  4. 外部システムがリクエストを処理し、データを返却します(通常はJSONまたはXML形式)。
  5. Salesforce Connectがレスポンスを解析し、SalesforceのUIやSOQLの結果セットとして整形してユーザーに返します。

この仕組みにより、データは常に外部システムが「信頼できる情報源(Source of Truth)」となり、Salesforce側にはデータが保存されないため、データの同期や整合性の問題を根本的に解決します。


示例コード(Apex Connector Framework)

標準のODataアダプタでは対応できない独自のAPIと連携する場合、アーキテクトはApex Connector Frameworkの利用を検討します。このフレームワークでは、`DataSource.Provider`クラスと`DataSource.Connection`クラスを実装して、独自のデータ連携ロジックを定義します。

以下のコードは、Salesforce公式ドキュメントに基づく単純なカスタムコネクタの実装例です。架空のデータサービスからデータを取得するシナリオを想定しています。

Provider Class の実装

`DataSource.Provider`クラスは、コネクタの認証機能や基本機能を定義します。

// DataSource.Provider を実装し、カスタムコネクタの認証機能とケーパビリティを定義します。
public class MyCustomConnectorProvider extends DataSource.Provider {

    // コネクタがサポートする認証の種類を返します。
    // この例では、匿名アクセスのみをサポートしています。
    override public List<DataSource.AuthenticationCapability> getAuthenticationCapabilities() {
        List<DataSource.AuthenticationCapability> capabilities = new List<DataSource.AuthenticationCapability>();
        capabilities.add(DataSource.AuthenticationCapability.ANONYMOUS);
        return capabilities;
    }

    // コネクタがサポートする操作(ケーパビリティ)を返します。
    // この例では、基本的なクエリ(ROW_QUERY)と検索(SEARCH)をサポートしています。
    override public List<DataSource.Capability> getCapabilities() {
        List<DataSource.Capability> capabilities = new List<DataSource.Capability>();
        capabilities.add(DataSource.Capability.ROW_QUERY);
        capabilities.add(DataSource.Capability.SEARCH);
        return capabilities;
    }

    // 認証情報と外部データソース定義に基づき、Connectionインスタンスを返します。
    // 実際のデータ操作はこのConnectionクラスで行われます。
    override public DataSource.Connection getConnection(DataSource.ConnectionParams connectionParams) {
        return new MyCustomConnectorConnection(connectionParams);
    }
}

Connection Class の実装

`DataSource.Connection`クラスは、実際のデータ操作(クエリ、同期など)ロジックを実装します。

// DataSource.Connection を実装し、実際のデータクエリやスキーマ同期のロジックを定義します。
public class MyCustomConnectorConnection extends DataSource.Connection {

    private DataSource.ConnectionParams connectionInfo;

    // コンストラクタで接続情報を受け取ります。
    public MyCustomConnectorConnection(DataSource.ConnectionParams connectionInfo) {
        this.connectionInfo = connectionInfo;
    }

    // Salesforceからのクエリリクエストを処理します。
    override public DataSource.TableResult query(DataSource.QueryContext context) {
        // ここで外部システムへのHTTPコールアウトを実行します。
        // HttpRequest req = new HttpRequest();
        // req.setEndpoint('https://api.example.com/data?' + context.queryMoreToken);
        // req.setMethod('GET');
        // Http http = new Http();
        // HttpResponse res = http.send(req);
        // String responseBody = res.getBody();
        //
        // 以下のコードは、レスポンスを解析し、TableResultを構築する概念的な例です。
        
        List<Map<String, Object>> sampleData = new List<Map<String, Object>>();
        Map<String, Object> row1 = new Map<String, Object>();
        row1.put('ExternalId', 'E001');
        row1.put('DisplayName', 'Sample Record 1');
        row1.put('SomeValue__c', 123.45);
        sampleData.add(row1);

        Map<String, Object> row2 = new Map<String, Object>();
        row2.put('ExternalId', 'E002');
        row2.put('DisplayName', 'Sample Record 2');
        row2.put('SomeValue__c', 678.90);
        sampleData.add(row2);

        // クエリ結果をDataSource.TableResult形式で返します。
        // isDoneフラグは、さらに多くの結果があるかどうか(ページネーション)を示します。
        // nextStateは次のクエリに渡すトークン(例:次のページのURLなど)です。
        return DataSource.TableResult.getTableResult(true, null, context.tableSelection.table, sampleData);
    }

    // 外部システムのスキーマをSalesforceに同期させるためのロジックです。
    override public List<DataSource.Table> sync() {
        List<DataSource.Table> tables = new List<DataSource.Table>();
        
        // 外部オブジェクトの列(項目)を定義します。
        List<DataSource.Column> columns = new List<DataSource.Column>();
        columns.add(DataSource.Column.text('ExternalId', 255));
        columns.add(DataSource.Column.text('DisplayName', 255));
        columns.add(DataSource.Column.decimal('SomeValue__c', 18, 2));

        // 外部オブジェクト(テーブル)を定義し、リストに追加します。
        String tableName = 'MyExternalObject';
        tables.add(DataSource.Table.get(tableName, 'DisplayName', columns));
        
        return tables;
    }
}

⚠️ 上記のコードは、Salesforce Developerドキュメントの概念に基づいた実装例です。実際のHTTPコールアウト部分やエラーハンドリングは、対象システムのAPI仕様に合わせて詳細に実装する必要があります。


注意事項

Salesforce Connectは強力なツールですが、アーキテクトとしてその制約とトレードオフを深く理解することが不可欠です。

権限とセキュリティ(Permissions and Security)

・認証:外部データソースの認証設定は極めて重要です。Named Credential(指定ログイン情報)と組み合わせ、パスワードやAPIキーがコードや設定画面にハードコードされることを避けるべきです。OAuth 2.0フローの利用を強く推奨します。
・アクセス権:外部オブジェクトへのアクセスは、プロファイルと権限セットで制御します。通常のオブジェクトと同様に、CRUD権限(作成、参照、更新、削除)をユーザーごとに設定できます。ただし、外部システム側でのアクセス制御も別途考慮する必要があります。

API制限(API Limits)

・Callout制限:Salesforce Connectの各リクエストはSalesforceのCallout制限を消費します。1つのトランザクション内で多数の外部オブジェクトレコードにアクセスすると、ApexのCallout制限(同期100回など)に抵触する可能性があります。特に、トリガや一括処理内で外部オブジェクトをクエリする際は注意が必要です。
・外部システムのレート制限:連携先の外部システムにもAPIのレート制限が存在します。Salesforceからのアクセスが集中し、外部システムの制限を超えないような設計(キャッシュ戦略の検討など)が求められます。

パフォーマンスとデータ量(Performance and Data Volume)

・レイテンシ:全てのデータアクセスはリアルタイムのネットワーク越しのCalloutであるため、外部システムの応答速度とネットワークのレイテンシが直接ユーザーエクスペリエンスに影響します。応答が遅いシステムとの連携は、画面表示の遅延を引き起こします。
・High Data Volume:外部データソースの設定で「High Data Volume」オプションを有効にすると、パフォーマンスが最適化され、一部の制限が緩和されます。大量のデータを扱う場合は必須のオプションですが、SOSL検索や集計クエリが利用できなくなるなどのトレードオフがあります。

機能的な制約(Functional Limitations)

・リレーションシップ:外部オブジェクトは、標準/カスタムオブジェクトへの参照関係(Lookup)、および他の外部オブジェクトへの参照関係を持つことができます。標準/カスタムオブジェクトから外部オブジェクトへの間接参照関係(Indirect Lookup)も可能です。しかし、主従関係(Master-Detail)はサポートされていません。
・SOQL/SOSLの制約:`GROUP BY`、`COUNT(fieldname)`、`SUM()`などの集計関数は、外部システムがサポートしていない限り利用できません。また、複雑な`WHERE`句もサポートされない場合があります。これらはアダプタと外部システムの能力に依存します。
・レポートとダッシュボード:外部オブジェクトはレポートで利用可能ですが、パフォーマンス上の理由から、大規模なデータセットに対する複雑なレポート作成には向いていません。集計やクロスフィルタなどの機能にも制約があります。


まとめとベストプラクティス

Salesforce Connectは、データ統合戦略において「全てのデータをSalesforceにコピーする」という従来のアプローチに代わる、エレガントで強力な選択肢を提供します。アーキテクトとして、このツールをいつ、どのように使うべきかを正しく判断することが成功の鍵となります。

ベストプラクティス

  1. ユースケースを慎重に評価する

    「リアルタイム性」が本当に必要か自問してください。データの鮮度がそれほど重要でなく、複雑な変換や集計が必要な場合は、夜間バッチでデータを同期する従来型のETLアプローチの方が適している場合もあります。

  2. 標準アダプタを優先する

    連携先システムがODataをサポートしている場合、保守性や信頼性の観点から、カスタムのApex Connectorを開発するよりもODataアダプタの利用を最優先すべきです。

  3. 外部システムのパフォーマンスを考慮した設計

    ユーザーエクスペリエンスは外部システムの応答性に直結します。外部APIのパフォーマンス要件を明確にし、必要であれば外部システム側にキャッシュ層や最適化されたAPIエンドポイントの構築を依頼することも視野に入れます。

  4. ページネーションを賢く利用する

    外部オブジェクトのリストビューやクエリでは、サーバーサイドページネーション(Client-DrivenまたはServer-Driven)が重要です。一度に大量のデータを取得しようとせず、必要な分だけを効率的に取得するように外部データソースを設定します。

  5. エラーハンドリングと監視

    外部システムはいつでもダウンする可能性があります。Apexカスタムコネクタでは堅牢なエラーハンドリング(再試行ロジック、例外のログ記録など)を実装し、外部システムの稼働状況を監視する仕組みを構築することが不可欠です。

結論として、Salesforce Connectは、適切なシナリオで適用されれば、開発コストを削減し、データ管理を簡素化し、ユーザーに常に最新の情報を提供する、非常に価値のあるアーキテクチャパターンです。その能力と制約の両方を深く理解し、システム全体の設計に組み込むことが、我々アーキテクトの責務と言えるでしょう。

コメント