Amazon API Gateway を Salesforce からコールアウトする
Amazon API Gateway を使って作成した Rest API を Salesforce からコールアウトしてみたいと思います。
Salesforce からのコールアウトのイメージを掴むには下記のエントリーもご参照ください。
[Salesforce] リード作成時にコールアウトを使ってJiraにチケットを作る
Amazon API Gateway で Rest APIを作る
API GatewayとStep Functionsを組み合わせた非同期APIが最強だった話
の記事のサンプルをベースに使わせていただきました。
サンプルではoutputが固定なので、少し改修してinputの値を表示するようにしました。
diff --git a/app.py b/app.py index 9f20415..ac0c7fb 100644 --- a/app.py +++ b/app.py @@ -12,4 +12,4 @@ def lambda_handler(event, context): seconds = int(os.environ.get("TIMER")) sleep(seconds) - return {"message": "らーめんが ゆであがりました はやく たべないと のびて しまいます"} + return {"message": f"{event['lead-name']}さんに用意した{event['aji']}らーめんが ゆであがりました はやく たべないと のびて しまいます"}
実行は次の通りです。
デプロイして1、
$ sls deploy --stage default
エンドポイントを設定して、
# Set Api Endpoint $ StartExecution=https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/<ステージ名>/ramen/start-execution $ DescribeExecution=https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/<ステージ名>/ramen/describe-execution
実行する。
# StartExecution $ executionArn=$(curl -X POST -d '{"lead-name": "進地", "aji": "みそ"}' $StartExecution | jq -r '.executionArn') # DescribeExecution $ curl -X POST -d '{"executionArn": "'$executionArn'"}' $DescribeExecution | jq
結果は、DescribeExecution
がStartExecution
の実行直後の実行だと、
% curl -X POST -d '{"executionArn": "'$executionArn'"}' $DescribeExecution | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 208 100 77 100 131 350 595 --:--:-- --:--:-- --:--:-- 945 { "input": { "lead-name": "進地", "aji": "みそ" }, "status": "RUNNING" }
しばらく待ってから再実行すると、
$ curl -X POST -d '{"executionArn": "'$executionArn'"}' $DescribeExecution | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 488 100 357 100 131 642 235 --:--:-- --:--:-- --:--:-- 877 { "input": { "lead-name": "進地", "aji": "みそ" }, "output": { "message": "進地さんに用意したみそらーめんが ゆであがりました はやく たべないと のびて しまいます" }, "status": "SUCCEEDED" }
となります。
Salesforce から Amazon API Gateway で作った Rest API をコールアウトする
それでは、先に作成したAPIをSalesforceからコールアウトしてみます。
指定ログイン情報の作成
まず、Amazon API GatewayをApexからコールアウトできるように、指定ログイン情報を作成します。
指定ログイン情報に設定する各値は次の通りです。
項目 | 設定値 |
---|---|
表示ラベル | AWS_APIGW |
名前 | AWS_APIGW |
URL | https://<発行されたAmazon API Gatewayのホスト名>.execute-api.<お使いのリージョン(ap-northeast-1など)>.amazonaws.com |
ID 種別 | 指定ユーザ |
認証プロトコル | AWS 署名バージョン 4 |
AWS アクセスキー ID2 | AWSの接続に利用するアカウント/ロールのアクセスキーID |
AWS シークレットアクセスキー2 | AWSの接続に利用するアカウント/ロールのシークレットアクセスキー |
AWS リージョン2 | お使いのリージョン(ap-northeast-1など) |
AWS サービス2 | apigateway |
他の項目 | 入力、チェックしない |
AWSに対して接続する場合は認証プロトコルに「AWS 署名バージョン 4」が用意されていますので、認証プロバイダを自前で設定する必要がなくて楽ちんです。
コールアウトの実装
それでは、SalesforceでAmazon API Gateway をコールアウトする処理を実装します。
public with sharing class APIGatewayCalloutAsync implements Queueable,Database.AllowsCallouts { private final String body; private final Integer period; public APIGatewayCalloutAsync(String body, Integer period) { this.body = body; this.period = period; } public void execute(QueueableContext context) { Http http = new Http(); HttpRequest req = new HttpRequest(); req.setEndpoint('callout:AWS_APIGW/default/ramen/describe-execution'); req.setMethod('POST'); req.setHeader('Content-Type', 'application/json'); req.setHeader('Accept', 'application/json'); req.setBody(this.body); HttpResponse res = http.send(req); CalloutResponse cres = (CalloutResponse)JSON.deserializeStrict(res.getBody(), CalloutResponse.class); if ( cres.status != 'SUCCEEDED' ) { Long startTime = DateTime.now().getTime(); Long finishTime = DateTime.now().getTime(); while ((finishTime - startTime) < (this.period * 1000)) { //sleep for this.period sec finishTime = DateTime.now().getTime(); } System.enqueueJob(this); } else { System.debug(cres.output.get('message')); } } class CalloutResponse { Map<String,String> input; Map<String,String> output; String status; } }
APIGatewayCalloutAsync は非同期にAWS_APIGW/default/ramen/describe-execution
へのコールアウトを繰り返すQueueableを実装したクラスです。コンストラクタの第二引数で与えた秒数間隔をあけて第一引数で与えたJSONをパラメータに使ってコールアウトします。
コールアウトから{"status": "SUCCEEDED"}
が返ってくるまで繰り返し、返ってきたら{"output": {"message": "メッセージ"}}
をデバッグ出力して終了します。
呼び出し側は、例えば開発者コンソールの[Debug] > [Open Execute Anonymous Window] にて次のコードを実行します。
HttpRequest req = new HttpRequest(); req.setEndpoint('callout:AWS_APIGW/default/ramen/start-execution'); req.setMethod('POST'); req.setHeader('Content-Type', 'application/json'); req.setHeader('Accept', 'application/json'); req.setBody('{"lead-name": "進地", "aji": "みそ"}'); Http http = new Http(); HttpResponse res = http.send(req); ExecutionArn arn = (ExecutionArn)JSON.deserializeStrict(res.getBody(), ExecutionArn.class); System.enqueueJob(new APIGatewayCalloutAsync('{"executionArn": "' + arn.executionArn + '"}', 10)); class ExecutionArn { String executionArn; String startDate; }
AWS_APIGW/default/ramen/start-execution
を呼び出してExecutionArn
を取得し、取得したExecutionArn
と繰り返しの間隔に10秒を指定してAPIGatewayCalloutAsyncオブジェクトをキューに追加しています。キューは10秒間隔でAPIGatewayCalloutAsync.execute()を実行し、先述の通りにoutputが返ってきたら終了します。
このサンプルの場合、最終結果として、進地さんに用意したみそらーめんが ゆであがりました はやく たべないと のびて しまいます
という文章がデバッグ出力されれば成功です。
まとめ
Amazon API Gateway で作成した Rest API エンドポイントに対して、Salesforceからコールアウトする方法について書きました。 コールアウトでJiraにチケットを作る場合と比べても圧倒的に設定がシンプルで楽であることがおわかりいただけたかと思います。
また、 Amazon API Gateway と Step Functions で構成された非同期APIの実行処理に対して、処理完了したか判断してレスポンスを受け取るためのAPI(AWS_APIGW/default/ramen/describe-execution
)を非同期で繰り返し実行する方法としてApexのQueueableインターフェースを実装する例を書いてみました。
AWS と Salesforce のインテグレーションの一形式として活用を検討してみてください。