ikeike443のブログ

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

Playframework勉強会やります

今週の土曜日に、Playframework勉強会を執り行ないます。
http://atnd.org/events/19107

あいにく既に満席ですが、当日になってキャンセルされる方がでる可能性もあります。

興味が有る方はとりあえず補欠登録してみてください。当日来てみたら入れた、って可能性は充分あります。


当日来場が難しい方は、Ustで御覧ください。

下記がUst放送予定地です。
http://www.ustream.tv/channel/playframework%E5%8B%89%E5%BC%B7%E4%BC%9A


SalesForceエバンジェリストの方もいらしてPlay on HerokuについてLTでお話ししてくれますし、楽しい勉強会になるといいなと思います。

Play! on Heroku 翻訳

HerokuがJavaのみならず、Playframeworkをネイティブにサポートすると発表しました
以下はその翻訳です。一部意訳したりしてます。翻訳の間違いなど、是非ご指摘ください! Play!いいよね!


Play! on Heroku
by Jesper - 8 hrs ago


JavaRubyの両方を経験しているWeb開発者はしばしば疑問に思うことがある。なぜJavaのWeb開発はこんなにややこしいんだ? Ruby, 特にRailsで開発するとこんなにシンプルなのに。
この疑問に答える方法はたくさんある。しかし重要なのは、Java言語そのものに問題があるわけではないということだ。Play! Frameworkの中の人たちが、RubyにおけるRailsのように、エレガントで生産的なWebフレームワークを作り、そのことを証明してみせた。


ここに、Play! on Herokuのパブリックベータをアナウンスできることを大変嬉しく思う。


Play! on Heroku クイックスタート


Play!のver.1.2.3以降をダウンロードし、Play!アプリケーションを新規作成してみよう:

$ play new helloworld
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2.3, http://www.playframework.org
~
~ The new application will be created in /Users/jjoergensen/dev/tmp/helloworld
~ What is the application name? [helloworld] 
~
~ OK, the application is created.
~ Start it with : play run helloworld
~ Have fun!
~
$ cd helloworld

次にProcfileを作成する:

web: play run --http.port=$PORT $PLAY_OPTS 

Gitにコミットし、Cedarにアプリを作成し、デプロイする:

$ git init
$ git add .
$ git commit -m init

$ heroku create --stack cedar

$ git push heroku master
Counting objects: 30, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (22/22), done.
Writing objects: 100% (30/30), 35.95 KiB, done.
Total 30 (delta 1), reused 0 (delta 0)

-----> Heroku receiving push
-----> play app detected
-----> Installing Play!..... done
-----> Building Play! application...
       ~        _            _ 
       ~  _ __ | | __ _ _  _| |
       ~ | '_ \| |/ _' | || |_|
       ~ |  __/|_|\____|\__ (_)
       ~ |_|            |__/   
       ~
       ~ play! 1.2.3, http://www.playframework.org
       ~
       1.2.3
       Play! application root found at ./
       Resolving dependencies: .play/play dependencies ./ --forceCopy --sync --silent -Duser.home=/tmp/build_2rgcv7zjrtyul 2>&1
       ~ Resolving dependencies using /tmp/build_2rgcv7zjrtyul/conf/dependencies.yml,
       ~
       ~
       ~ No dependencies to install
       ~
       ~ Done!
       ~
       Precompiling: .play/play precompile ./ --silent 2>&1
       Listening for transport dt_socket at address: 8000
       16:14:33,716 INFO  ~ Starting /tmp/build_2rgcv7zjrtyul
       16:14:34,372 INFO  ~ Precompiling ...
       16:14:37,656 INFO  ~ Done.

-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size is 26.2MB
-----> Launching... done, v5
       http://blazing-water-545.herokuapp.com deployed to Heroku

デプロイできたら、URLにアクセスして、Herokuの上でPlay!が動いていることを確認しよう。


ラジカルなアプローチ


