Help us understand the problem. What is going on with this article?

「SpringBoot」に疲れたら「jooby」はいかが?

More than 1 year has passed since last update.

最近かかわったプロジェクトでは、「SpringBoot」(もしく「Spring Web」)の採用が多くデファクトスタンダードになってきたように感じています。
「SpringBoot」が提供しくれているたくさんの機能には大変お世話になっているのですが、不満も多いです。

例えば以下のようなものです。

  • 設定が「アノテーションで簡単になった」とはいえ、呪文のようなプロパティー設定まみれ。
  • DIのメリットはトランザクション管理だけど、今となっては Loanパターン (try-with-resources構文みたいなやつ)で実現したほうがわかりやすいしはまりにくい。
  • J2EE仕様なんていう化石化したIF使いたくない
  • DIの魔法の奥で発生した分けのわからない例外に多大な時間が奪われる
  • spring のデフォルトの使い方から外れると、急にハードルが上がる

たまたま出会った、 joobyっていうのを試してみて、好印象だったのでご紹介します。


Joobyとは

パスを「レスポンスに変換する関数」に割り当てることを主眼にしているフレームワークです。

公式サイトでは「javaで作る、スケーラブルで 早くて モジュール志向で マイクロフレームワーク だ」と言っています。

マイクロフレームワークなどと言われると 「buzzword っぽくて胡散臭い」と思ったのですが、

使ってみると「コンパクトに作り始めて拡張も容易」なフレームワークだと思いました。

また、実際にアプリを実行してみたところ、起動も早く「マイクロフレームワークの風」を感じました。 (netty ベースのサーバが起動します )

公式サイトのサンプルソース

Javaサンプル

import org.jooby.Jooby;
public class App extends Jooby {
  { get("/", () -> "Hey Jooby!"); }
  public static void main(final String[] args) {
    run(App::new, args);
  }
}

これだけでWebアプリのサーバが起動します。
また、標準的に kotlinもサポートしている ところが素敵です。

Kotlinサンプル

import org.jooby.*
class App : Kooby ({
    get("/") { "Hey Jooby!" }
})
fun main(args:Array<String>) {  run(::App, *args) }

このブログでは以下 kotlin のソースで紹介していきます。


ルーティング実装

上の 「Kotlinサンプル」の get("/") { "Hey Jooby!" } がルーティング実装です。 ルートパス にアクセスすると Hey Jooby! という文字列返却されるという意味です。(直観的でとても分かりやすい)

    get("/hoge") { "hogeres" }
    post("/foo/boo") { FooControler.boo() }

というような実装をしていけば、Webアプリ完成ということになります。

以下、少しだけ複雑な例です。
(「リクエストや、レスポンスに対するハンドリング」「テンプレートエンジン使う」場合)

get("/boo/hoge") { req , rsp -> BooControler.hoge(req.param("name") , rsp)
    Results.html("freemarker/boo/hoge.html")
}

簡単なことも難しいことも直観的に実装できるところがいいと思います。


ルーティング以外の実装

ルーティング以外の、使いそうな実装を紹介していきます。

例外ハンドリング

例外が発生した場合、何をレスポンスするかを実装できます。

err { req, rsp, err ->
    val cause = err.cause
    when (cause) {
      is MyException1 -> { /* レスポンス実装 */ }
      is MyException2 -> { /* レスポンス実装 */ }
      else -> Err.DefHandler().handle(req, rsp, err)
    }
}

特定の例外のみハンドリングしたい場合は以下のようにすることもできます。

err(MyException1::class.java) { req, rsp, err -> /* 省略 */}

Filter

リクエストの処理前後に、フィルター処理を挟むことができます。これにより、アクセスログを出力したり、HTTPヘッダーやクッキーを、一律もしくは条件付きで 付与することができます。

before("**") { req, rsp -> initLoginfo(req, rsp) }

after("**") { req, rsp, result ->
    accessLog(req, rsp, result)
            .header("Access-Control-Allow-Origin", appEnv.allowOrigin)
            .header("Access-Control-Allow-Credentials", true)
}

MODULES

jooby は使用する「モジュール」 を指定することによって機能拡張する思想です。
標準的にサポートしているものが 公式サイトのMODULES に書かれています。

Maven や gradle の dependency 設定をして、ルーティングの前あたりに、
use( <モジュールのインスタンス> ) というように実装して機能追加する使い方が基本です。

以下少し例を上げます。

Freemarker テンプレートエンジンに使う

以下のようにコーディングしておくと Freemarker のテンプレートが使えます。

    use(Ftl("/freemarker"))

上の例では、
classpath が通っているディレクトリから freemarker ディレクトリ以下に、テンプレートを見に行きますという意味になります。

実際にテンプレートを使う場合、以下のようにコードを書くことになります。

get("/hoge/") {
    Results.html("hoge/index.html")
            .put("hogeParam", hogeBoo.hoge)
}

上の例では、テンプレートファイル freemarker/hoge/index.html の中で、 変数 ${hogeParam} のようにしてオブジェクトにアクセスできるようになります。 ( Freemarker の標準的な使い方ができます)

RESTish な APIのために jackson を使う

以下のようにコーディングしておくと

    use(Jackson())

get("/myjson") { MyJsonObject( firstName ="Yamada", name ="tarou", age ="25") } というようなコードを書くだけで json としてレスポンスが返されるようになり、RESTish APIが作りやすくなります。

ただし、単なる文字列を返却したい場合、返却値が ダブルクォーテーション でくくられる ようなふるまいになってしまいました。
(例えば、 get("/alive/chek") { "I'm alive" } とすると、 レスポンスの文字列が "I'm alive" となってしまう)

json 以外のレスポンスも返却したい場合は、 use(Jackson()) を使わず、自力でJackson に json成形させたほうがいいように思います。


その他の micro web framework

"micro web framework" としては他に Spark Framework というものも人気があり、
パスを レスポンス にマッピングするという思想が、jooby と似ています。

簡単さという点では、 jooby よりもさらに簡単です。
ただ、細かいハンドリングが場合は jooby のほうがやり易そうです。また、 MODULES による拡張性の面でも jooby のほうに軍配が上がるかと思います。

利用する局面に応じて どちらがいいか比較してみてください。


jooby いかがでししたでしょうか。

それでは ごきげんよう


関連ページ

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away