今回はトリガ+非同期+HTTPコールアウトを組み合わせた処理について、
単発では分かるものも、組み合わせになるとどれが有線されるか曖昧になるので、検証して見ました
トリガ内でのHTTPコールアウト
トリガからHTTPのコールアウトを行う時は、トリガ内から直接コールアウトするのではなく、非同期メソッドの中で実施することが求められます。
コールアウト先URLへのアクセスを、リモートサイトのセキュリティ設定で許可するのも忘れずに。
それぞれ、ケース別に合わせて検証してみました。
ちなみに、この検証で使用しているエンドポイントはデタラメなので、実際に動作確認したい場合実在する接続先を使ってくださいね。
それではケース別に検証
ケース1:トリガから直接httpコール
トリガから直接HTTPコールアウトするように記述しました。
コード
HttpCalloutHogeTrigger.trigger
trigger HttpCalloutHogeTrigger on Account (after insert) { if(Trigger.isInsert && Trigger.isAfter){ for(Account acc : Trigger.New) { //HTTPリクエストの作成 HttpRequest req = new HttpRequest(); req.setEndpoint('★エンドポイントURL'); req.setMethod('GET'); //HTTPリクエストの送信 Http http = new Http(); HttpResponse res = http.send(req); //レスポンスチェック if (res.getStatusCode() == 200) { //成功時に実行したい処理 } else { System.debug('Callout failed: ' + res); } } } }
実行結果
トリガを有効化して、取引先を100件登録すると結果は以下のようになります。
→トリガからの直接Httpコールはサポートされていないためエラーになる
ケース2:トリガとクラスを分離して実行(@futureはつけない)
今後はコールアウト部分を別クラスに記載して、トリガからクラスメソッドを呼び出すようにしました。
コード
trigger HttpCalloutHogeTrigger on Account (after insert) {
if(Trigger.isInsert && Trigger.isAfter){
for(Account acc : Trigger.New) {
HogeHttpCallout.callouttest();
}
}
}
HogeHttpCallout.cls
public class HogeHttpCallout { public static void callouttest() { //HTTPリクエストの作成 HttpRequest req = new HttpRequest(); req.setEndpoint('★エンドポイントURL'); req.setMethod('GET'); //HTTPリクエストの送信 Http http = new Http(); HttpResponse res = http.send(req); //レスポンスチェック if (res.getStatusCode() == 200) { //コールアウト成功 } else { System.debug('Callout failed: ' + res); } } }
実行結果
→処理記述場所がApexクラスに変わっただけで、トリガプロセスの中で実施されている事には変わらないため、ケース1と同じ
ケース3:クラスに@futureアノテーションをつけて実行
今度はApexクラスに@futureアノテーションをつけて非同期で動くようにしました。
コード
HttpCalloutHogeTrigger.trigger
trigger HttpCalloutHogeTrigger on Account (after insert) { if(Trigger.isInsert && Trigger.isAfter){ for(Account acc : Trigger.New) { HogeHttpCallout.callouttest(); } } }
HogeHttpCallout.cls
public class HogeHttpCallout { //このメソッドを非同期実行するために、@futureを記述 @future public static void callouttest() { //HTTPリクエストの作成 HttpRequest req = new HttpRequest(); req.setEndpoint('★エンドポイントURL'); req.setMethod('GET'); //HTTPリクエストの送信 Http http = new Http(); HttpResponse res = http.send(req); //レスポンスチェック if (res.getStatusCode() == 200) { //コールアウト成功 } else { System.debug('Callout failed: ' + res); } } }
実行結果
→@future(callout=true)を宣言していないので、その状態でコールアウトを行うとエラー
ケース4:@futureアノテーション(callout=true)をつけて、100レコード登録
今度は@futureアノテーションにコールアウトを許可する(callout=true)をつけてみました。
登録件数は100件です。
コード
HttpCalloutHogeTrigger.trigger
trigger HttpCalloutHogeTrigger on Account (after insert) { if(Trigger.isInsert && Trigger.isAfter){ for(Account acc : Trigger.New) { HogeHttpCallout.callouttest(); } } }
HogeHttpCallout.cls
public class HogeHttpCallout {
//このメソッドを非同期実行するために、@futureを記述
@future(callout=true)
public static void callouttest() {
//HTTPリクエストの作成
HttpRequest req = new HttpRequest();
req.setEndpoint('★エンドポイントURL');
req.setMethod('GET');
//HTTPリクエストの送信
Http http = new Http();
HttpResponse res = http.send(req);
//レスポンスチェック
if (res.getStatusCode() == 200) {
//コールアウト成功
} else {
System.debug('Callout failed: ' + res);
}
}
}
実行結果
→ガバナ制限:Apex呼び出し1回につき許可される futureアノテーションを持つメソッドの最大数の50を超えている
ケース5:50個Insertして実行
コード
コードはケース4と同じです。今後はレコード50件で登録してみます。
実行結果
ガバナ制限に抵触しないので成功
まとめ
以上のように、アノテーションの付け方や呼び出される件数などで、エラー内容が変わることが分かります。
トリガと非同期とコールアウトを組み合わせたケースについのまとめは以下の通りです。
- トリガプロセス内でHTTPコールアウトはできない
- ガバナ制限により、一度に呼び出せる非同期メソッドは最大50回
- 非同期メソッド内でコールアウトする場合は@future(callout=true)宣言が必要
ただ単に正常ケースだけではなくて、エラーが起こった時のエラーメッセージ(例外)についても試験で問われるので覚えておきましょう。
コメント
trigger HttpCalloutHogeTrigger on Account (after insert) {
if(Trigger.isInsert && Trigger.isAfter){
for(Account acc : Trigger.New) {
HogeHttpCallout.callouttest();
}
}
}
public class HogeHttpCallout {
//このメソッドを非同期実行するために、@futureを記述
@future(callout=true)
public static void callouttest() {
//HTTPリクエストの作成
HttpRequest req = new HttpRequest();
req.setEndpoint(‘http://hogehoge.com/hogehoge.html’);
req.setMethod(‘GET’);
//HTTPリクエストの送信
Http http = new Http();
HttpResponse res = http.send(req);
//レスポンスチェック
if (res.getStatusCode() == 200) {
//成功時に実行したい処理
} else {
System.debug(‘Callout failed: ‘ + res);
}
}
}
HttpCalloutHogeTriggerの対象レコードのIDをHogeHttpCallout.callouttestにパスして、再度クエリにしたら、もっといいと思いますが、まあ、今回、ここにフォーカスしていない記事だし、余計なことを言ったら、申し訳ございません