JavaでWebアプリが書かれれば書かれるほど、Web開発を簡単にしようと試みるフレームワークが増殖していく。しかしこの問題にクリーンルームアプローチで取り組もうとするフレームワークは存在しなかった。皆、サーブレットコンテナやJSPとの互換性を保たないといけないと思い込み、スタンダードなJavaのWebアプリ構成に準拠しようとし、Javaオブジェクト指向の原則に適合させようとしてきた。時にはそれが無理なことだと分かっていても。


Play!はフレッシュな状態から書かれた最初のJava Webフレームワークだ。Railsから多くのアイディアを拝借し、built-for-deploymentなフレームワークとして作られている。Play!アプリケーションはパッケージにしたり、配布したり、といったことは意図されていない。そのままデプロイ出来るように作られている。これはJavaのネストしたパッケージ構造や、XMLによる制御を捨てることが出来、WARファイルのことを忘れることができ、代わりに分かりやすく、生産的なプロジェクト構造を保つことが出来る。


例えば、helloworldアプリは一個のJavaクラスからなるコントローラによって作ることが出来る:

package controllers;

import play.*;
import play.mvc.*;

import java.util.*;

import models.*;

public class Application extends Controller {

    public static void index() {
        render();
    }

}


このクラスはindex()というメソッドによってHTTPのエントリポイントを定義している。このメソッドはindex.htmlというテンプレートファイルに対して、render()というメソッドでレンダリングを行っている。


定型的なクラスもなければ、XMLの設定ファイルも必要ない。Play!は規約をフレッシュなアプローチで提供している。そして意味の有るところではStaticコードを使う。例えば、コントローラのエントリポイントはステートレスであり、オブジェクト指向であるよりもHTTP指向であるべきなので、Staticメソッドとして実装されているのだ(上記index()メソッド)。


他にも、開発者にとって嬉しい機能が付いている。例えば開発時の自動コンパイルだ。君も、他のJavaのWebフレームワークに比べて、Play!のドラマチックとでも言うべき生産性の高さを目のあたりにすることになる。

コンテナレス


Jettyと言えばコンテナレス開発の筆頭だった。ただ、十年以上もの間、たった一人でその場に立ち続けていた感じだ。
その使い勝手はちょっと悪いことがあった。なぜなら、コンテナレス開発をしていることを意識しないといけないからだ。Play!はコンテナレス開発およびデプロイのやり方をシンプルかつエレガントに提示してみせた。プロダクションで使うには、プロジェクトを丸ごとアップロードして、play run --%prod を実行するだけだ。


Herokuはまさにこのやり方にあうようにデザインされていた。Play!アプリは自然なホームをHerokuの上に見出したことになる。Herokuの上で開発するには、ローカルでplay runしてテストまたはforman startすればいい。デプロイの準備が出来たら、プロジェクト全体をそのまままるごとgit push heroku masterするだけだ。するとHerokuはそれをプロダクションモードでplay runする。このデプロイ方法はシンプルで、開発とプロダクションの差異も理解しやすいものだ。実際、ローカルで実行したのと全く同じ方法でHerokuの上でも実行される。環境の違いによる問題は発生しない。


簡単なだけじゃない


ここまで読んで、Play!は使いやすさによるコストパフォーマンスとロバストネスに過度にフォーカスしたものなんだと結論づけたくなる人もいるだろう。結局、他のフレームワークで構築されたアプリや、高度に最適化されたライブラリを置き換える理由になるの? と。


Play!について調べると、スクラッチから作るやり方が最もパフォーマンスがいいことに気づくだろう。Play!はリクエストの非同期処理のサポートについて、一から考えてデザインされている。この技術はNode.jsやPythonのTwisted、RubyのEventMachineなどで広く採用された技術だ。


Play!はNettyを使っている。NettyはJBossチームによって開発されたノンブロッキングI/Oライブラリだ。Play!はノンブロッキングI/Oと継続プログラミングモデルを統合し、リクエストの非同期処理を実現している。

