本連載では、リアクティブプログラミング(RP)の概要や、それに関連する技術、RPでアプリを作成するための手法について解説します。今回は、Lightbend Reactive Platformを構成するPlay framework、Akka、Akka Streamsについて、実際にサンプルを動かしながら解説します
前回記事では、Lightbend Platformを構成する各プロダクトについて紹介しました。今回はLightbend Reactive Platformを構成するPlay framework、Akka、Akka Streamsについて、実際にサンプルを動かしながら解説します。
なお、本稿のサンプルプログラムを動かしたい場合、前回記事にセットアップ方法を記述してあるので、それを参考に環境を作成しておきましょう。
ここではPlayのプロジェクトを作成し、ソースコードの内容について解説します。
なお前回記事では、「Activator ui」を使用してプロジェクトを作成しましたが、Activator uiはEOLを迎えることになっています。
現在は「sbt」「Giter8」の使用が推奨されているので、その方法を用いてプロジェクトを作成してみましょう。
sbtはMavenやGradleと同じビルドツールです。Scalaを用いてビルドの定義を記述し、コンパイルやライブラリの管理まで行えます。Lightbend Reactive Platformでは、2016年にGiter8テンプレートのサポートが追加されました。
Giter8は、GitHubのリポジトリに登録されているテンプレートからプロジェクトを生成するためのツールです。
sbtはHomeBrewでインストールできます。
% brew update && brew install sbt
HomeBrewを使わない場合、下記ページを参照してsbtをインストールしてください。
次に、Giter8を使ってプロジェクトを作成します。途中で出て来る入力項目は全てデフォルトで問題ありません。
% sbt new playframework/play-scala-seed.g8
作成したプロジェクト(play-scala-seed)へ移動し、sbtコマンドを実行すると、sbtコンソールが起動します(※初回は依存ライブラリのダウンロードなどで時間がかかります)。
% sbt
sbtコンソールでrunコマンドを実行すると、アプリが起動します。「http://localhost:9000」にアクセスしてみてください。
[play-scala-seed] $ run
ブラウザに「Welcome to Play!」と表示されればアプリは正常に起動しています。
主要なファイルのコードを少しだけ見てみましょう。
sbtのビルド定義は、ここに記述します。サンプルでは、プロジェクト名、Scalaのバージョンなどが定義されています。またサードパーティーのライブラリを使う場合は、libraryDependenciesを使うことで依存性の設定を追加できます。
メソッド/パスをアクションとマッピングさせるための定義ファイルです。下記のroutesファイルでは、GETメソッドで「/」(ルートパス)にアクセスすると、HomeControllerクラスのindexメソッドが実行されます。
# An example controller showing a sample home page GET / controllers.HomeController.index # Map static resources from the /public folder to the /assets URL path GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
routesでルートパスにマッピングされたアクションを実行するためのコントローラークラスです。
@Singleton class HomeController @Inject()(cc: ControllerComponents) extends AbstractController(cc) { def index() = Action { implicit request: Request[AnyContent] => Ok(views.html.index()) } }
ここに定義されているindexメソッドが、マッピングされたアクションです。リクエストを受け取ったら後述するビューへ処理を渡しています。
また、@Injectアノテーションを使うことで、ControllerComponentsがDI(Dependency Injection)されます。もちろん自作クラスもDI可能なので、ここでロジッククラスへのDIを行うのが一般的です。
Playでは「Twirl」というScalaベースのテンプレートエンジンが使えます。Scalaのコードブロックを埋め込み、HTML(XMLやCSVなどテキストベースなら何でも)を生成できます。
@() @* <-ここでパラメーターを受け取ることも可能 *@ @main("Welcome to Play") { <h1>Welcome to Play!</h1> }
Play frameworkの詳細は、連載「Scala+Play 2.0でWebアプリ開発入門」でも解説しています(※バージョンは2.0〜2.1を使用しているので注意)。よろしければ、こちらもご確認ください。
Akkaは、伸縮性、拡張性、耐障害性のある「アクター」モデルのメッセージ駆動型ランタイムライブラリです。詳細については、記事「Play2+nginx/Akka/WebSocketで高速双方向通信」など、Akkaについて解説しているサイトは多くあるので、ご確認ください。
まずはAkkaの動作を確認してみましょう。シンプルなアクターを作成し、メッセージ処理を実行してみます。
プログラムを動かしたい場合は、下記コマンドを実行してScalaアプリのテンプレートを作成してください。
sbt new sbt/scala-seed.g8
最初にアクターを定義します。Actorクラスはメッセージ受信用のMailboxとメッセージ処理用のreceiveを持っています。下記は、文字列を受け取ったらコンソール出力するだけのシンプルなアクターです。
/* src/main/scala/example/Main.scala */ class HelloActor extends Actor { def receive = { case req:String => println(s"Hello $req") case _ => println("unknown type message") } }
実行オブジェクトを作成します。先ほど定義したアクターのインスタンスを作成し、メッセージを送信してみます。
/* src/main/scala/example/Main.scala */ import akka.actor.{Actor,ActorSystem,Props} object Main extends App { //ActorSystemはAkka 全体の設定保持と全てのアクターインスタンスを管理 val system = ActorSystem("HelloActor") val actor = system.actorOf(Props[HelloActor], "helloActor") //メッセージ送信 actor ! "taro" //アクターとシステムの停止 system.stop(actor) system.terminate }
ActorSystem#actorOfを使ってアクターのインスタンスを作成し、メッセージを送信しています。HelloActorのreceiveで文字列を受け取り、コンソールを表示しています。
Copyright © ITmedia, Inc. All Rights Reserved.