【Salesforce】DMLをサポートしないレコードを更新する
Apexでセルフサービスユーザの設定レコードをDML操作するコードを書いていると、コンパイル時にエラーが出ました。
コンパイル時のエラー
DML operation Update not allowed on List
SelfServiceUserはDML操作をサポートしないとのことですね。
どうやら、設定系のオブジェクトはDML操作できないものが結構たくさんあるみたいです。
DML 操作をサポートしない sObject
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_dml_non_dml_objects.htm
SOAP APIだと操作が出来るようです。
https://developer.salesforce.com/docs/atlas.ja-jp.api.meta/api/sforce_api_objects_selfserviceuser.htm
しかし、わざわざSOAP API用の処理を作るのは面倒ですし、Salesforce以外のリソースも必要になってしまいます。
そんなわけで、REST APIで試してみました。
https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/dome_update_fields.htm
SalesforceのApexで行えばセッションIDは簡単に取得できますから、JSONとHTTPRequestを使えば割と簡単にできます。
自分のDeveloper環境ではセルフサービスユーザを有効にしていなかったため、メールサービスのアドレスでやってみました。
List<EmailServicesAddress> recordList;
EmailServicesAddress record;
Map<String, Object> jsonMap;
Map<String, Object> recordJSONMap;
Map<String, Object> requestBodyMap;
HTTPRequest req;
HTTPResponse res;
HTTP http;
String endPoiint;
// レコードを取得する
recordList = [select Id from EmailServicesAddress];
// 1件だけ取得する
record = recordList[0];
// リクエストBodyを
requestBodyMap = new Map<String, Object>();
requestBodyMap.put('RunAsUserId', UserInfo.getUserId());
// URLを作成する
endPoiint = '';
endPoiint += URL.getSalesforceBaseUrl().toExternalForm();
endPoiint += '/services/data/v42.0/sobjects/EmailServicesAddress/' + record.Id;
// リクエストを作成する
req = new HTTPRequest();
req.setEndpoint(endPoiint);
req.setMethod('POST');
req.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());
req.setHeader('Content-Type', 'application/json');
req.setBody(JSON.serialize(requestBodyMap));
system.debug('【ログ】' + req.getBody());
// HTTPResuestを送信する
http = new HTTP();
res = http.send(req);
// 結果を表示する
system.debug('【ログ】' + res.getBody());
簡単ですね。
と思ったら、エラーが返ってきました。
[{"errorCode":"METHOD_NOT_ALLOWED","message":"HTTP Method 'POST' not allowed. Allowed are HEAD,GET,PATCH,DELETE"}
POSTするなということでした。
全然簡単ではありませんでしたね。
ちなみに、メソッドをPATCHにするとSalesforceのHTTPRequestの制約でエラーとなります。
そんなわけで、一工夫しました。
複数の操作を一括で行うREST APIを使用します。
List<EmailServicesAddress> recordList;
EmailServicesAddress record;
Map<String, Object> jsonMap;
Map<String, Object> recordJSONMap;
Map<String, Object> requestBodyMap;
HTTPRequest req;
HTTPResponse res;
HTTP http;
String endPoiint;
// レコードを取得する
recordList = [select Id from EmailServicesAddress];
// 1件だけ取得する
record = recordList[0];
system.debug(JSON.serialize(record));
// リクエスト用Mapを作成する
jsonMap = new Map<String, Object>();
jsonMap.put('RunAsUserId', UserInfo.getUserId());
// 1レコード用のJSONを作成する
recordJSONMap = new Map<String, Object>();
recordJSONMap.put('method', 'PATCH');
recordJSONMap.put('url', '/services/data/v42.0/sobjects/EmailServicesAddress/' + record.Id);
recordJSONMap.put('referenceId', record.Id);
recordJSONMap.put('body', jsonMap);
//
requestBodyMap = new Map<String, Object>();
requestBodyMap.put('allOrNone', true);
requestBodyMap.put('compositeRequest', new List<Object>{recordJSONMap});
// URLを作成する
endPoiint = '';
endPoiint += URL.getSalesforceBaseUrl().toExternalForm();
endPoiint += '/services/data/v42.0/composite/';
// リクエストを作成する
req = new HTTPRequest();
req.setEndpoint(endPoiint);
req.setMethod('POST');
req.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());
req.setHeader('Content-Type', 'application/json');
req.setBody(JSON.serialize(requestBodyMap));
system.debug('【ログ】' + req.getBody());
// HTTPResuestを送信する
http = new HTTP();
res = http.send(req);
// 結果を表示する
system.debug('【ログ】' + res.getBody());
帰ってきたメッセージです。
{"compositeResponse":[{"body":null,"httpHeaders":{},"httpStatusCode":204,"referenceId":"093N00000004KR0IAM"}]
ステータスに204が返ってきたので驚きましたが、遷移しなくて良いというステータスなんだそうです。
ともあれ、REST APIであればちゃんと操作することが出来ます。
ちなみに、同じ方法でセルフサービスユーザの更新も確認できました。
No comments.