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