LoginSignup
15
14

More than 5 years have passed since last update.

AWS Lambda JavaでLambdaFunctionで発生した例外の処理について

Last updated at Posted at 2016-02-19

はじめに

AWS Lambdaで、呼び出し元/呼び出し先ともにJavaを使った際の例外処理についてまとめてみました。

テスト用のクラス

Lambda Functionクラス

AWS Lambdaに登録するためのクラスです。

package lambdatest;

import java.time.LocalDateTime;

import com.amazonaws.services.lambda.runtime.Context;

public class Lambda {

    public String ok(Object o, Context context) {
        context.getLogger().log("OK " + LocalDateTime.now());
        return "OK";
    }

    public String timeout(Object o, Context context) {
        try{
            Thread.sleep(TimeUnit.SECONDS.toMillis(100));
        }catch(Exception e){

        }
        context.getLogger().log("Timeout " + LocalDateTime.now());
        return "Timeout";
    }

    public String runtimeException(Object o, Context context) {
        context.getLogger().log("RuntimeException " + LocalDateTime.now());
        throw new RuntimeException("RuntimeException");
    }

    public String exception(Object o, Context context) throws Exception {
        context.getLogger().log("exception " + LocalDateTime.now());
        throw new Exception("Exception");
    }
}

Lambdaの呼び出しコード

登録したLambdaを呼び出すクライアントクラスです。

package lambdatest;

import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.lambda.AWSLambdaClient;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;

public class InvokeLambda {

    public static void main(String[] args) {
        AWSLambdaClient lambda = new AWSLambdaClient();
        lambda.setRegion(Region.getRegion(Regions.AP_NORTHEAST_1));
        InvokeRequest req = new InvokeRequest();
        req.setFunctionName("LambdaTest");
        req.setPayload("{\"hoo\":\"bar\"}");
        try {
            InvokeResult invoke = lambda.invoke(req);
            String res = new String(invoke.getPayload().array());
            System.out.println(res);
            System.out.println(invoke.getFunctionError());
            System.out.println(invoke.getStatusCode());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

呼び出し時の挙動確認

上記のテストクラスを使って、呼び出すLambdaのメソッドごとの挙動を確認した結果が以下となります。

OKのパターン

正常パターン。lambdatest.Lambda::ok を呼び出す。処理は成功して、"OK"という文字列が返って来ます。

Payload:"OK"
FunctionError:null
StatusCode:200

Timeoutのパターン

lambdatest.Lambda::timeoutを呼び出すと処理がタイムアウトする。
呼び出し元では例外は発生せず、タイムアウト時に以下のPayload,FunctionError,StatusCodeが返ってきます。

Payload:{"errorMessage":"2016-02-19T10:10:00.159Z e59b6744-d6f0-11e5-9eae-c56145704801 Task timed out after 15.00 seconds"}
FunctionError:Unhandled
StatusCode:200

RuntimeExceptionのパターン

lambdatest.Lambda::runtimeExceptionを呼び出すとRuntimeExceptionがすろーされる。
呼び出し元では例外は発生せず、タイムアウト時に以下のPayload,FunctionError,StatusCodeが返ってきます。

Payload:{"errorMessage":"RuntimeException","errorType":"java.lang.RuntimeException","stackTrace":["lambdatest.Lambda.runtimeException(Lambda.java:28)","sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)","sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)","sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)","java.lang.reflect.Method.invoke(Method.java:497)"]}
FunctionError:Unhandled
StatusCode:200

Exceptionのパターン

Payloadに入っている例外クラス名がExceptionとなっていだけで、あとはRuntimeExceptionと同じです。

LambdaのHandler設定が間違っていた時

AWS LambdaのHandler設定が誤っており、呼び出し先クラスやメソッドがない場合。
この場合でも呼び出し元では例外は発生せず、タイムアウト時に以下のPayload,FunctionError,StatusCodeが返ってきます。

Payload:{"errorMessage":"No public method named ERRORHANDLER with appropriate method signature found on class class lambdatest.Lambda"}
FunctionError:Unhandled
StatusCode:200

例外処理の方法

結論として、AWSクレデンシャル/リージョン/FunctionNameが正しければ、Lambda側で例外が発生してもクライアント側では例外がスローされないため、InvokeResultの中身を見て、エラーかどうかを判断する必要があります。
InvokeResult#getFunctionError()の戻り値がnullでない場合はエラーが発生しているとみなしてもよさそうなので、この場合はPayloadからエラー内容を取り出し、適宜メッセージを取り出してログを吐いたりリトライする形になります。

なおAWSクレデンシャル間違いの場合はcom.amazonaws.AmazonServiceException、リージョンやFunctionNameが違う場合はcom.amazonaws.services.lambda.model.ResourceNotFoundExceptionが発生するため、これは別途catchして例外処理を行う必要があります。

15
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
14