Serverless Framework/AWS/Javaで実装する際の注意点。
テンプレートが生成するコードそのままではAPI GatewayとLambdaが連動せず、動きません!!
例えば下記コマンドでプロジェクトを生成する。
sls create --template aws-java-maven --path serverless
すると以下のJavaファイルが作成される。
package hello;
import java.io.IOException;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
public class Handler implements RequestHandler<Request, Response> {
@Override
public Response handleRequest(Request input, Context context) {
return new Response("Go Serverless v1.0! Your function executed successfully!", input);
}
}
しかしAPI Gatewayを通してこのメソッドが実行される場合、これでは動作しない。なぜなら次のようなJSONが渡されてくるから(一部改変)。
{
"httpMethod" : "POST",
"requestContext" : {
"httpMethod" : "POST",
"accountId" : "*******",
"apiId" : "*******",
"resourceId" : "******",
"identity" : {
"userAgent" : "Apache-HttpClient\/4.5.x (Java\/1.8.0_112)",
"userArn" : "arn:aws:iam::******:user\/****",
"caller" : "***************",
"cognitoAuthenticationProvider" : null,
"cognitoIdentityId" : null,
"accessKey" : "******************",
"accountId" : "*****************",
"sourceIp" : "test-invoke-source-ip",
"apiKey" : "test-invoke-api-key",
"cognitoAuthenticationType" : null,
"cognitoIdentityPoolId" : null,
"user" : "*******************"
},
"requestId" : "test-invoke-request",
"stage" : "test-invoke-stage",
"resourcePath" : "\/hello"
},
"resource" : "\/hello",
"pathParameters" : null,
"isBase64Encoded" : false,
"headers" : null,
"path" : "\/hello",
"stageVariables" : null,
"queryStringParameters" : null,
"body" : "{\n \"key1\": \"hoge\",\n \"key2\": 120\n}"
}
本当に欲しいのは、最後の body
プロパティの部分。
ここを抽出するようなプログラムを書く必要があるということ。
リクエストだけでなく、レスポンスもこのままでは動かない。
レスポンスとなるオブジェクトは statusCode
、headers
、body
の3つのプロパティが必要らしい。
この辺りに対処する一つの解をサンプルとして提供しておく。aws-serverless-java-sample
(2018.6.24修正)
AWS SDKに、これに対応する解があったので書き直します。
AWSからaws-lambda-java-eventsというライブラリが提供されていて、Lambdaをいろんなサービスと接続した時のリクエストとレスポンスの型が定義されています。
API Gatewayと接続している際に渡されてくるリクエストとレスポンスの型は次の通りです。
bodyはString型だったりするので、JSONのencode/decodeの手間は残りますが、それでも随分コーディングしやすくなるはずです。