Akka HTTPリファレンス
Akka HTTP Scala API
scaladslのdsl: domain-specific language(DSL)
Akka HTTPリファレンス
Akka HTTP Scala API
scaladslのdsl: domain-specific language(DSL)
JSONフォーマットによるユーザ登録・削除とユーザ、ユーザリスト参照
Akka HTTP Quickstart for Scala
Githubコード
以下4つのファイルで構成
以下のUserResistryアクターが、サーバのREST-APIにより、各リクエストを処理します。
ダウンロードしたサンプルコードディレクトリ内でsbtシェルを起動し、reStart(sbt-revolverプラグイン:バックグラウンド起動)により本システム起動します。
$sbt
sbt:akka-http-quickstart-scala> reStart
root Starting com.example.QuickstartApp.main()
[success] Total time: 1 s, completed 2020/11/26 18:12:28
sbt:akka-http-quickstart-scala> root [2020-11-26 18:12:30,849] [INFO] [akka.event.slf4j.Slf4jLogger] [HelloAkkaHttpServer-akka.actor.default-dispatcher-3] [] - Slf4jLogger started
root[ERROR] SLF4J: A number (1) of logging calls during the initialization phase have been intercepted and are
root[ERROR] SLF4J: now being replayed. These are subject to the filtering rules of the underlying logging system.
root[ERROR] SLF4J: See also http://www.slf4j.org/codes.html#replay
root [2020-11-26 18:12:32,317] [INFO] [akka.actor.typed.ActorSystem] [HelloAkkaHttpServer-akka.actor.default-dispatcher-3] [] - Server online at http://127.0.0.1:8080/
DSLにより、ユーザと各ユーザのルートは、 /users, /users/<id>
に設定されます。
ユーザへのアクセスは、http://127.0.0.1:8080/users/<id>
ユーザリストは、http://127.0.0.1:8080/users
となります。
この時点ではユーザデータは空なので、実際にユーザデータを上記サーバへポストします。ポストする手段としては、cURLコマンド、またはPostmanを利用します。
cURLによるポスト
$ curl -H "Content-type: application/json" -X POST -d '{"name": "MrX", "age": 31, "countryOfResidence": "Canada"}' http://localhost:8080/users
$ curl -H "Content-type: application/json" -X POST -d '{"name": "Anonymous", "age": 55, "countryOfResidence": "Iceland"}' http://localhost:8080/users
$ curl -H "Content-type: application/json" -X POST -d '{"name": "Bill", "age": 67, "countryOfResidence": "USA"}' http://localhost:8080/users
Postmanによるポスト
Postmanダウンロード
ユーザごとに以下を参考に、JSONフォーマットによる各ユーザデータをサーバへ送信します。
登録したユーザの確認は、例えばユーザBillの場合、
$ curl http://localhost:8080/users/Bill
{"name":"Bill","age":67,"countryOfResidence":"USA"}
全ユーザの確認は、
$ curl http://localhost:8080/users
{"users":[{"name":"Anonymous","age":55,"countryOfResidence":"Iceland"},{"name":"MrX","age":31,"countryOfResidence":"Canada"},{"name":"Bill","age":67,"countryOfResidence":"USA"}]}
Postman、ウェブブラウザでも上記データは取得できます。
ユーザを削除する場合は、
$ curl -X DELETE http://localhost:8080/users/Bill
User Bill deleted.
akka-http-json provides JSON (un)marshalling support for Akka HTTP via the following JSON libraries:
akka-http-circe
https://mvnrepository.com/artifact/de.heikoseeberger/akka-http-circe
project/build.sbtへ以下追加
libraryDependencies ++= Seq(
"de.heikoseeberger" %% "akka-http-circe" % "1.35.2",
...
)
Circe
val circeVersion = "0.12.3"
libraryDependencies ++= Seq(
"io.circe" %% "circe-core",
"io.circe" %% "circe-generic",
"io.circe" %% "circe-parser"
).map(_ % circeVersion)
akka-http-jackson
https://mvnrepository.com/artifact/de.heikoseeberger/akka-http-jackson
project/build.sbtへ以下追加
libraryDependencies ++= Seq(
"de.heikoseeberger" %% "akka-http-jackson" % "1.35.2",
...
)
IoTの基本であるJSONフォーマットによるデータ送受信
3つのJSONライブラリ:Spray, Circe, JacksonによるAkka HTTPのサンプルコード
(IntelliJにより作成)
build.sbt
name := "AkkaHttpJson"
version := "0.1"
scalaVersion := "2.13.4"
val akkaVersion = "2.6.5"
val akkaHttpVersion = "10.2.1"
val akkaHttpJsonVersion = "1.35.2"
val circeVersion = "0.12.3"
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor-typed" % akkaVersion,
"com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
"de.heikoseeberger" %% "akka-http-circe" % akkaHttpJsonVersion,
"de.heikoseeberger" %% "akka-http-jackson" % akkaHttpJsonVersion,
"com.typesafe.akka" %% "akka-stream" % akkaVersion,
"ch.qos.logback" % "logback-classic" % "1.2.3",
)
// Circe
libraryDependencies ++= Seq(
"io.circe" %% "circe-core",
"io.circe" %% "circe-generic",
"io.circe" %% "circe-parser"
).map(_ % circeVersion)
AkkaHttpJson.scala
import java.util.UUID
import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import akka.http.scaladsl.Http
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import de.heikoseeberger.akkahttpjackson.JacksonSupport
/*
We're going to work with these data structures in our endpoints.
In practice we'd create some "request" data structures, e.g. AddUserRequest.
*/
case class Person(name: String, age: Int)
case class UserAdded(id: String, timestamp: Long)
import spray.json._
trait PersonJsonProtocol extends DefaultJsonProtocol {
implicit val personFormat: RootJsonFormat[Person] = jsonFormat2(Person)
implicit val userAddedFormat: RootJsonFormat[UserAdded] = jsonFormat2(UserAdded)
}
// Spray
object AkkaHttpJson extends PersonJsonProtocol with SprayJsonSupport {
implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty, "AkkaHttpJson")
val route: Route = (path("api" / "user") & post) {
entity(as[Person]) { _: Person =>
complete(UserAdded(UUID.randomUUID().toString, System.currentTimeMillis()))
}
}
def main(args: Array[String]): Unit = {
Http().newServerAt("localhost", 8081).bind(route)
}
}
// Circe
object AkkaHttpCirce extends FailFastCirceSupport {
import io.circe.generic.auto._
implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty, "AkkaHttpJson")
val route: Route = (path("api" / "user") & post) {
entity(as[Person]) { _: Person =>
complete(UserAdded(UUID.randomUUID().toString, System.currentTimeMillis()))
}
}
def main(args: Array[String]): Unit = {
Http().newServerAt("localhost", 8082).bind(route)
}
}
// Jackson
object AkkaHttpJackson extends JacksonSupport {
implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty, "AkkaHttpJson")
val route: Route = (path("api" / "user") & post) {
entity(as[Person]) { _: Person =>
complete(UserAdded(UUID.randomUUID().toString, System.currentTimeMillis()))
}
}
def main(args: Array[String]): Unit = {
Http().newServerAt("localhost", 8083).bind(route)
}
}
JSONライブラリを導入した各オブジェクト(サーバ)を、IntelliJのrunコマンド、またはオブジェクトの左に示されたアイコンをクリックして起動します。
JSONフォーマットのユーザデータをポスト—>JSONフォーマットのidとタイムスタンプを表示
Postmanまたはsnap版httpユーティリティにより動作を確認して下さい。
$ echo '{"name": "bill", "age": 23 }' | http post localhost:8081/api/user
HTTP/1.1 200 OK
Content-Length: 71
Content-Type: application/json
Date: Fri, 27 Nov 2020 09:06:19 GMT
Server: akka-http/10.2.1
{
"id": "61ffca83-425c-4dfa-b7ca-5e14f0546380",
"timestamp": 1606467979105
}
ServerBuilder API
10.1.x
// only worked with classic actor system
implicit val system = akka.actor.ActorSystem("TheSystem")
implicit val mat: Materializer = ActorMaterializer()
val route: Route =
get {
complete("Hello world")
}
Http().bindAndHandle(route, "localhost", 8080)
10.2.x
// works with both classic and typed ActorSystem
implicit val system = akka.actor.typed.ActorSystem(Behaviors.empty, "TheSystem")
// or
// implicit val system = akka.actor.ActorSystem("TheSystem")
// materializer not needed any more
val route: Route =
get {
complete("Hello world")
}
Http().newServerAt("localhost", 8080).bind(route)