フルスクラッチでAkka HTTPを起動させる (Scala)

ちきさんです。

フルスクラッチでAkka HTTPを起動するところまで出来たのでメモを残します。

ちなみにAkka HTTPはExpressみたいなものです。

※全体的にNode.jsの知識がある人にわかりやすいように書いています。

## 前提としてsbtが必要

sbtがインストールされている必要があります。僕はbrewでインストールしました。sbtはnpm相当だけどもっと高機能なもの、という感じです。

```
$ brew install sbt
```

## sbt newを使わない

`sbt new`コマンドはYeomanみたいなものです。プロジェクトの雛形をさくっと用意してくれるのでとても便利ですが、裏で何が起きているのかわからないのは不気味だし知らないままでいるのも良くないので、これに頼らずに`npm init`相当の作業からAkka HTTPを起動させるまでをやります。

---

## sbt

まずはプロジェクト用のディレクトリを作ります。

```
$ mkdir my-akka
$ cd my-akka
```

作ったディレクトリに移動したら`sbt`を実行します。`npm init`みたいなものです。

```
$ sbt
```

しばらくすると`sbt:my-akka>`みたいなプロンプトが表示されるので、設定をいくつか書いていきます。

_プロジェクトの名前_

```
$ sbt:my-akka> set name := "my-akka"
```

_プロジェクトのバージョン_

```
$ sbt:my-akka> set version := "0.1"
```

_Scalaのバージョン_

```
$ sbt:my-akka> set scalaVersion := "2.12.4"
```

_保存_

```
$ sbt:my-akka> session save
$ sbt:my-akka> exit
```

## build.sbt

ここまでで`build.sbt`ファイルが作成されたので確認してみます。

```
$ cat build.sbt
```

```txt:build.sbt
name := "my-akka"

version := "0.1"

scalaVersion := "2.12.4"
```

このようになっていると思います。次に依存関係を記述します。

テキストエディタを使って下記の記述を末尾に追加します。

```
libraryDependencies += "com.typesafe.akka" %% "akka-http" % "10.1.0"
libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.5.11"
```

```txt:build.sbt
name := "my-akka"

version := "0.1"

scalaVersion := "2.12.4"

libraryDependencies += "com.typesafe.akka" %% "akka-http" % "10.1.0"
libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.5.11"
```

最終的に`build.sbt`ファイルが上記のようになっていればOKです。`package.json`みたいなものですね。

依存関係が増えたので

```
$ sbt update
```

を実行します。`npm install`みたいなものです。
(補足: `sbt run`するときに自動的に`sbt update`もされるらしいです)

## Akka HTTP

Akka HTTPの公式ドキュメントにサンプルコードが色々載っているので適当なものをコピペします。
(ref: https://doc.akka.io/docs/akka-http/current/scala/http/introduction.html )

まずソースコードを置くディレクトリを作成します。

```
$ mkdir -p src/main/scala/com/ovrmrw/akka
```

`src/main/scala`で始まるのは慣例です。(ref: http://www.scala-sbt.org/1.0/docs/ja/Directories.html )

そして`WebServer.scala`というファイルを作ってコピーしたコードを貼り付けました。

```scala:src/main/scala/com/ovrmrw/akka/WebServer.scala
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import scala.io.StdIn

object WebServer {
  def main(args: Array[String]) {

    implicit val system = ActorSystem("my-system")
    implicit val materializer = ActorMaterializer()
    // needed for the future flatMap/onComplete in the end
    implicit val executionContext = system.dispatcher

    val route =
      path("hello") {
        get {
          complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
        }
      }

    val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)

    println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
    StdIn.readLine() // let it run until user presses return
    bindingFuture
      .flatMap(_.unbind()) // trigger unbinding from the port
      .onComplete(_ => system.terminate()) // and shutdown when done
  }
}
```

これで準備完了です。

## sbt run

`npm start`に相当するのが`sbt run`です。やってみましょう。

プロジェクトのルートディレクトリで、

```
$ sbt run
```

を実行します。しばらく待つと

```
Server online at http://localhost:8080/
```

と表示されるので、ブラウザを起動して `http://localhost:8080/hello` を開きます。

**Say hello to akka-http**

と表示されればOKです。やったね！

---

(参考にしたもの)

- https://www.packtpub.com/mapt/book/application_development/9781785288180/1/ch01lvl1sec9/creating-an-akka-scala-sbt-project-from-scratch