Play 2.0 JavaでVelocity Plugin for Play2 frameworkを使う


Play frameworkがバージョン2.0になって新しくなった機能にテンプレート機能があります。よくあるテンプレート形式のGroovyテンプレートから、静的型付けかつ、なんか妙に構文ぽい雰囲気のあるScalaテンプレートというスタイルのものに変わったのでした。
これをそのまま使ってもいいけど、Scalaテンプレートなんてちょっと一般のフロント寄りの人は受け付けないでしょう。

そういう人には、別のテンプレート言語を採用するという方法があり、そのうちの1つがvelocityプラグインです。

Furyu/play-velocity-plugin

velocityは、Apache Velocityと言い、Apacheプロジェクトの1つです。Javaで実装されています。Apacheプロジェクトということで安心感があります。
このプラグインは、Scalaベースのプロジェクトでの使用が前提として開発されており、マニュアルでも下記のような形で使えると記載されています。

object YourController extends Controller {
  def index = Action {
    Ok(VM("vm/index.vm", Map("name" -> "__name__", "title" -> "__title__")))
  }
}

今回は、これをJavaベースのプロジェクトでも使ってみましょう。
まず、プラグインを導入します。こんな風にsbtの設定ファイルに依存関係を記述します。

val appDependencies = Seq(
  "jp.furyu" %% "play-velocity-plugin" % "1.0"
)

続いて、プラグインの実行順序を規定するために下記のようにconf/play.pluginsファイルに記載します。

5000:jp.furyu.play.velocity.VelocityPlugin

まあ、ここまでは、Scalaベースと同じ感じです。
Play 2.0 Javaでは、ScalaのコードをJavaから扱うことになるので、インポートの書き方が少し変わります。
まず、下記のようにインポートを指定します。

import play.libs.Scala;
import jp.furyu.play.velocity.mvc.package$;

play.libs.Scalaというのは、JavaからScalaのコードを使ったり、逆をつかったりするために便利なライブラリで、例えばJavaのMapやList、ArrayなどをScalaのものとしてScalaで作られているライブラリに受け渡すためのラッパーとして使えます。おそらくこのファイルは今後もっと充実していく気がします。

次の、jp.furyu.play.velocity.mvc.package$という書き方ですが、velocityプラグインが定義されているVelocityPlugin.scalaでは、mvcというオブジェクト(ここでいうオブジェクトはScalaのObjectのこと)として定義されている上にpackage宣言がされているので、このような参照スタイルになると思われます。

インポートをした後で、こんな風にコントローラを書きます。

public static Result index() {
    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put("name", "__name__");
    map.put("title", "__title__");
    return ok(package$.MODULE$.VM("vm/index.vm", Scala.asScala(map), "utf-8"));
}

ポイントは、HashMapを<String, String>でなく<String, Object>にしないといけないのと、呼び出し方が「package$.MODULE$.VM(“vm/index.vm”, Scala.asScala(map), “utf-8”)」となる点です。これは、Scalaで生成されたクラスを逆コンパイルすると出てくる$つきの表記で、シングルトンとして定義されるobjectを使っているとこんな風にJavaからはStaticなメソッドとして扱う事ができるぽいです。

Scala.asScala(map)は、play.libs.Scala.asScalaメソッドを使ってScalaのMapへと変換をしています。

以上で、あとはテンプレートを任意の位置に配置することでレンダリングが行えます。

ただし、「package$.MODULE$.VM(“vm/index.vm”, Scala.asScala(map), “utf-8”)」となるのはちょっとかっこわるいので、適当なところにラッパー用のクラスを用意して対応したほうがよいと思います。
例えばこんな感じでインターフェースを持てるといいかもです。

return ok(velocity.vm("/index", map, "utf-8"));

以上、興味があったらPlay 2.0 Javaプロジェクトでも導入してみてください。

Comments are closed.