この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

サンプルの DataSource.Connection クラスの作成

最初に、DataSource.Connection クラスを作成して、Salesforce が外部システムのスキーマを取得したり、外部データのクエリや検索を処理できるようにしたりします。
1global class SampleDataSourceConnection
2    extends DataSource.Connection {
3    global SampleDataSourceConnection(DataSource.ConnectionParams
4        connectionParams) {
5    }
6// Add implementation of abstract methods
7// ...
DataSource.Connection クラスには次のメソッドがあります。

sync

sync() メソッドは、システム管理者が外部データソースの詳細ページで [検証して同期] ボタンをクリックしたときに呼び出されます。このメソッドは、外部システムの構造的なメタデータを説明する情報を返します。

DataSource.Connection クラスの sync メソッドを変更しても、外部オブジェクトが自動的に再同期されることはありません。

メモ

1// ...
2    override global List<DataSource.Table> sync() {
3        List<DataSource.Table> tables =
4            new List<DataSource.Table>();
5        List<DataSource.Column> columns;
6        columns = new List<DataSource.Column>();
7        columns.add(DataSource.Column.text('Name', 255));
8        columns.add(DataSource.Column.text('ExternalId', 255));
9        columns.add(DataSource.Column.url('DisplayUrl'));
10        tables.add(DataSource.Table.get('Sample', 'Title',
11            columns));
12        return tables;
13    }
14// ...

query

query メソッドは、外部オブジェクトで SOQL クエリが実行されたときに呼び出されます。SOQL クエリは、Salesforce でユーザーが外部オブジェクトのリストビューまたは詳細ページを開いたときに自動的に生成され実行されます。DataSource.QueryContext は常に 1 つのテーブルのみを対象とします。

このサンプルのカスタムアダプターは、DataSource.QueryUtils クラスでヘルパーメソッドを使用して、SOQL クエリの WHERE および ORDER BY 句を基に結果の絞り込みや並べ替えを行います。

DataSource.QueryUtils クラスとそのヘルパーメソッドは、Salesforce 組織内でローカルにクエリ結果を処理できます。このクラスは、初期テスト用の Salesforce Connect カスタムアダプターの開発を簡略化し、利便性を向上することを目的として提供されます。ただし、DataSource.QueryUtils クラスとそのメソッドは、コールアウトを使用して外部システムからデータを取得する本番環境での使用はサポートされていません。クエリ結果を Salesforce に送信する前に、外部システムで絞り込みと並べ替えを完了してください。可能であれば、サーバー駆動ページングを使用するか、別の技法を使用してクエリの LIMIT および OFFSET 句に従って外部システムに適切なデータサブセットを判定させてください。

1// ...
2    override global DataSource.TableResult query(
3        DataSource.QueryContext context) {
4        if (context.tableSelection.columnsSelected.size() == 1 &&
5            context.tableSelection.columnsSelected.get(0).aggregation ==
6                DataSource.QueryAggregation.COUNT) {
7                List<Map<String,Object>> rows = getRows(context);
8                List<Map<String,Object>> response =
9                    DataSource.QueryUtils.filter(context, getRows(context));
10                List<Map<String, Object>> countResponse =
11                    new List<Map<String, Object>>();
12                Map<String, Object> countRow =
13                    new Map<String, Object>();
14                countRow.put(
15                    context.tableSelection.columnsSelected.get(0).columnName,
16                    response.size());
17                countResponse.add(countRow);
18                return DataSource.TableResult.get(context,
19                    countResponse);
20        } else {
21            List<Map<String,Object>> filteredRows =
22                DataSource.QueryUtils.filter(context, getRows(context));
23            List<Map<String,Object>> sortedRows =
24                DataSource.QueryUtils.sort(context, filteredRows);
25            List<Map<String,Object>> limitedRows =
26                DataSource.QueryUtils.applyLimitAndOffset(context,
27                    sortedRows);
28            return DataSource.TableResult.get(context, limitedRows);
29        }
30    }
31// ...

search

search メソッドは、外部オブジェクトの SOSL クエリによって呼び出されるか、外部オブジェクトも検索する Salesforce グローバル検索をユーザーが実行したときに呼び出されます。DataSource.SearchContext は複数のオブジェクトに対する統合検索が可能なため、複数のテーブルを選択できます。ただし、次の例では、カスタムアダプターが 1 つのテーブルしか認識していません。

1// ...
2    override global List<DataSource.TableResult> search(
3            DataSource.SearchContext context) {
4        List<DataSource.TableResult> results =
5            new List<DataSource.TableResult>();
6        for (DataSource.TableSelection tableSelection :
7            context.tableSelections) {
8            results.add(DataSource.TableResult.get(tableSelection,
9                getRows(context)));
10        }
11        return results;
12    }
13// ...
getRows ヘルパーメソッドを次に示します。検索のサンプルでは、このメソッドをコールして、外部システムから行の値を取得します。getRows メソッドは、他のヘルパーメソッドを使用します。
  • makeGetCallout は、外部システムにコールアウトを実行します。
  • foundRow は、コールアウトの結果の値に基づいて行に値を入力します。foundRow メソッドは、項目名や項目値の変更など、返された項目値に変更を行うために使用されます。

このスニペットに上記のメソッドは含まれませんが、「Connection クラス」に詳細な例が記載されています。通常、結果セットを縮小するために SearchContext または QueryContext の検索条件が使用されますが、この例では簡易化のため、コンテキストオブジェクトは使用していません。

1// ...
2    // Helper method to get record values from the external system for the Sample table.
3    private List<Map<String, Object>> getRows () {
4        // Get row field values for the Sample table from the external system via a callout.
5        HttpResponse response = makeGetCallout();
6        // Parse the JSON response and populate the rows.
7        Map<String, Object> m = (Map<String, Object>)JSON.deserializeUntyped(
8                response.getBody());
9        Map<String, Object> error = (Map<String, Object>)m.get('error');
10        if (error != null) {
11            throwException(string.valueOf(error.get('message')));
12        }
13        List<Map<String,Object>> rows = new List<Map<String,Object>>();
14        List<Object> jsonRows = (List<Object>)m.get('value');
15        if (jsonRows == null) {
16            rows.add(foundRow(m));
17        } else {
18            for (Object jsonRow : jsonRows) {
19                Map<String,Object> row = (Map<String,Object>)jsonRow;
20                rows.add(foundRow(row));
21            }
22        }
23        return rows;
24    }
25// ...

upsertRows

upsertRows メソッドは、外部オブジェクトレコードが作成または更新されるときに呼び出されます。外部オブジェクトレコードは、Salesforce ユーザーインターフェースまたは DML を使用して作成または更新できます。次の例は、upsertRows メソッドのサンプル実装を示しています。この例では、渡された UpsertContext を使用してどのテーブルが選択されたかを判断し、選択されたテーブルの名前が Sample の場合にのみ更新/挿入を実行します。更新/挿入操作は、新しいレコードの挿入と既存のレコードの更新のいずれかに分けられます。これらの操作は、コールアウトを使用して外部システムで実行されます。コールアウト応答から取得した結果を基に DataSource.UpsertResult の配列に値が入力されます。コールアウトは行ごとに実行されるため、次の例では Apex のコールアウト数の制限に達する可能性があります。

1// ...
2    global override List<DataSource.UpsertResult> upsertRows(DataSource.UpsertContext 
3            context) {
4       if (context.tableSelected == 'Sample') {
5           List<DataSource.UpsertResult> results = new List<DataSource.UpsertResult>();
6           List<Map<String, Object>> rows = context.rows;
7           
8           for (Map<String, Object> row : rows){
9              // Make a callout to insert or update records in the external system.
10              HttpResponse response;
11              // Determine whether to insert or update a record.
12              if (row.get('ExternalId') == null){
13                 // Send a POST HTTP request to insert new external record.
14                 // Make an Apex callout and get HttpResponse.
15                 response = makePostCallout(
16                     '{"name":"' + row.get('Name') + '","ExternalId":"' + 
17                     row.get('ExternalId') + '"');
18              }
19              else {
20                 // Send a PUT HTTP request to update an existing external record.
21                 // Make an Apex callout and get HttpResponse.
22                 response = makePutCallout(
23                     '{"name":"' + row.get('Name') + '","ExternalId":"' + 
24                     row.get('ExternalId') + '"',
25                     String.valueOf(row.get('ExternalId')));
26              }
27         
28              // Check the returned response.
29              // Deserialize the response.
30              Map<String, Object> m = (Map<String, Object>)JSON.deserializeUntyped(
31                      response.getBody());
32              if (response.getStatusCode() == 200){
33                  results.add(DataSource.UpsertResult.success(
34                          String.valueOf(m.get('id'))));
35              } 
36              else {
37                 results.add(DataSource.UpsertResult.failure(
38                         String.valueOf(m.get('id')), 
39                         'The callout resulted in an error: ' + 
40                         response.getStatusCode()));
41              }
42           } 
43           return results;
44       } 
45       return null;
46    }
47// ...

deleteRows

deleteRows メソッドは、外部オブジェクトレコードが削除されるときに呼び出されます。外部オブジェクトレコードは、Salesforce ユーザーインターフェースまたは DML を使用して削除できます。次の例は、deleteRows メソッドのサンプル実装を示しています。この例では、渡された DeleteContext を使用してどのテーブルが選択されたかを判断し、選択されたテーブルの名前が Sample の場合にのみ削除を実行します。削除は、各外部 ID のコールアウトを使用して外部システムで実行されます。コールアウト応答から取得した結果を基に DataSource.DeleteResult の配列に値が入力されます。コールアウトは ID ごとに実行されるため、次の例では Apex のコールアウト数の制限に達する可能性があります。

1// ...
2    global override List<DataSource.DeleteResult> deleteRows(DataSource.DeleteContext 
3            context) {
4       if (context.tableSelected == 'Sample'){
5           List<DataSource.DeleteResult> results = new List<DataSource.DeleteResult>();
6           for (String externalId : context.externalIds){
7              HttpResponse response = makeDeleteCallout(externalId);
8              if (response.getStatusCode() == 200){
9                 results.add(DataSource.DeleteResult.success(externalId));
10              } 
11              else {
12                 results.add(DataSource.DeleteResult.failure(externalId, 
13                         'Callout delete error:' 
14                         + response.getBody()));
15              }
16           }
17           return results;
18       }
19       return null;
20     }
21// ...