finatra
finatra(https://twitter.github.io/finatra/)はSinatraからアイデアを得て、twitterSeverを使って作られたScalaベースのwebフレームワークです。この記事を書いた時点で、最新のバージョンは2.0です。
Hello World
finatraのリポジトリ(https://github.com/twitter/finatra)にあるexamples/finatra-hello-worldを使います。
README.mdには既に詳しいディプロイ方法が載ってありますが、起動方法は下記のコマンドを叩く:
./sbt -Dlogback.configurationFile=src/test/resources/logback-test.xml run
portを変える
このプロジェクトはデフォルトに8888(フロント)と9990(内部用)を使っていますが、もしいずれかのportは既に他のアプリに使われたりしたら、エラーがでます。portを変えるには、runの後ろに、-http.port=:1212(フロント)、-admin.port=:9911(内部用)というオプションを追加してください。
ブラウザを開いて、http://localhost:8888/hi?name=Worldにアクセスすると

ServerとControllerをつくてみる
先ほどのHello Worldプロジェクトでは、既にHelloWorldSeverとHelloWorldControllerが
用意されたので、特に何もしなくてもサイトとして動きます。これから、自分でServerとControllerを作ってみます:
Server
./src/main/scala/jp/co/befool/biiにBiiServer.scalaを作成します。
この記事のコードがパッケージ
jp.co.befool.biiにあります。パッケージというコンセプトが分かる方は、自分好きなパッケージにしても大丈夫です。
package jp.co.befool.bii
import com.twitter.finatra.http.HttpServer
import com.twitter.finatra.http.routing.HttpRouter
import com.twitter.finatra.http.filters.CommonFilters
// finatraのHttpServerを拡張
class BiiServer extends HttpServer {
// routerなど設定
override def configureHttp(router: HttpRouter) {
router
.filter[CommonFilters] // Commonフィルターが必要です
}
}
// BiiServerのエントリーポイント
object BiiServerMain extends BiiServer
Controller
./src/main/scala/jp/co/befool/bii/controller/RootController.scalaを作成します:
package jp.co.befool.bii.controller
import com.twitter.finatra.http.Controller
import com.twitter.finagle.http.Request
// finatraのControllerを拡張
class RootController extends Controller{
// http://localhost
get("/") { request: Request =>
response.ok.body(s"<h1>HelloWorld</h1>")
}
}
BiiServerからRootControllerにルートします:
import jp.co.befool.bii.controller.RootController
// finatraのHttpServerを拡張
class BiiServer extends HttpServer {
// routerなど設定
override def configureHttp(router: HttpRouter) {
router
.filter[CommonFilters] // Commonフィルターが必要です
.add[RootController] // RootControllerを追加
}
}
コマンドsbt runすると
[warn] Multiple main classes detected. Run 'show discoveredMainClasses' to see the list
Multiple main classes detected, select one to run:
[1] com.twitter.hello.HelloWorldServerMain
[2] jp.co.befool.bii.BiiServerMain
Enter number:
サーバーが二つ検出されたので、どっちを実行するかという質問です。2で入力します。問題なければ、ブラウザでhttp://localhost:8888で見ると:

サーバーちゃんと動いています。
RequestのValidationをやってみます
先ほど作ったRootControllerの直前に、RootRequestを作成します:
import com.twitter.finatra.request.QueryParam
import com.twitter.finatra.validation.NotEmpty
case class RootRequest (
// @NotEmpty記号は空値が不可ということです
// @QueryParamは@NotEmptyの対象パラメータ名です
@NotEmpty @QueryParam name: String
)
RootControllerのget("/")ルートに修正を入れます:
get("/") { request: RootRequest =>
response.ok
.header("Content-Type", "text/html; charset=utf-8")
.body(s"<h1>こんにちは、${request.name}</h1>")
}
requestのタイプを先ほど作ったRootRequestに宣言します。
sbt runして、ブラウザでhttp://localhost:8888にアクセスして、下記のエラーが表示されます:

URLをhttp://localhost:8888/?name=世界にして、アクセスすると:

Requestのバリデーション動いてるとわかりますね。
まとめ
finatraに興味ある方は、より詳しい説明と使い方が公式のリポジトリに載っています:https://github.com/twitter/finatra/blob/master/http/README.md。
オープンソースのwebフレームワークとしては、finatraのドキュメントなどはまだ不足してる感じがします。しかし、twitterという超大手なweb企業が使ってるというとこが、魅力を感じる人もいるでしょう(自分はそうでした)。次回はfinatraを利用してアプリのバックエンドを作ってみようと思います。