例えば、PDFのレンダリングはリクエストをサスペンドしておいて、バックグラウンドで行われる。こんなふうにシンプルに:

public static void generatePDF(Long reportId) {
    Promise<InputStream> pdf = new ReportAsPDFJob(report).now();
    InputStream pdfStream = await(pdf);
    renderBinary(pdfStream);
}

Play!はJavaのWebフレームワークにはつきもののステートフルなセッションも捨て去った。シェアナッシングモデルを取り入れることで、Play!は、ノードを追加するだけでアプリケーションを水平にスケールアウトさせることに成功した。


さらに詳しく


ここまで読んできて、Play!はただ生産的なだけではなく、楽しいものだってことが分かったと思う。すぐにアプリ作りを始めよう!

Special Thanks


ZenexityのPlay! Frameworkチームに感謝したい。特にGuillaume Bortには大変お世話になった。またErwan Loisantにはいくつかの機能要望を受け入れてもらい、Herokuに統合してもらった。

*1:[http://playdocja.appspot.com/documentation/1.2.3/5things:title=ここ]に日本語訳があります。

The First Play! meetup in Japan

The Play! meetup in Japan was held at Kronos co., LTD's seminar room on 6 Aug. 2011.
It might be the first time about play meetup in Japan.


I went to this meetup and talked about play good points I felt while using for work.
My slide is this:


I hope it was help and great info for those who bored about Java EE and Servlet programming.
Play! is fun. Java programming is also fun fundamentaly. I think.



Other people's slide are also here:


This slide is gae and siena module tutorial for Play! beginners presented by @daiksy.
Many of audience were interested about this slide and easiness for getting started with Play! on GAE.




This slide mentioned about Netty and NIO in Play! presented by @tan_go238.
@tan_go238 demonstrated a little NIO server that notify onto growl developed with Netty.



After the all presentations finished, it was free time that audience tried to use Play! and talked about the first impression about Play!.
At this free time, @kiy0taka, groovy hacker, demonstrated his first Play! app mostly written by groovy.
It was very funny. At first, this app started up groovy console in Play! view html, and then touch a model instance and do save() on groovy console.
It was joke app! but we loved it and his improvised idea. ;-p
His code is below:



This meetup was very very fun!
The next Play! meetup is coming soon!
I planned the next in Tokyo.

Keep in touched! :-)

第一回 Playframework 勉強会 in 関西に行ってきたよ!

去る8月6日土曜日、大阪の株式会社クロノスさんのセミナールームにて、第一回Playframework勉強会in関西が開催されました!
http://atnd.org/events/17724

つーわけで行ってきた!
業務でPlayframeworkを使う中で(・∀・)イイネ!!と感じたことをだらだらとしゃべってきた!
まとまってなくてごめんなさい!! スライドはこれです!


他の参加者の方々のスライドは下記です。


@daiksyさんによるPlay! on GAEのチュートリアル。
@daiskyさんのスライドとプレゼンテーションはとっても分かりやすくて、とても勉強になりました。



@tan_go238さんによるNettyとノンブロッキングI/O周りの話。
Play!は1.1から内部でNettyを使ってるんですよね。
NettyからGrowlに通知をするサンプルアプリなんかもデモしてくれて、とても充実した内容でした。


また、@s_kozakeさんによるPlayframeworkガイダンスもとてもわかり易くて、初めてPlayframeworkに触れる人にとってとてもいい内容でした。スライドアップ待ってます!
@s_kozakeさんは、Playframeworkのこのムービーの内容を暗記しているみたいで、ムービーに合わせて内容説明をするということをやってくれてました。
あれとっても分かりやすくてよかったです。


発表が終わった後、2時間くらいのフリータイムがあって、各々初めてのPlayframeworkアプリ作成にトライしました。
また、気が向いた人がLTをやる、みたいな感じで進みました。


LTの白眉は@kiy0takaさんによる初めてのPlayframeworkアプリBy Groovyでした。
ViewテンプレートにGroovyを使っていて、素のGroovyをゴリゴリ書けることを聞いた@kiy0takaさん。
ViewのなかでGroovy consoleを起動して、その中からモデルに触ってデータ更新するというアプリ(?)を作ってくれました。
Groovyで何かネタを出来ないかといつも狙っている感のある@kiy0takaさんならではですね。

コードは下記です。


最後は懇親会で酒を飲みました。
当日のTogetterまとめは下記です!
http://togetter.com/li/171094


というわけで、第一回Playframework勉強会in関西、とっても楽しかったです。


次回の開催は、私の方で主催して、東京でやろうと思ってます。
いつ頃がいいですかね?


参加したい、発表してもイイ、LTならなんかしゃべってもイイ、っていう人は、是非Twitterなどでお知らせください

Playframework 1.2 雑感

なんだかすっかり遅くなっちゃったけど、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=このチケットを参照]

PlayframeworkでHSQLDBをファイルモードで使うTips

PlayframeworkでHSQLDBをファイルモードで使う際のTips。自分のための備忘。
後でPlayのコードを読んでパッチ書けそうなら書く。

まず、HSQLDBをファイルモードで使うには、conf/application.confを下記のように"db=fs"と編集

# Database configuration
# ~~~~~ 
# Enable a database engine if needed.
#
# To quickly set up a development database, use either:
#   - mem : for a transient in memory database (HSQL in memory)
#   - fs  : for a simple file written database (HSQL file stored)
db=fs

その状態で一度play runすると、dbフォルダにdb.propertiesというファイルが出来る。
下記参照。

#HSQL Database Engine 1.8.0.9
#Sat Mar 26 17:40:28 JST 2011
hsqldb.script_format=0
runtime.gc_interval=0
sql.enforce_strict_size=false
hsqldb.cache_size_scale=8
readonly=false
hsqldb.nio_data_file=true
hsqldb.cache_scale=14
version=1.8.0
hsqldb.default_table_type=memory
hsqldb.cache_file_scale=1
hsqldb.log_size=200
modified=yes
hsqldb.cache_version=1.7.0
hsqldb.original_version=1.8.0
hsqldb.compatible_version=1.8.0

で、なぜか初期状態ではhsqldb.default_table_type=memoryとなっていて、ファイルシステムにストアされない。
これバグっぽい気がするので後で質問投げてコード読んで見る。


ともあれ、db.propertiesを下記のようにcachedに変更する*1

hsqldb.default_table_type=cached

これでdbフォルダの下に、db.dataというバイナリファイルが出来るようになる。


EclipseのDBViewerプラグインを使っているのなら、下記のように接続文字列を設定すれば、ビジュアルに中身を確認できて便利。

jdbc:hsqldb:file:/path/to/playapp/db/db;shutdown=true

ちなみにユーザーは勝手に"SA"に設定され、パスワードは空で設定されるので、接続の設定もそのようにすればいいと思う。

以上

*1:プロパティファイルの内容については[http://www.hsqldb.org/doc/guide/ch04.html:title=ここが参考になる]

第二回Jenkins勉強会でLTしてきました

PlayframeworkとJenkinsについてしゃべってきました。
LTって初めてで、5分で終わるかと思ったら終わりませんでした。。
よかったら下記から見てみてください。

Playについての詳細な内容についてはまた別途ブログに書こうと思います。

もっとPlayframeworkについて話す機会がほしいなあ。。
JGGUGid:kiy0takaさんにPlayのユーザーグループ作れば、みたいなことも言われたんですけど、仲間が全然いない。。
JGGUGに混ぜさしてもらってしゃべる機会がほしいなー。。

懇親会ではid:kkawaさん、T4Jの@yusukeyさんや@fujibeeさん、さぼてんまんさんとお話できてよかったです。

ではまた。