[Java] AWS Lambda + API gateway + S3でjsonファイルをいじるだけ（１）

# やりたいこと
自分のS3バケット上にjsonファイルを作ったり、中身を書き換えたりできるapiをlambdaとapi gatewayつかって作る予定です！！言語はjava11です！！！
**といっても今回はlambda動かすところまで。**

~~s3とか~~api gateway周りは[次回](https://qiita.com/regaeve/items/23ba1a883a87adf92365)(~~あるといいな~~あった)

# 環境
- windows 10
- java11
- gradle
- intelij idea community

# リージョンについて
僕の場合、lmabda、api gatewayはオハイオ(us-east-2)で作成しました。
場所は多分どこでもよいと思いますが、**両方とも揃えないと連携できない**気がします。
S3はリージョン指定できないので気にする必要ないです。

![Inkedスクリーンショット 2021-08-12 104325_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/84bea0f3-49cd-e8dd-59fd-6c8c86a452af.jpeg)


# lambdaにコードをアップロードして動かすまで

## lambda関数を作る 
1. AWSコンソールからサービス⇒コンピューティングサービス⇒lambdaを選択
(お気に入りにしとくと良いかも)![スクリーンショット 2021-08-12 101453.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/dcaba8ee-4b10-f565-beb7-37af755e55d9.png)

1. 関数の作成を選択![スクリーンショット 2021-08-12 101328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/d138d814-1585-c26f-d6c2-0b75d8e1bcf2.png)

1. **一から作成、関数名はgetJsonFromS3、ランタイムはjava11**、他はいじらずに作成します。（後から撮影したのでスクショでは怒られてます。。）![スクリーンショット 2021-08-12 103110.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/118f2ce6-7726-eab8-347e-e78eccae0a0e.png)

1. こんな感じになったら完成![スクリーンショット 2021-08-12 103501.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/eb16e7b3-81a0-464d-55e5-3df591ecd604.png)

1. テストのタブ⇒テスト（オレンジ色のボタン）でテスト実行 ![スクリーンショット 2021-08-12 105111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/6168dc6c-55eb-79c2-633f-5a90f209fab2.png)

1. 動いたら多分OK!!、詳細を見るとHello from Lambda!!と来ているはずです。![スクリーンショット 2021-08-12 105301.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/a48814c7-920d-182e-9ae1-1ef1f705acfa.png)

## コードを書く

とりあえずeventを返してほしい。
公式を参考にした結果下記のようになりました。
クラス名はGetEventとしました。

```Java:GetEvent.class
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import java.util.Map;

public class GetEvent implements RequestHandler<Map<String, String>, String> {
    @Override
    public String handleRequest(Map<String, String> event, Context context) {
            
            //eventを返すだけ
            return event.toString();
    }
}
```

## build.gradleを書く
gradleを使ってビルドします。

```gradle:build.gradle
plugins{
    id 'java'
}

repositories {
    mavenCentral()
}

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

dependencies {
    implementation 'com.amazonaws:aws-java-sdk-core:1.12.32'
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.1'
    implementation 'com.amazonaws:aws-lambda-java-events:3.9.0'
}

task buildZip(type: Zip) {
    from compileJava
    from processResources
    into('lib') {
        from configurations.runtimeClasspath
    }
}

build.dependsOn buildZip
```

追記2021/08/12
古すぎたのでバージョンを書き換えました。

この設定でビルドしてdistributionsファイルにzipファイルが出来上がると思います。

(intelij ideaで開発したので、他の場合だと記述が違うかもしれません。
)
(出来上がってくれ。。)

## Lambdaにアップロードする
distributionsファイルに出来上がったzipをlambdaにアップロードします。


アップロードはlambdaのコードタブから⇒アップロード元⇒.zipまたは.jarファイルで行います。

(S3からやってもいいと思います。)
(そもそもこのプロセスを自動化できるっぽい。。)
![スクリーンショット 2021-08-12 115234.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/cc3751d1-6984-fceb-a5e8-43f42a626a8b.png)

## Lambdaを動かしてみよう
このままでは動きません。

lambdaのコードのタブから下の方にある**ランタイム設定**へ移動
編集ボタンから、ハンドラを変更する必要があります。
![スクリーンショット 2021-08-12 120756.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/8445b503-ec40-027d-660a-9d9fbd7f1249.png)

デフォルトだと
`example.Hello::handleRequest`
となっていると思います。これは

`パッケージ名.クラス名::関数名`
のような対応関係になっています。
僕の場合は`パッケージなし`、クラス名は`GetEvent`、関数名は`handleRequest`なので

`GetEvent::handleRequest`
となります。

![スクリーンショット 2021-08-12 122357.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/fd4c8db5-39a2-8962-fb97-67147e9cf7c2.png)


**設定したらテストを実行だ！！**
デフォルトだとテンプレートhello-worldがeventに渡されるはずです。
![スクリーンショット 2021-08-12 133402.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/e9ea3411-c394-3add-7fa4-437e622f0947.png)


テスト実行するとそのまま表示されます。
![スクリーンショット 2021-08-12 133426.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/664d86dc-eb60-1714-e914-565acfa5e3ef.png)

## 入れ子jsonを受け取れるようにする

```json:入れ子.json
{
   "key1":"value1",
   "key2":{"Key3":"value2"}
}
```

こういうのを`event`で受け取りたいとき
このまま入れ子になっているjsonを入れるとエラーになります。
これは`event`を`Map<String,String>型`として受け取っているためです。

![スクリーンショット 2021-08-12 134804.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/104b59bc-8408-8a9d-fc8a-611649e2401b.png)

`event`を`Map<String><Object>型`とすることで受け取ることが可能になります。
受け取り方としては

```java:GetEvent.class
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import java.util.Map;

public class GetEvent implements RequestHandler<Map<String, Object>, String> {
    @Override
    public String handleRequest(Map<String, Object> event, Context context) {

            //各々キャストして取得、決め打ち
            String text = (String) event.get("key1");
            Map<String,String> innerText = (Map<String, String>) event.get("key2");

            return text + innerText.toString();
        }
}
```

(もっと賢い方法ありそうですが。。。わからん。。)
で、ビルドして、アップロードして、もう一回テストすると。

![スクリーンショット 2021-08-12 141721.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240124/60a91ed7-f213-0c58-3faa-2f8592dec81a.png)

はい！受け取れました！！
~~key1は？？？仕様変わってんじゃねーーか！！！！~~

## 一旦終わり

これJsonでっかくなったらやばそう。。。
Json周りはちゃんとした方法POJO?Gson??があるらしいですがよくわかってないので本シリーズは**アホアホコード**で今後も頑張ります。

とりあえずここまででlambdaは動くようになった。
[次回](https://qiita.com/regaeve/items/23ba1a883a87adf92365)はapigateway ~~とs3をやる。~~