LoginSignup
17
12

More than 3 years have passed since last update.

AWS Lambda + Java で Hello World

Posted at

概要

  • AWS (Amazon Web Services) Lambda で Java によるシンプルな Hello World を動かす
  • ハンドラの実装には AWS Lambda Java コアライブラリ (aws-lambda-java-core) に用意されている定義済みインターフェイス RequestHandler を使用する
  • JAR ファイルの生成には Maven を使用する

ソースコード

ファイル一覧

HelloWorld.java と pom.xml のみのシンプルな構成。

├── pom.xml
└── src
    └── main
        └── java
            └── com
                └── example
                    └── HelloWorld.java

HelloWorld.java

汎用的な JSON 入力データを処理できるように入力データを Map オブジェクトで受け取る。
出力も同じく Map オブジェクトで返す。

package com.example;

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

import java.util.HashMap;
import java.util.Map;

public class HelloWorld implements RequestHandler<Map<String, Object>, Map<String, Object>> {

  /**
   * AWS Lambda のハンドラーメソッドです。
   *
   * @param input   入力データ
   * @param context AWS Lambda Context オブジェクト
   * @return 出力データ
   */
  @Override
  public Map<String, Object> handleRequest(Map<String, Object> input, Context context) {
    Map<String, Object> output = new HashMap<>();
    output.put("foo", "Hello, world");
    output.put("bar", "Goodbye, world");
    output.put("input", input); // 入力情報を見たいので出力に含める
    output.put("context", context); // コンテキスト情報を見たいので出力に含める
    return output;
  }
}

Maven 用ビルド設定ファイル pom.xml

  • AWS Lambda でサポートされている Java のバージョン 1.8 に合わせる
  • AWS Lambda 用ライブラリ aws-lambda-java-core を導入する
  • ライブラリも含めた JAR ファイルを生成するため maven-shade-plugin を導入する

IDE なしで Maven を使用した .jar デプロイパッケージの作成 (Java) - AWS Lambda

「dependencies」セクションで、groupId (com.amazonaws) は Maven 中央レポジトリの Maven アーティファクト用の Amazon AWS グループ ID です。artifactId (aws-lambda-java-core) は、RequestHandler、RequestStreamHandler の定義、および Java アプリケーションで使用する Context AWS Lambda インターフェイスを提供する AWS Lambda のコアライブラリです。ビルド時に、Maven はこれらの依存関係を解決します。
プラグインセクションでは、Apache maven-shade-plugin は、Maven がビルドプロセス中にダウンロードして使用するプラグインです。このプラグインは、デプロイパッケージであるスタンドアロン .jar (.zip ファイル) を作成するために、jar のパッケージ化に使用されます。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>lambda-hello-world</artifactId>
  <packaging>jar</packaging>
  <version>1.0</version>
  <name>lambda-hello-world</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-lambda-java-core</artifactId>
      <version>1.2.0</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.1</version>
        <configuration>
          <createDependencyReducedPom>false</createDependencyReducedPom>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

</project>

JAR ファイルを作る

mvn package コマンドで JAR ファイルを生成。

