Lagom with Scalaやってく!【その2:最小サービスの作成】
Gakuです。
Lagom with Scalaやってく!【その1:環境構築】
前回までで、環境構築は終わったので、今回は新しくサービスを作成します。
提供されているHello Worldはいろいろなことが記載されており、理解が難しかったので、さらにコードを削ぎ落とし、最低限動くサービス(GetメソッドでStringを取得するだけのもの)を作ります。
今回作成したコード
こちらにあります。
https://github.com/gaku3601/study-lagom/tree/step2
apiとimplのフォルダを作成する
PJルートにmy-study-lagom-apiとmy-study-lagom-implフォルダを作成します。この状態だと、まだmoduleとして認識されていない状態ですね。
モジュールの追加
study-lagom/build.sbtを以下のように修正します。
organization in ThisBuild := "com.example"
version in ThisBuild := "1.0-SNAPSHOT"
// the Scala version that will be used for cross-compiled libraries
scalaVersion in ThisBuild := "2.13.0"
val macwire = "com.softwaremill.macwire" %% "macros" % "2.3.3" % "provided"
val scalaTest = "org.scalatest" %% "scalatest" % "3.1.1" % Test
// 追記
lazy val `study-lagom` = (project in file("."))
.aggregate(`my-study-lagom-api`, `my-study-lagom-impl`, `study-lagom-api`, `study-lagom-impl`, `study-lagom-stream-api`, `study-lagom-stream-impl`)
// 追加
lazy val `my-study-lagom-api` = (project in file("my-study-lagom-api"))
.settings(
libraryDependencies ++= Seq(
lagomScaladslApi
)
)
// 追加
lazy val `my-study-lagom-impl` = (project in file("my-study-lagom-impl"))
.enablePlugins(LagomScala)
.settings(
libraryDependencies ++= Seq(
macwire,
)
)
.dependsOn(`my-study-lagom-api`)
lazy val `study-lagom-api` = (project in file("study-lagom-api"))
.settings(
libraryDependencies ++= Seq(
lagomScaladslApi
)
)
lazy val `study-lagom-impl` = (project in file("study-lagom-impl"))
.enablePlugins(LagomScala)
.settings(
libraryDependencies ++= Seq(
lagomScaladslPersistenceCassandra,
lagomScaladslKafkaBroker,
lagomScaladslTestKit,
macwire,
scalaTest
)
)
.settings(lagomForkedTestSettings)
.dependsOn(`study-lagom-api`)
lazy val `study-lagom-stream-api` = (project in file("study-lagom-stream-api"))
.settings(
libraryDependencies ++= Seq(
lagomScaladslApi
)
)
lazy val `study-lagom-stream-impl` = (project in file("study-lagom-stream-impl"))
.enablePlugins(LagomScala)
.settings(
libraryDependencies ++= Seq(
lagomScaladslTestKit,
macwire,
scalaTest
)
)
.dependsOn(`study-lagom-stream-api`, `study-lagom-api`)
実装
とりあえず、理解している部分にはコメントを記載しました。理解できていないところはふわっとしたコメントを記載していますが、スルーいただければ幸いです。(自分の覚書用で。理解できたら更新します。
apiの実装
で、こんな感じで実装。
package com.example.mystudylagom.api
import akka.NotUsed
import com.lightbend.lagom.scaladsl.api.{Descriptor, Service, ServiceCall}
trait MyStudyLagomService extends Service {
/**
* Example: curl http://localhost:9000/api/hello2/Alice
* id: stringには/api/hello2/:idのidが入ってくる
* ServiceCall[NotUsed, String]のNotUsed部分にはrequest bodyが、Stringはresponseの肩
* 今回、request bodyはNotUsedで使わないことを宣言している→つまり取得処理
* lagomはServiceCall[NotUsed, String]自動的にGetメソッドと判断する
*/
def hello(id: String): ServiceCall[NotUsed, String]
override final def descriptor: Descriptor = {
import Service._
named("my-study-lagom")
.withCalls(
pathCall("/api/hello2/:id", hello _), // APIルーティングを定義
)
.withAutoAcl(true) // これはつけとかないと動かない。
}
}
ServiceImplの作成
で、MyStudyLagomServiceImpl.scala
package com.example.mystudylagom.impl
import akka.NotUsed
import com.example.mystudylagom.api.MyStudyLagomService
import com.lightbend.lagom.scaladsl.api.ServiceCall
import scala.concurrent.Future
class MyStudyLagomServiceImpl() extends MyStudyLagomService {
// apiの実装の中身。「_ =>」の_にはpostの場合、request bodyが入ってくるみたい。
override def hello(id: String): ServiceCall[NotUsed, String] = ServiceCall { _ =>
// なんでもかんでもFutureで返せばOKっぽい?
Future.successful("test")
}
}
これで起動すれば動きそうですが、エラーが出ます。ちらっと調べた感じDIをするためのLoaderが必要とのこと。
こんな感じで実装
package com.example.mystudylagom.impl
import com.example.mystudylagom.api.MyStudyLagomService
import com.lightbend.lagom.scaladsl.api.ServiceLocator
import com.lightbend.lagom.scaladsl.api.ServiceLocator.NoServiceLocator
import com.lightbend.lagom.scaladsl.server._
import com.lightbend.lagom.scaladsl.devmode.LagomDevModeComponents
import play.api.libs.ws.ahc.AhcWSComponents
import com.softwaremill.macwire._
/*
* これはDIの仕組みを行うために必要?
* このfileを作らないと動かない
* とりあえず、いらないものを削ぎ落として、最低限動くようにしたもの
* akkaとかcassandraの読み込みもここで行うようなので、また別の機会でほそぼそ試す。
*/
class MyStudyLagomLoader extends LagomApplicationLoader {
// loadとloadDevModeで、おそらく、本番・開発環境で使う依存を管理する感じかな?
override def load(context: LagomApplicationContext): LagomApplication =
new MyStudyLagomApplication(context) {
override def serviceLocator: ServiceLocator = NoServiceLocator
}
// このメソッド、消しても動く?と思って消してみたらエラー出た。
override def loadDevMode(context: LagomApplicationContext): LagomApplication =
new MyStudyLagomApplication(context) with LagomDevModeComponents
}
abstract class MyStudyLagomApplication(context: LagomApplicationContext)
extends LagomApplication(context)
with AhcWSComponents {
// こんな感じでバインドするみたい
override lazy val lagomServer: LagomServer = serverFor[MyStudyLagomService](wire[MyStudyLagomServiceImpl])
}
で、このLoaderをconfで指定してあげる。
# Loaderの読み込みでこの一行は必要
play.application.loader = com.example.mystudylagom.impl.MyStudyLagomLoader
起動
ここまでできたら起動してみる。で作成したAPIにcurl投げると
gakumbp:study-lagom gaku$ curl http://localhost:9000/api/hello2/Alice
test
なんか返ってくる!
そして、別サービスのstudy-lagomのAPIにcurl投げると
gakumbp:study-lagom gaku$ curl http://localhost:9000/api/hello/Alice
Hello, Alice!
こちらもなんか返ってくる🥳
おわり
なんとな〜く。わかっては来ているけど、ここからどうサービス間で連携するのか、とか、どう永続化をするのか。
CQRSはどうすんの?集約ルートどう書くの?
みたいなところが山積みなんで、暇な時にこそこそやっていこうと思う。
Author And Source
この問題について(Lagom with Scalaやってく!【その2:最小サービスの作成】), 我々は、より多くの情報をここで見つけました https://qiita.com/gaku3601/items/c7c2efa6b0a5fd4399b0著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .