読者です 読者をやめる 読者になる 読者になる

ikeike443のブログ

ソフトウェアビジネスに関心がある系のブログ

Playframework 1.2 雑感

Play! Java Scala

なんだかすっかり遅くなっちゃったけど、Play1.2がリリースされたので、リリースノートを読みながら確認をば。

1.2 概要

全体的に、意欲的なアップデートと言えそう。
dependenciesコマンドの追加、テスト時のsurefireの出力サポート、等々、やっとCI周りがまともになり、さらにDB管理機構のEvolutionが++な感じ。
またこのバージョンからWebSocketが正式にサポートされた。
他にも非同期HTTP通信に関する意欲的な機能が追加されており、次世代な感じが満載。

依存関係管理機能がやっと追加

PlayはMaven非対応。なぜならGuillaumeがMaven嫌いだから。
MLでMavenで依存関係管理したい、っていう問い合わせがあるたび、ivy使えば、と突き放してきたわけですが、1.2でやっと機能が追加されました。
dependenciesコマンドです。
これはMavenリポジトリに配置されたJarの依存関係の解決と、Playモジュールの依存関係の解決の両方をやってくれるようです。
ちなみに内部ではivyが使われてます


dependency.yml というファイルがconfの下に追加されています。こいつに依存関係を下記のように記述してやって、

# Application dependencies
transitiveDependencies: true 

require:
    - play
    - play -> crud
    - play -> secure
    - commons-httpclient -> commons-httpclient 3.1

下記コマンドを実行してやればいいです。

$ play dependencies

するとlibの下にcommons-httpclientが入り、Playモジュールであるcrudとsecureがインストールされます。


独自リポジトリに配置されたjarを使いたい場合には例えば下記のように書きます。

require:
    - play
    - SsApi -> SsApiCommon 0.0.9
repositories:
    - Shanon:
        type:       http
        artifact:   "http://path/to/mymavenrepo/SsApi/[artifact]/[revision]/[artifact]-[revision].[ext]"
        contains:
            - SsApi -> SsApiCommon 0.0.9

こうすると、僕の所属する株式会社シャノンのリポジトリからSsApiCommon-0.0.9.jarというファイルを取ってきて、libに配置してくれます。


詳細はここを参照してください。

Surefire レポートが出るようになった

以前、Jenkins勉強会でPlayのCI事情についてLTしたときには、PlayはSurefireを書きだしてくれていませんでした。
独自のHTMLフォーマットで結果を書き出すのみだったので、少しでもJenkinsで使いやすくなるよう、プラグインを書いたわけですが、この問題も解決されました。
1.2からは、テスト実行後にSurefireを書きだしてくれるようになったので、テスト結果の集計も出来るようになり、JenkinsのようなCIサーバとの相性がグッとよくなったと思います。

バグ注意!

ちなみに、このsurefire出力にはバグがあります。*1
テストがこけると、まともなxmlを書き出せなくなってしまうので、Jenkinsなどでテスト結果を集計する最中に例外を吐きます。。
既に次の1.2.1には修正パッチが適用されていますが、1.2の段階ではバグが残っているので注意してください。

フィクスチャYAMLの中でテンプレートタグが使えるようになった

Playframeworkには、元々フィクスチャの機能があります。Railsなんかでよく見るアレですね。
テスト用にデータをロードしてくれるアレです。


1.2から、フィクスチャYAMLの中にテンプレートタグが使えるようになったので、テスト用にデータを用意するのが大分楽になったと思います。
例えば下記のようなデータを用意したい時に、

vendor.tag.AreaTag(at11):
    label:            China
vendor.tag.AreaTag(at12):
    label:            France
vendor.tag.FunctionTag(ft1):
    label:            Wedding
vendor.tag.FunctionTag(ft2):
    label:            Party

いちいち複数行に分けて書かずに、タグを使ってこう書けます。

#{list ['China', 'France']}
vendor.tag.AreaTag(at1${_index}):
    label:${_}
#{/list}
#{list ['Wedding', 'Party']}
vendor.tag.FunctionTag(ft${_index}):
    label:${_}
#{/list}

大量データのテストを書かないといけない場合などに重宝しそうですね。


上記の他にも、Playで使えるあらゆるタグが使える(つまりGroovyがほぼそのまま使えるということでもある)ので、工夫次第でかなりのことができそうです。

DB変更管理が可能になった

Railsでいうマイグレーションに当たる機能になると思いますが、Evolutionという機能が追加されました。
DDLの変更の追跡、コンフリクトの解決、等々を面倒みてくれる機能のようです。
JPAを使っていれば、開発中はauto-updateの機能を使って自動的にスキーマを変更してしまうのでこの機能はいらないのですが、プロダクション環境にデプロイする段になると、必要になる機能だと思います。


使い方のイメージとしては、下記のような感じでしょうか。

  • 開発中はapplication.confにddl=updateと書いておいて、スキーマを自動更新
  • リリースの際に、dbモジュールを使ってddlを抜き出し、db/evolutionsに配置しておく
  • プロダクション環境においてevolutionsコマンドを実行し、スキーマを変更する

今まではdbモジュールを使ってddlを抜き出した後は手動で変更管理をしていたので、便利に使えそうです。

バグ注意!

尚、このevolutionsコマンドもバグがあります。
crudやsecureのようなPlayモジュールをインストールしている場合、Null Pointer Exceptionを吐いて落ちてしまいます。。
僕が見つけたのでチケット起票し、pull requestしておきました。
既にマージされたので、1.2.1からは治っているでしょう。

WebSocketサポート、非同期HTTPサポート

WebSocketが正式にサポートされたのはとても大きいですね。まだチェックしきれてないのですが、期待大です。

また、1.1から引き続き、非同期HTTPに関する実装が追加されています。
なにが行われているかを理解するために、今play.classloding.enhancersパッケージのコードを読みながら確認してる最中なので、詳細はアレですが。。

なんか、長いリクエストによってスレッドプールが占有されないように、一回サスペンドしておいて処理が終わってから改めてレスポンスを返すようにする、みたいなことをやってるっぽいです。

また同時にチャンクレスポンスにも対応してるので、例えば下記のようなコードで、大きなサイズのファイルダウンロードに関する問題を解決することができるんじゃないかと、個人的に期待しています。

public static void generateLargeCSV() {
    CSVGenerator generator = new CSVGenerator();
    response.contentType = "text/csv";
    while(generator.hasMoreData()) {
          String someCsvData = await(generator.nextDataChunk());
          response.writeChunk(someCsvData);
    }
}

詳細はここここを是非参照してください。

非同期HTTPやWebSocketについては、もう少し理解が深まったら改めてブログに書きたいと思います。

Play Scalaが独立したサイトを持つようになった

これです。
いよいよ本気でScalaフレームワークとしてブレイクしそうですね!


いやーなかなか、Play!は面白くなってきましたなあ!

*1:[http://play.lighthouseapp.com/projects/57987/tickets/744-testrunner-create-surefire-reports-containing-malformed-xml:title=このチケットを参照]