LoginSignup
0
1

More than 3 years have passed since last update.

Java Lambda の入出力型を試してみた〜POJO 編〜

Last updated at Posted at 2020-10-02

Java Lambda の入出力の型には、いろんなパターンが使えます。

  • Map 方式
  • POJO 方式
  • InputStream/OutputStream 方式

公式ドキュメントでは ここ に書かれています。

Map 編 では、Map 型を使用して JSON を扱う方法を紹介しました。

Map 方式のコードをみてみると、Object 型から String/Integer/Long 型などへのキャストが多数現れます。

public class MapFunction implements RequestHandler<Map<String, Object>, Map<String, Object>> {
    @Override
    public Map<String, Object> handleRequest(Map<String, Object> event, Context context) {
        String name = (String) event.get("name");
        System.out.println(name); // orange juice

        Integer price = (Integer) event.get("price");
        System.out.println(price); // 1000

        Long releaseDate = (Long) event.get("releaseDate");
        System.out.println(releaseDate); // 1601606387939
...

コードが汚いだけでなく、型が変更された場合にコンパイル時に引っかからず、実行時に ClassCastException が出てしまうかもしれません。

そこで、POJO 方式です。

まずは、Map の代わりとなる POJO クラスを作ります。Size クラスは内部クラスにしていますが、普通のクラスにしてもいいですね。

import java.util.List;

public class Product {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private Integer price;

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    private Long releaseDate;

    public Long getReleaseDate() {
        return releaseDate;
    }

    public void setReleaseDate(Long releaseDate) {
        this.releaseDate = releaseDate;
    }

    private Double rate;

    public Double getRate() {
        return rate;
    }

    public void setRate(Double rate) {
        this.rate = rate;
    }

    private List<String> rawMaterial;

    public List<String> getRawMaterial() {
        return rawMaterial;
    }

    public void setRawMaterial(List<String> rawMaterial) {
        this.rawMaterial = rawMaterial;
    }

    private Size size;

    public Size getSize() {
        return size;
    }

    public void setSize(Size size) {
        this.size = size;
    }

    public static class Size {
        private Integer height;

        public Integer getHeight() {
            return height;
        }

        public void setHeight(Integer height) {
            this.height = height;
        }

        private Integer width;

        public Integer getWidth() {
            return width;
        }

        public void setWidth(Integer width) {
            this.width = width;
        }

        private Integer depth;

        public Integer getDepth() {
            return depth;
        }

        public void setDepth(Integer depth) {
            this.depth = depth;
        }
    }
}

Lambda 関数のハンドラでは、このクラスを入出力の型として使います。

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

import java.util.Arrays;
import java.util.List;

public class PojoFunction implements RequestHandler<Product, Product> {
    @Override
    public Product handleRequest(Product product, Context context) {
        String name = product.getName();
        System.out.println(name); // orange juice

        Integer price = product.getPrice();
        System.out.println(price); // 1000

        Long releaseDate = product.getReleaseDate();
        System.out.println(releaseDate); // 1601606387939

        Double rate = product.getRate();
        System.out.println(rate); // 4.5

        List<String> rawMaterial = product.getRawMaterial();
        System.out.println(rawMaterial); // [orange, fragrance]

        Product.Size size = product.getSize();
        Integer height = size.getHeight();
        System.out.println(height); // 10

        Integer width = size.getWidth();
        System.out.println(width); // 20

        Integer depth = size.getDepth();
        System.out.println(depth); // 30

        Product response = new Product();
        response.setName("coffee");
        response.setPrice(Integer.valueOf(500));
        response.setReleaseDate(System.currentTimeMillis());
        response.setRate(Double.valueOf(4.2));
        response.setRawMaterial(Arrays.asList("coffee", "sugar"));

        Product.Size responseSize = new Product.Size();
        responseSize.setHeight(Integer.valueOf(100));
        responseSize.setWidth(Integer.valueOf(200));
        responseSize.setDepth(Integer.valueOf(300));
        response.setSize(responseSize);

        return response;
    }
}

キャストがキレイに消えました。これで、型を変更してもコンパイルエラーにできますね。

これを以下のJSON を渡して実行すると、

{
    "name": "orange juice",
    "price": 1000,
    "releaseDate": 1601606387939,
    "rate": 4.5,
    "rawMaterial": ["orange", "fragrance"],
    "size": {
        "height": 10,
        "width": 20,
        "depth": 30
    }
}

こんな出力になります。

{
  "name": "coffee",
  "price": 500,
  "releaseDate": 1601623033115,
  "rate": 4.2,
  "rawMaterial": [
    "coffee",
    "sugar"
  ],
  "size": {
    "height": 100,
    "width": 200,
    "depth": 300
  }
}

POJO 方式だと、Map 方式の HashMap を使う場合と違って、順序は維持されてるようです。

便利なライブラリ

JSON を POJO クラスにマッピングできることを利用して、便利に使えるライブラリ aws-lambda-java-libs が AWS 公式で提供されています。
https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-events

たとえば、API Gateway の Lambda プロキシ統合の場合、こんな感じで用意されている POJO クラスを入出力に使えます。

public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) {
    APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
    response.setStatusCode(Integer.valueOf(200));
    response.setBody("ok");
    return response;
}

さいごに

次は、InputStream/OutputStream 方式を紹介しようと思います。

Java Lambda の入出力型を試してみた〜Stream 編〜
https://qiita.com/kazfuku/items/6f0f55ffa3a88d76cfaa

0
1
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
0
1