【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.