AWS LambdaのファンクションをJavaで書く（S3イベント処理編）


前回に引き続き、AWS LambdaがJava対応したのでその簡単なチュートリアルをしてみます。
前回はすごく簡単なサンプルでしたので今回はS3のイベントを受け取って処理を行うファンクションをJavaで実装してみます。
前回同様、作業環境はMac OSX YosemiteでIDEはEclipseベースのSTS（Spring Tool Suite）を利用しています。あと、mavenは導入済みの前提です。

#Lambdaファンクションを書く
今回はS3上の特定バケット上にオブジェクト（ファイルとか）がアップロードされたらそのイベントをトリガーにアップロードされたファイル名を出力するだけのLambdaファンクションを用意します。
まず、前回は使わなかったaws-lambda-java-eventsを使うのでpom.xmlに追加してください。

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

```

今回はこのライブラリに含まれるS3Eventという事前定義されたクラスを利用してハンドラメソッドを実装します。自分自身でPOJOオブジェクト作って頑張ってもいいのですがサポートされているイベントソースのものであれば事前定義済みのものがあるので特別な要件が無い限りこれを使うのが楽でいいと思います。


```java
package com.sample.lambda;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.events.S3Event;
import com.amazonaws.services.s3.event.S3EventNotification.S3EventNotificationRecord;

public class S3EventHandler {
	public String handler(S3Event event, Context context){
		LambdaLogger lambdaLogger = context.getLogger();
		S3EventNotificationRecord record = event.getRecords().get(0);
		lambdaLogger.log(record.getEventName()); //イベント名
		lambdaLogger.log(record.getS3().getBucket().getName()); //バケット名
		lambdaLogger.log(record.getS3().getObject().getKey()); //オブジェクトのキー（オブジェクト名）
		return record.getS3().getObject().getKey();
	}
}

```

S3EventオブジェクトからgetRecords()でS3EventNotificationRecordのListを取得するのですが今回は1件しか入っていないので最初の要素を決め打ちで取得しています。
S3EventNotificationRecordオブジェクトからはイベントの各種情報が取得できるのですが、getS3()でS3のエンティティを示すS3Entityオブジェクトを取得できます。このオブジェクトからはイベントの発生元となったバケットの情報やオブジェクトの情報が取得できるので基本的にはこれを利用していく形になります。今回はオブジェクトのキー名を取得して出力および返却しています。

#パッケージング
[前回](http://qiita.com/Keisuke69/items/fc39a2f464d14480a432)同様、以下のようなpom.xmlを用意しパッケージングします。ポイントとしては作成されるJARファイルに必要となるライブラリ群も含まれているということです。興味がある方は作成されたJARファイルを解凍して確認してみてください。

```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>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-lambda-java-events</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>



```

#Lambdaファンクションの作成とデプロイ
Lambdaファンクションを作成します。今回もRuntimeは"Java 8"とし作成したJARファイルをアップロードします。
なお、Handlerは`com.sample.lambda.S3EventHandler::handler`としています。

![Screen Shot 2015-06-16 at 4.32.16 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/26e5972c-a34f-d539-dd4b-fc8ca6a3b3f5.png "Screen Shot 2015-06-16 at 4.32.16 PM.png")

#テスト
さて、[前回](http://qiita.com/Keisuke69/items/fc39a2f464d14480a432)同様にファンクションのEdit/Test画面を開きます。今回はSample Eventとしてあらかじめ用意されている"S3 Put"を利用してテストを行います。Sample Eventから"S3 Put"を選択してInvokeしてみてください。

![Screen Shot 2015-06-16 at 4.32.34 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/db6565ca-8628-9213-5386-91c69e596369.png "Screen Shot 2015-06-16 at 4.32.34 PM.png")

画面下部には結果が出力されます。今回のSample Eventではオブジェクト名（オブジェクトのキー）が"HappyFace.jpg"となっていて、handlerのreturnでオブジェクト名をStringで返しているためExecution Resultにオブジェクト名が出力されています。

![Screen Shot 2015-06-16 at 5.16.28 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/5d917684-b2bf-a096-7ea7-0e22dbe59169.png "Screen Shot 2015-06-16 at 5.16.28 PM.png")

ちなみに画面右下に実行時のログも出力されていて、ここにはLambdaLogger.log()で出力したメッセージが出力されるのですがLambdaLogger.log()は今回のように複数呼んでも1つのログイベントとして処理されてしまいますのでご注意を。

![Screen Shot 2015-06-16 at 5.23.09 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/d11dcf94-2d12-96fe-5474-30b9f7030748.png "Screen Shot 2015-06-16 at 5.23.09 PM.png")

改行したい場合は各ログエントリ内で改行する（\nを出力）か、LambdaLoggerの代わりにSystem.out.println()でメッセージを出力してください。

#まとめ
こんな感じでLambdaがサポートしているイベントソースのイベントであれば簡単に処理ができます。今回はS3でしたがKinesisの場合はKinesisEventというものが用意されていて同様に処理できます（ただし、Kinesisの場合はRecordが複数になるのでKinesisEventRecordのListを処理することになります）。
次回はPOJOを用意してカスタムイベントを実装する例をご紹介したいと思います。