こんにちは、管理人の@Salesforce.Zです。
Salesforceの奥が深いですね。 開発においては、外部 Web Service から取得した結果に基いてセールスフォース内のレコードを作成/更新するケースが多々あります。 しかしながら、同じトランザクション内で DML(Insert/Update/Upsert/Delete)発行後にコールアウトを行なう事はでません。
今回非同期メソッドの中で、DMLとhttp コールアウトの順番について記事を起こします。 なぜなら、間違えたら、エラーになるからです。
★ 非同期メソッドの中でコールアウトエラーの解消
目次
問題
futrue methodを使い、データ登録をした。 データ登録後に、つまりDMLステートメント(CRUD)を発行後に、httpメソッドで、コールアウトを実行すると下記のエラーになります。 「You have uncommitted work pending. Please commit or rollback before calling out」
コード例
global with sharing class yourclass{ @future(callout=true) private static void followAsynJob(String requestBody){ try{ //➀DML operation Account acc = new Account(); acc.Name = 'test'; insert acc; //②call out String params = 'params'; excuteCallout(params ); }catch(DmlException e){ System.debug('The following exception has occurred: ' + e.getMessage()); } } private static Map<String, String> excuteCallout(String params){ Map<String, String> userMap = new Map<String, String>(); Map<String, Object> result; String authorizationHeader = 'Bearer {accessToken}'; Http http = new Http(); HttpRequest request = new HttpRequest(); request.setEndpoint('https://api.sample/' + params); request.setHeader('Authorization', authorizationHeader); request.setMethod('GET'); HttpResponse response = http.send(request); // Parse the JSON response if (response.getStatusCode() == 200) { } else { System.debug('リクエスト失敗' + response.getStatusCode() + ' ' + response.getStatus()); } return userMap; } }
上記のコードのように、➀がDML実行、②がcallout実行となり、これは「You have uncommitted work pending. Please commit or rollback before calling out」エラーになります。
原因は公式ドキュメントを参照してください。
対策
回避策としては、下記のサンプルコードのように、トランザクションを分けるように実装することで 後半のHTTPコールアウト後の更新処理が実行可能となります。
トランザクションを分けて実装するだが、エラーとなる順番➀と②を逆にすれば、解消できます。