Lagomでイミュータブルなデータクラスを作る

Lagomを試してみるシリーズ第三回です。今回はLagomでイミュータブルなデータクラスを作る方法について見ていきたいと思います。Lagomの本質にたどり着くにはまだまだ時間がかかりそうですw

Lagomのドキュメントを読んでいると以下のようなアノテーションてんこ盛りのインターフェースが登場します。

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.lightbend.lagom.javadsl.immutable.ImmutableStyle;
import org.immutables.value.Value;

@Value.Immutable
@ImmutableStyle
@JsonDeserialize(as = ItemId.class)
@JsonSerialize(as = ItemId.class)
public interface AbstractItemId {
    @Value.Parameter
    long orderId();
    @Value.Parameter
    long itemId();
}

JSON関連はひとまず置いておいて、Immutablesのアノテーションを使ってイミュータブルなデータクラスを作っているようです。ちなみにImmutablesというのはJava用のライブラリでアノテーションプロセッサでインターフェースからコンパイル時にデータクラスを自動生成するというものです。

github.com

Immutablesを使うにはbuild.sbtのhelloworld-apiプロジェクトの設定を以下のように編集します。

lazy val helloworldApi = project("helloworld-api")
  .settings(
    version := "1.0-SNAPSHOT",
    libraryDependencies ++= Seq(
      lagomJavadslApi,
      lagomJavadslImmutables // これを追加
    )
  )

前回作成したHelloIdをImmutablesを使ってイミュータブルなデータクラスにしてみます。

import com.lightbend.lagom.javadsl.immutable.ImmutableStyle;
import org.immutables.value.Value;

@ImmutableStyle
@Value.Immutable
public interface AbstractHelloId {
    @Value.Parameter
    String area();
    @Value.Parameter
    String name();
}

アノテーションを付与するだけでなく、以下のような注意点があります。

  • クラスではなくインターフェースにすること
  • インターフェース名をAbstract + クラス名にすること
  • プロパティはメソッドとして定義すること

インターフェース名はAbstractHelloIdですが、データクラスを使う側ではHelloIdで使うことができます。

@Override
public ServiceCall<HelloId, NotUsed, String> hello() {
  return (id, request) -> completedFuture("Hello, " + id.name() + " in " + id.area() + "!");
}

なお、IntelliJではこのままだとアノテーションプロセッサで生成されるHelloIdクラスを認識することができません。調べてみたところ、HelloId.javatarget/scala-2.11/classesディレクトリに生成されていたので、プロジェクトの設定でこのディレクトリをソースパスに追加することで認識できるようになりました。

f:id:takezoe:20160411094857p:plain