$ mvn package
$ ls -l target/*.jar
-rw-r--r--@ 1 foo  staff  10047  8 25 10:08 target/lambda-hello-world-1.0.jar
-rw-r--r--@ 1 foo  staff   2692  8 25 10:08 target/original-lambda-hello-world-1.0.jar

AWS Lambda にデプロイするのは lambda-hello-world-1.0.jar ファイルとなる。
jar コマンドで含まれているファイル一覧を確認できる。

$ jar --list --file target/lambda-hello-world-1.0.jar 
META-INF/
META-INF/MANIFEST.MF
com/
com/example/
com/example/HelloWorld.class
META-INF/maven/
META-INF/maven/com.example/
META-INF/maven/com.example/lambda-hello-world/
META-INF/maven/com.example/lambda-hello-world/pom.xml
META-INF/maven/com.example/lambda-hello-world/pom.properties
com/amazonaws/
com/amazonaws/services/
com/amazonaws/services/lambda/
com/amazonaws/services/lambda/runtime/
com/amazonaws/services/lambda/runtime/LambdaRuntime$1.class
com/amazonaws/services/lambda/runtime/CognitoIdentity.class
com/amazonaws/services/lambda/runtime/LambdaRuntime.class
com/amazonaws/services/lambda/runtime/ClientContext.class
com/amazonaws/services/lambda/runtime/Client.class
com/amazonaws/services/lambda/runtime/Context.class
com/amazonaws/services/lambda/runtime/LambdaRuntimeInternal.class
com/amazonaws/services/lambda/runtime/LambdaLogger.class
com/amazonaws/services/lambda/runtime/RequestHandler.class
com/amazonaws/services/lambda/runtime/RequestStreamHandler.class
META-INF/maven/com.amazonaws/
META-INF/maven/com.amazonaws/aws-lambda-java-core/
META-INF/maven/com.amazonaws/aws-lambda-java-core/pom.xml
META-INF/maven/com.amazonaws/aws-lambda-java-core/pom.properties

Lambda 関数の作成

Lambda Management Console から Lambda 関数を作成する。

「一から作成」を選択。

aws-lambda-java-1.png

「基本的な情報」を入力する。
関数名: 任意の名前
ランタイム: Java 8
実行ロール: 基本的な Lambda アクセス権限で新しいロールを作成

aws-lambda-java-2.png

「Designer」では特に何もしない。

aws-lambda-java-3.png

「関数コード」を入力する。
コード エントリ タイプ: .zip または jar ファイルをアップロード
ランタイム: Java 8
ハンドラ: com.example.HelloWorld::handleRequest

「アップロード」をクリックして生成した JAR ファイル lambda-hello-world-1.0.jar をアップロードして、右上の「保存」をクリックする。

aws-lambda-java-4.png

ページ右上の「テスト」をクリックして、新しいテストイベントを作成する。
イベントテンプレート: Hello World
イベント名: 任意の名前
入力データとなる JSON は任意のものに変更する (あるいはデフォルトのまま)。

aws-lambda-java-5.png

ページ右上の「テスト」をクリックすると、テストを実行できる。結果が表示される。

aws-lambda-java-6.png

出力結果の例。

{
  "input": {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
  },
  "bar": "Goodbye, world",
  "foo": "Hello, world",
  "context": {
    "awsRequestId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "logGroupName": "/aws/lambda/myJavaHelloWorld",
    "logStreamName": "2019/08/25/[$LATEST]XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "functionName": "myJavaHelloWorld",
    "functionVersion": "$LATEST",
    "invokedFunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:myJavaHelloWorld",
    "logger": {},
    "identity": {
      "identityId": "",
      "identityPoolId": ""
    },
    "remainingTimeInMillis": 14814,
    "memoryLimitInMB": 512
  }
}

ハンドラについて

  • ハンドラの実装方法は大きく分けて2パターンある
    • 任意の名前とパラメータを使用して独自のハンドラーメソッドを記述する
    • 定義済みインターフェイス (RequestStreamHandler または RequestHandler) を使用する
  • 両者とも入出力のインターフェースは同じ
    • ハンドラには引数で入力データと Context オブジェクトが渡される

RequestHandler インターフェース

ハンドラ作成用に事前定義されているインターフェイスの利用 (Java) - AWS Lambda

任意の名前とパラメータを使用して独自のハンドラーメソッドを記述する代わりに、AWS Lambda Java コアライブラリ (aws-lambda-java-core) に用意されている定義済みインターフェイスのいずれかを使用して、Lambda 関数ハンドラーを作成することもできます。

いずれかの定義済みインターフェイス (RequestStreamHandler または RequestHandler) を実装し、インターフェイスに用意された handleRequest メソッドを実装できます。標準の Java の型を使用するか、ハンドラーの入出力(AWS Lambda が自動的に入出力をシリアル化して、データ型に一致させる)用のカスタム POJO 型を使用するかに応じて、これらのインターフェイスの 1 つを実装します。または Stream 型を使用してシリアル化をカスタマイズします。

javadoc による公式ドキュメントが見つからなかったので、GitHub にあるソースコードを参考にする。

aws-lambda-java-libs/RequestHandler.java at master · aws/aws-lambda-java-libs · GitHub

/**
 * 
 * Lambda request handlers implement AWS Lambda Function application logic using plain old java objects 
 * as input and output.
 *
 * @param <I> The input parameter type
 * @param <O> The output parameter type
 */
public interface RequestHandler<I, O> {
    /**
     * Handles a Lambda Function request
     * @param input The Lambda Function input
     * @param context The Lambda execution environment context object.
     * @return The Lambda Function output
     */
    public O handleRequest(I input, Context context);
}

入力データ

Java の AWS Lambda 関数ハンドラー - AWS Lambda

inputType – ハンドラーの最初のパラメータはハンドラーへの入力です。このパラメータには、イベントデータ (イベントソースによって発行される) またはユーザーが提供するカスタム入力 (文字列やカスタムデータオブジェクトなど) を指定できます。AWS Lambda がこのハンドラーを正常に呼び出せるようにするには、関数は、input パラメータのデータ型にシリアル化できる入力データとともに呼び出す必要があります。

ハンドラーの入出力タイプ (Java) - AWS Lambda

AWS Lambda は、ハンドラーの次の入出力タイプをサポートします。
・Java のシンプルな型(AWS Lambda は、文字列型、整数型、ブール型、マップ型、およびリスト型をサポートします)
・POJO (Plain Old Java Object) 型
・ストリーム型(POJO を使用しない場合、または Lambda のシリアル化のアプローチがニーズに合わない場合は、バイトストリーム実装を使用できます)。詳細については、「例: ハンドラーの入出力にストリームを使用する (Java)」を参照してください。

Context オブジェクト

Java の AWS Lambda Context オブジェクト - AWS Lambda

Lambda で関数が実行されると、コンテキストオブジェクトはハンドラに渡されます。このオブジェクトは、呼び出し、関数、および実行関数に関する情報を示すメソッドおよびプロパティを提供します。

aws-lambda-java-libs/Context.java at master · aws/aws-lambda-java-libs · GitHub

The context object allows you to access useful information available within the Lambda execution environment

戻り値について

Java の AWS Lambda 関数ハンドラー - AWS Lambda

outputType – Lambda 関数を同期的に呼び出す (RequestResponse 呼び出しタイプを使用) 場合は、サポートされているいずれかのデータ型を使用して関数の出力を返すことができます。たとえば、Lambda 関数をモバイルアプリケーションのバックエンドとして使用する場合、これを同期的に呼び出しています。出力データ型は JSON にシリアル化されます。
Lambda 関数を非同期的に呼び出す(Event 呼び出しタイプを使用)計画の場合、outputType は void である必要があります。たとえば、Amazon S3 や Amazon SNS などのイベントソースとともに AWS Lambda を使用する場合、これらのイベントソースは Event 呼び出しタイプを使用して Lambda 関数を呼び出します。

参考資料

17
12
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
17
12