AWS LambdaがJava対応したので簡単チュートリアル


既報([【AWS発表】AWS Lambdaのアップデート、イベントに応じてJavaコードを実行](http://aws.typepad.com/aws_japan/2015/06/aws-lambda-update-run-java-code-in-response-to-events.html))の通り、AWS Lambdaで利用可能な言語としてこれまでのNode.jsに加えてJavaが追加となりました。オフィシャルブログではそんなにコードのサンプルもなかったのでこちらでもう少し補足してみようかと思います。
ちなみに今回の私の作業環境はMac OSX YosemiteでIDEはEclipseベースのSTS（Spring Tool Suite）を利用しています。あと、mavenは導入済みの前提です。

#Lambdaファンクションを書く
まず、LambdaをJavaで書く用に2つのライブラリ、aws-lambda-java-coreとaws-lambda-java-eventsが新たに提供されたのでこれを使えるようにしてください。後者は不要であればなくてもいいです。今回は使いません。以下はmavenの例です。

```xml

<dependency>
	<groupId>com.amazonaws</groupId>
	<artifactId>aws-lambda-java-core</artifactId>
	<version>1.0.0</version>
</dependency>
```

まずは、シンプルに渡された数値を出力するだけのコードを用意してみます。

```java

package com.sample.lambda;

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

public class App {
	public String handler(int count, Context context){
		LambdaLogger lambdaLogger = context.getLogger();
		lambdaLogger.log("count = " + count);
		return String.valueOf(count);
	}
}
```

この例の場合、inputとして受け取る値はintの値です。あとはLambdaのloggerをContextから取得して受け取った値を単にログ出力しています。
ちなみにここではStringに変換した値をreturnしていますが、InvocationTypeがRequestResponseの場合のみこの値が呼び出し元に返されます。Eventの場合はどこにも使われません。InvocationTypeとはLambdaファンクションの呼び出し方のことでRequestResponseだと同期的に、Eventだと非同期で処理されます。

#パッケージング
ではこいつを早速Lambdaファンクション用にパッケージングしますがSTSとかEclipse使ってMavenプロジェクトとして作成していれば大した手間はありません。一応言及しておくと以下のような一般的なディレクトリ構成にします。

```
<プロジェクトディレクトリ>/pom.xml           
<プロジェクトディレクトリ>/src/main/java
```

この`<プロジェクトディレクトリ>/src/main/java`以下に先ほど作成したjavaファイルを保存します。もちろんJavaのお作法で保存するのでパッケージ名に対応したディレクトリ構成にしてください。今回の場合だと`<プロジェクトディレクトリ>/src/main/java/com/sample/lambda/App.java`になります。

pom.xmlの中身は以下のような感じになります。以下の例ではAWS SDK for Javaも入れてますが不要だったら外してください。あとは前述したLambda用のライブラリです。今回はaws-lambda-java-coreのみにしています。

```xml

<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.sample.lambda</groupId>
  <artifactId>com.sample.lambda</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>lambda-java</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-lambda-java-core</artifactId>
      <version>1.0.0</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <createDependencyReducedPom>false</createDependencyReducedPom>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

```

ここまで用意できたらターミナル等でプロジェクトディレクトリに移動して、以下のコマンドを実行します。

```shell-session

mvn package

```

コマンドじゃなくてEclipse等のIDE上から実行しても構いません。
そうすると`<プロジェクトディレクトリ>/target/`というディレクトリができてその他のファイルとともに`com.sample.lambda-0.0.1-SNAPSHOT.jar`といった名前のjarファイルができているかと思います。

#Lambdaファンクションの作成
基本的には今までと変わらないのですがランタイム（Runtime）として"Java8"を指定する必要があります。

![Screen Shot 2015-06-16 at 3.45.50 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/97792c11-bbbd-363e-e76d-41937fd34612.png "Screen Shot 2015-06-16 at 3.45.50 PM.png")

これまでとの違いですが、Java 8を選択するとインラインエディタは利用できなくなります。つまり、書いたコードは必ずコンパイルした上でZIPもしくはJARファイルにしてLambdaもしくはS3にアップロードをする必要があります。
ではここで先ほど作成したjarファイルを指定してアップロードしてしまってください。

続いてHandlerを指定します。Handlerの指定は`パッケージ.クラス名::メソッド`と指定します。今回の場合は`com.sample.lambda`というパッケージの`App`というクラスにある`handler`というメソッドなので`com.sample.lambda.App::handler`となります。

ちなみに、Javaの場合はデフォルトのメモリサイズおよびタイムアウトがそれぞれ512MBと15秒となっています（Node.JSの場合は128MB、3秒のまま）。
あと、今回の発表のタイミングで指定可能なメモリサイズの上限が1.5GBまで増えました！

#テスト
これでLambdaファンクションが作成されたので早速テスト実行してみましょう。マネージメントコンソール上のダッシュボードから作成したファンクションを選択して、"Actions"というプルダウンから"Edit/Test"を選択します。

![Screen Shot 2015-06-16 at 3.52.16 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/88871c88-8163-239b-6bb8-fcc03bdebdb5.png "Screen Shot 2015-06-16 at 3.52.16 PM.png")

次の画面のSample Eventのエリアに適当な値を入れます。Hello Worldを選択した上で中身を消して好きな値を入れるのがいいと思います。通常はJSONなんですが今回のApp.handlerはパラメータとしてintの値を受け取っているのでそれだけをベタ書きします。

![Screen Shot 2015-06-16 at 3.28.16 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/cd8313e5-bf05-108f-c004-9aa097728b06.png "Screen Shot 2015-06-16 at 3.28.16 PM.png")

そして"Invoke"をクリックするとLambdaファンクションが実行されます。
画面下部のExecution Resultのエリアに以下のようにメソッドでreturnした結果が表示されているかと思います。

![Screen Shot 2015-06-16 at 3.55.21 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/c8b48d35-da49-525f-cb86-f9f347991d6c.png "Screen Shot 2015-06-16 at 3.55.21 PM.png")

#まとめ
とりあえずこんな感じでJavaで書いたコードをLambdaで実行することができるようになったことがわかります。次はもう少し実践的な内容としてS3のイベントを受け取って処理するパターンとパラメータをJSONで渡すパターンをやってみたいと思います。