Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

はじめに

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して例外処理を行う必要があります。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした