本連載では、リアクティブプログラミング(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.
Java Agile 髫ェ蛟�スコ荵斟帷ケ晢スウ郢ァ�ュ郢晢スウ郢ァ�ー