ikeike443のブログ

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

第3回Playframework勉強会 #play_ja をやりました

http://playdocja.appspot.com/assets/images/logo-ja.png

去る7月14日、勉強会をやりました。

下記がその要項です。
http://playframeworkja.doorkeeper.jp/events/1231-%E7%AC%AC3%E5%9B%9Eplayframework%E5%8B%89%E5%BC%B7%E4%BC%9A-play_ja

70人で募集をかけたところ、3時間で満席になってしまいました。本当にありがとうございます。
最終的にはキャンセル待ちの方が75人にまでふくれあがりましたが、実際のところ現場に来場されたのは54人でした。

場所は@i2keyさんのご好意で、リクルートメディアテクノロジーラボさんの超シャレオツな会場を借りることが出来ました。
本当に本当にありがとうございました!

Ust録画

下記の通りバッチリあります。
リクルートメディアテクノロジーラボさんの開場は、いろいろ設備が充実していて驚愕です。
とてもクリアにスライドが録画されている上、音声もマイクでバッチリ拾えているので、この上ない臨場感です!



Video streaming by Ustream



Video streaming by Ustream

当日のタイムテーブルと資料一覧


























発表者タイトル
@ikeike443  Playアップデート
@i2key さん

 MediaTechnologyLabsの紹介


 Play2.0+JavaでAPIサーバを開発しているiPhoneアプリの紹介 


@tototoshi さん  Play20 + Scala について
@kara_d さん

 2.0Javaのオススメと、1.2からのアップグレード


@daiksy さん  Play2.0 + Scala での開発事例

LT分






























発表者タイトル
@garbegetown さん  ドキュメント翻訳について
@masahito さん  Play2.Xドキュメント翻訳について
@seratch さん  plugin 開発の導入
@たけぞう さん  ;Play1.2.X系+Scalaの話
@gakuzzzzさん  Play20-auth の話か DDD on Play20 みたいな話
@puriketu99 さん  おしべめしべシステムからplayをはじめよう


というわけで、またやりましょー。次は4ヶ月以内くらいにこれくらいの規模でまたやりたいです。

JJUG CCC 2012 Spring で講演しました

JJUG CCC 2012 Spring で講演してきました。

全くPlayを知らない人を対象に、そもそものところから説明を始めてライブコーディングで動きを見せ、その後一気に機能を網羅的に説明するというてんこ盛りの内容でした。

とにかくキーワードだけ全部言って、みんなの脳髄にクサビを打ち込んでしまえ! という思いでやりました。
概ね好評だったっぽく、よかったです。
会場も超満員でした。お声掛けくださった阿島さんのお顔を立てることも出来たのかなー、と思います。

これをきっかけに、日本でも利用事例が増えるといいなと思います。

Twitterでも下記のようにつぶやきましたが、


本当に僕を利用してもらって構わないんです。ぜひ上手く利用してください。

日本のSIerさんの現場でも全然普通に使えると思うんですよね。だって、


これ本当なんです。全く問題なかったですよ。
この話しはPlay1ですけど、Playの素直なAPIはスキルのあまり高くない方でもすんなり使いこなせるようになりますし、むしろPlayを通してWeb、HTTP、RESTについて学習することができるくらいです。
オススメです。


講演しただけでなく、GrailsScala、モバイルHTML5についての講演を聴きました。
Grailsも面白そうですね! 実は2010年に業務でPlayを採用するときに、Grailsも候補にあったんですよね。でもGroovy覚えるのが面倒でPlayにしてしまいました。。Playのコミュニティには、Grailsから流れてきた人も多いみたいなので、みなさんお待ちしてますよw
水島さんのScala Daysの報告も楽しく拝聴しました。2.10の新機能の紹介も面白かったです。どんどんRubyっぽい機能増えるんだなーと思いました。いいと思います。RubistをもっとScalaに引き込むべきだと思いますし!!
モバイルHTML5の講演は一番面白かったですね。TIZENの出来の良さに驚きましたし、Mozilla Phoneは自分で携帯電話作れちゃうってのがスッゲー楽しそうと思いました。プレゼンもすごくこなれた感じで面白かったです。こりゃー、モバイルでHTML5アプリ、来るな!って思いました。


懇親会ではJavaのプロジェクトLambdaの進捗の遅さ、クロージャーが入らなかった経緯などから、Javaはやっぱり後方互換性を最重要視していて、これからの時代の先端を走るのはちょっと無理かもねーって話をしてました。JVMは素晴らしいプラットフォームだから、今後は時代の先を行く試みはJava以外のJVM言語で行われていくんじゃないかなーって話で盛り上がりました。(例えばScalaとかね!)


ちなみにJJUGには初参加でした。初参加で初講演というのも乙ですね!
また誘ってください!!

ドメインオブジェクトからJSONへのアンマーシャルがだるい

このページの説明を見ててあーダルいなと思いました。

import play.api.libs.json._

case class User(id: Long, name: String, friends: List[User])
  implicit object UserFormat extends Format[User] {
    def reads(json: JsValue): User = User(
      (json \ "id").as[Long],
      (json \ "name").as[String],
      (json \ "friends").asOpt[List[User]].getOrElse(List()))
    def writes(u: User): JsValue = JsObject(List(
      "id" -> JsNumber(u.id),
      "name" -> JsString(u.name),
      "friends" -> JsArray(u.friends.map(fr => JsObject(List("id" -> JsNumber(fr.id), "name" -> JsString(fr.name))))))) 
  }

上記みたいなコードを毎回書くのだるい。

特にアンマーシャルはダルいので、下記みたいなコード書いてみた。


こう呼び出します。as("application/json")がダサいなあ。もっといい方法あれば教えて下さい。

case class User(id: Long, name: String, friends: List[User])
def sendJson() = Action {
    val peter = User(2, "peter",  List())
    Ok(toJson(peter)).as("application/json")
}


マーシャルは、まあまた今度考えよ。。

追記

totoshiさんがlift-jsonを使ってもっとイージーに書けるようにしてくれました。
あざーす。
http://d.hatena.ne.jp/tototoshi/20120526/1338032893

Erwanと飲んだ

最近公私ともに飲み歩いていて気がついたら1週間も経ってたよ。。
f:id:ikeike443:20120518003238j:image
※この写真は@choreostarさんに撮って頂きました。2次会で飲み過ぎて終電逃した3人の図です。あざす。



Playframeworkのコアメンバーでフランス人のErwan Loisantと5月10日に飲んだ。
Erwanが日本語をよく理解しているのはなんとなく前から知ってたんだけど(Play1.0.1の頃のPythonコードのひどさについてTwitterでブツブツ言ってたら日本語で絡まれたのが最初で、その時に日本語上手だなこのフランス人と思ったんだよね)、初めて会ってしゃべってみて、こんなにペラペラだとは思わなかった。

奥さんが日本人らしい。大学院は東京都立大(今の首都大学東京)らしい。大学院の後はシリコンバレーで働いてたらしい。その後フランスに帰ってZenexity(Playの会社)に移ったらしい。



Playの運営の仕方とか、Zenexityがどういう仕事をしているかとか、Guillaumeはどういう人か、とかNicolasやPeterはオランダ人だけど、パリからロッテルダムへは電車で4時間だからそこまで遠くないとか、ノルウェーのMortenは1.xを中心に活動してるとか、NYのPeterはPlay2のメンテのためにTypesafeに入社した人だとか、Guillaumeはプログラミングが上手いけどすごく無口で無愛想だとか、Sadekはシリアの人だったけど最近フランス国籍とったとか、フランスはすべての道がパリに通じてるせいで、国の端から端に行くのがすごく不便だとか、第二次大戦の話とか、そういう結構どうでもいい話をしました。



先ごろMLで盛り上がってた、Play1と2をプロジェクト分けて別物として開発しようよ、みたいな動きについては、GuillaumeはPythonの2系と3系の分裂っぷりを見てるから、もうあんまり1をプロモーションしたくはなみたいだけど、1が好きっていうユーザーも結構いるから悩んでるみたい。Playのプラグインも、1の時にみんなから自由に募ってみたら、最初はみんなつくるけどすぐにメンテしなくなって陳腐化したものが多かったから2ではどうやって運営しようかなーみたいに思ってるみたい。*1



日本でPlay絡みのイベントやるとして、GuillaumeやErwanを呼んだら来てくれる? って聞いたら、PlayとZenexityにとってメリットがありそうなら、お金なくても全然来る、と言ってました。結構乗り気だったよ。
ポイントは? と聞いたら、やっぱとりあえずは集客人数かなーってことだった。


というわけで、近々第三回Playframework勉強会について告知するので、是非みなさん参加してください。

特にScala絡みの人の参加が今まではなかったので、ぜひぜひ。


また、地方でも読んでくれれば行きます! 僕でよければ。

*1:まあこの辺はコアメンバーの中でもみな思惑が違いそう。。まあなんにせよ、1.x系はもうすぐ1.2.5が出るし、1.2.6もその後出ます。1.3はどうするか分からないけど、ユーザーが多ければ出すんじゃないかね。

Playframeworkのコミッターになりました

既にMLやTwitterなどで紹介していただきましたが、改めて自分のブログで報告しておきます。

f:id:ikeike443:20120414020116p:image:w300
Playframeworkのコミッターになりました。
http://www.playframework.org/code/team

Playframeworkとは1.0.1が出始めたくらいの頃からの付き合いで、未実装の機能を追加したり、バグを直したりしながらずっと使ってきました。

おかげで務めている会社には1.0.3.3で稼動しているアプリケーション、1.1.1のアプリケーション(これは1.2.4にあげたかも。。)、1.2.4で動いているアプリケーションが多数稼動しています。

直しながら使っていたので、1.xの内部のコードは大分読みました(最近チョット忘れてるんだけど)。そんな中、Playのコアメンバーの人数が足りなくて困っている(2.0に注力しているせいで、ユーザーの多い1.xのメンテが追いついてない)ようだったので、手を挙げることにし、無事採用してもらいました。

これを機に、日本Playframeworkユーザー会ももう少し真面目に運営しようかなとか、日本での普及活動をもっと積極的にやっていこうかな、なんて考えています。

私は日本語を話す日本人なので、日本人がコアメンバーの一人として参画しているフレームワークであれば、日本のシステム開発の現場への導入にも助けになるんじゃないかなと考えています。

というわけで、今後とも私共々、Playframeworkのことをよろしくお願いします。

なぜ Play は Servlet を使っていないのか(Why there is no servlets in Play 翻訳)

まだ正月休みなのです。暇なので訳してみました。


この記事は 1年半以上前に Play の生みの親である Guillaume Bort がブログに書いたものです。
(2012/8/19追記: リンク切れしていたためリンクを貼り直しました)

なぜ Playframework では Servlet が一切使われていないのかについて、簡潔に書いています。

丸山先生が Play に注目し始めた今、Play2.0 のリリースが間近に迫った今、あらためて読むと面白いかも知れません。



なぜ Play は Servlet を使っていないのか


Servlet API に準拠せずに Java web フレームワークを作ることはかなり変に思えるかも知れない。大抵の人はなぜこんな普通じゃない選択をしたのかを聞いてくる。気に入ってくれる人も何人かいるが、大半は毛嫌いする。正直に言うと、 Play フレームワークの一番最初のバージョンは Servlet を使い、Servlet コンテナの上で稼働するようになっていた。しかし、この要件を外すに至ったのには幾つもの理由がある。説明してみよう。


Play フレームワークの重要な特徴は2つある(他にも多くの特徴がある中でも): 完全なステートレスアーキテクチャモデルの上に構築されていること、魔法のように自動的にコードの変更を反映すること。実際、この2つの特徴は密接に重なり合っている。


コードのホットスワップを可能にするには、アプリケーションをステートレスに作ることが欠かせない。あなたは疑問に思ったことはないだろうか。なぜ PHP ではホットスワップ出来るのに、JEE だと出来ないのか、と(ここで言っているのは、バックグラウンドで war をデプロイし直すのではなく、本当にアプリケーションコードをホットスワップするという意味だ)。PHP に出来るのは PHP は徹頭徹尾ステートレスだからだ。PHP の場合、2つの連続したリクエストの間で、都度まっさらな新しいプロセスが起動する(確かに今は FastCGI を使っていくらかの最適化を図ることがあるが、根本的なモデルを変更するわけではない)。アプリケーションがステートレスでなかった場合、コードスワップの後にメモリ上の状態を再構築することなんてできない。きちんと動くケースもあるだろうが、重要な変更があった場合はまず動かないだろう。


Play をステートレスな web フレームワークとして作ることにした理由は、コードのホットスワップを実現したかったからだけではない。この話はこのポストの論点ではないが、基本的に、WEB 自身がステートレスアーキテクチャを採用しているのがその理由だ。そして WEB がステートレスアーキテクチャを採用していることにも幾つものとてもいい理由がある。


Servlet API を使ってステートレスなアプリケーションを作ることは可能だ。しかし、HttpSession や servlet の forward の仕組みなどを使わないようにしなければならない。Play フレームワークの一番最初のバージョンではそんな風にやっていた。


しかし正味の話、皆 servlet API が好きだから使っているわけではない。Servlet API がこれまで考案された HTTP API の中でもダメな部類であるという事実には皆同意している。だが、servlet filter とかその他色々な servlet に依存したコンポーネントを再利用したいがためにこの API を使っているのだ。


これらのコンポーネントは、大抵の場合設計がまずいという問題を抱えていることが多い。開発者の知らないところで、HTTP リクエストのオブジェクトとレスポンスのオブジェクトをごっちゃにしてセッションに格納したりする。だからこのようなコンポーネントをインストールすると、Play の初期処理で行っているステートレスな取り決めを破壊したり、クラスのリロードやキャストに多くの問題を引き起こしたりする結果になり得る。これは Play で書かれたアプリケーションコードをリロード出来るようにするために、コードを Play のカスタムクラスローダーの中で動かしている理由でもある。そして Servlet コンポーネントServlet コンテナのクラスローダーの中で動いている必要がある。これらのコンポーネントを協調して動かす必要があるのだろうか? もちろんあなたにはあるだろう。そしてそれは悪夢となる。


実際のところ、Servlet ベースのコンポーネントには2種類ある。私がこの問題に直面したのは、Play 用の captcha ライブラリを探していた時だった。2種類あるうちの一方に属するライブラリ群の作りは、2つの層に綺麗に分かれていた。1つは captcha を生成するロジックで、もう1つは Servlet API との結合だった。もう一方に属するライブラリ群はぐちゃぐちゃにコードが折り重なっていて、Servlet API なしには利用することが出来ない作りだった。よく出来ている方のライブラリを Play にインストールした場合、Play のユーザーはそれを使って本来の面白い部分を作ることに集中することが出来るが、ダメな方のライブラリをインストール出来てしまった場合、ユーザーのアプリケーションは壊れてしまう可能性が高いだろう。


最後に、我々が Servlet API を金輪際使わないことにしたのにはもう一つ理由がある。Servlet コンテナはオールドファッションな ”1リクエストにつき1スレッド” モデルを採用している。幾つかのアプリケーションにとってはそれでも問題ないだろう。だが、Ajax とロングポーリング呼出しが必須となった今日において、これでは不十分だ。


根本的な問題は、 JEE サーバと HTTP 層を結ぶには Servlet APIを使う以外に選択肢がないことだと思う。おそらく、 java のエコシステムには Rack の様なものが必要なのではないだろうか。つまり、HTTP を扱う本当に低レベルでポータブルな API が必要だと思う。少々欠陥のあるアーキテクチャ原則に基づいて構築された、半ばでたらめな HTTP API ではなく。

Play! framework 概要 Tipsもあるよ!

Play! Advent Calendar 2011 一日目ということで、軽めの話をします。

おさらい:Play!とは

Play!はJavaで軽量に素早く開発できるフレームワークです。


Play!についてよく知らない人が圧倒的多数だと思いますので、ものすごく簡単に説明しますね。


Play!はJavaEEの仕様を捨ててWebとフォーリンラブすることに決めたフレームワークなので、Servlet特有の変なセッション仕様なんてないですし、えっと、セッションレプリケーションってなんですか? ってなノリのフレームワークです。
もちろん、warにパッケージングする必要もないです。


EclipseのECJを使って動的コンパイルを行うことで、ほんとうの意味でのホットデプロイを実現しています。というか、デプロイしないんですけど。。まあ、ほとんどスクリプト言語のようにJavaを使えるわけです。再起動無しで変更が反映されるって素敵。


モデル周りは、JPA、っていうかこれJPAなのかなー。。って思うくらい手を入れてますが、そのおかげでPlayではDBスキーマの変更もJavaのコードを書き換えるだけで自動でやれちゃいます。DBスキーマの変更も再起動無しでやっちゃうわけですね。
もちろん、この機能はプロダクション環境で動作すると危険ですので、環境によって動作を変えるなんてのも容易です。


今時のプラグインが揃ってる

プラグインシステムも用意されています。
ここを見ると分かるんですが、Javaとは思えないイケてるラインナップっぷり。
MongoDB、Redis、CoffeeScriptやSASSなんて当たり前のようにサポートされています。

Play!を好んで使う開発者っていうのが、どんな人達なのか、よくわかると思います。
HerokuがネイティブにPlayをサポートしたのも当然だなあなんて思いますね。

ノンブロッキングもあるよ!

また、最近Node.jsで注目度を高めたノンブロッキングI/Oもサポートしています。興味のある人はこのへんのコード*1や、このへんのコード*2を読んでみるといいと思います。また、多分誰かがこの辺詳しく突っ込んでくれるでしょう!


これでノンブロッキングI/Oといえば、JavascriptならNode.js、PythonならTwisted、RubyならEventMachine、JavaならPlay!と言えるわけです。よかったですね!


Node.jsとPlay!を比較した記事なんかもありました。レンダリングを除いたI/O部分だけ見れば、Play!はNode.jsに比肩する部分もある(2011年3月時点の話)んですよね。レンダリングを含むとNode.jsには全然勝てないんですが。。
詳しく知りたい方は、翻訳しておいたので下記を見てください。まあこの記事は半年も前なのであまり参考にはならんかもですが。。
https://www.evernote.com/shard/s18/sh/d356225c-93ab-4fb2-9a7c-178eb23045e9/d82052027a5bb481579eaa4691d53dfb



そしてScalaへ、そしてPlay2.0へ

っていうここまでが、Playの1.x系のお話。
このへんの話はこのスライドにもまとめてあるので、ぜひ読んでください。


で、こんなイケてるフレームワークを作ったPlayの連中は、やっぱりJavaの世界では異端児なのか、それほど広く受け入れられてるとは言いがたいと思います。特に日本国内では知名度含めて結構絶望的ですし、JavaEEを完全無視しているせいで、キワモノ扱いを受けてますね。


彼らはScalaをサポートし始めました。1.1からScalaプラグインを作ってサポートを始めます。
日本国内では、このへんのエントリをきっかけに、ScalaフレームワークとしてPlay!がプチブレイクし始めた感ありますよね。


そして、Play2.0です。

彼らはついに、Play!をScalaフレームワークとして一から書きなおし始めてしまいました。*3

この判断が正しかったかどうかはまだわかりません。大きな賭けだと思います。ただ、このままJavaのちょっと変わったフレームワークとしての地位に甘んじるよりも、Scalaの未来に賭けよう、という姿勢を僕は支持します。


2012年はPlay!とScalaの年になるでしょう。
"Play2 with Scala in Action"という書籍も出ますし、なによりScalaの総本山であるTypesafeがPlay2.0をテクノロジースタックとしてサポートすると表明しましたから。


という訳で、一日目はPlayの概要についておさらいして見ました。
これだけで終わると寂しいので、1.x系のTipsを幾つか紹介します。

Play! 1.xのTips

  • CookieにSecureフラグを付与する

httpsCookieをやり取りする際は、secureフラグを立てたいのが普通だと思います。
Play!はデフォルトのままだとsecureフラグを自動でたてたりはしてくれませんので、明示的にapplication.confに下記を設定してやる必要があります。

application.session.secure=true

この辺は、私が1年半前にバグ報告した結果付いた機能です。昔はこれも出来なかったんですよね。。
http://d.hatena.ne.jp/ikeike443/20100505/1273040748

  • Memcachedハマリ道(というかapplication.confの癖に注意)

Play!でmemcachedを使うのは簡単で、application.confに下記のように書いてやるだけで動きます。

memcached=enabled
memcached.host=xxxx:11211

memcachedを複数台立てて分散させたい場合は下記のように書くだけです。これだけでPlay!のCache API(の中で使われてるspymemcached)がよしなにしてくれます。

memcached.1.host=xxxx:11211
memcached.2.host=xxxx:11211
memcached.3.host=xxxx:11211
...


ところがちょっと罠があって、例えば開発環境においてはmemcachedサーバは一台しか立ててないけど、ステージング環境では複数台立ててますよ、みたいな状況で例えば下記のように設定してしまうと。。

#開発用
memcached.host=hogedomain:11211
#ステージング用
%QA.memcached.1.host=fugadomain:11211
%QA.memcached.1.host=bazdomain:11211

実はこうしてしまうと、Play!はIDなしの設定(memcached.host=hogedomain:11211)をIDありの設定よりも優先して有効化してしまうという癖がありまして、ステージング環境でもhogedomianのmemcachedを見に行ってしまい、想定外の挙動をしてしまってパニック、ってな感じのハマリ方をします。はい。昔ハマリました。。

なので、解決策としてはIDなしの設定をやめてしまって、開発環境にも明示的にIDを振ってやる、というのが解決策かなーと思います。

つまりこんな感じ。

#開発用
%DEV.memcached.host=hogedomain:11211
#ステージング用
%QA.memcached.1.host=fugadomain:11211
%QA.memcached.1.host=bazdomain:11211


この話、memcachedに限らず、log4jもそうですし、その他の割とあらゆる設定について言えることですので、覚えておくといいと思います。

  • Jobを環境によってOn/Offする

Play!には非同期Jobフレームワークが存在します。
play.jobs.Jobを継承して、@Everyか@Onといったアノテーションを書いておくと、それにしたがってスケジュール実行してくれる便利な機能です。詳しくは以前書いたのでこちらを見てください。

例えばこの機能を使って、あるサービスのAPIを定期的に叩いてデータを収集する、みたいなコードを書いたりするわけです。
プロダクションはそれでいいのですが、自動テストを組んだ時に困るわけです。
実はPlay!のauto-testコマンドの実行時に、Jobも動いてしまうんですよね。

というわけで、環境によってJobをOn/Offできるようにパッチを書いたのです。
http://d.hatena.ne.jp/ikeike443/20100824/1282656188


この機能を使えば、例えばapplication.confに下記のように書いておくだけで、環境によってJobのOn/Offを制御できるわけです。

%DEV.cron.JobA=5min
%DEV.cron.JobB=*    0    *    *    *    ?
%PROD.cron.JobA=5min
%PROD.cron.JobB=*    0    *    *    *    ?
%test.cron.JobA=never
%test.cron.JobB=never

ぜひご活用ください。

  • Dependencies

最後にDependenciesのTipsです。
Dependenciesコマンドを使うと、内部でivyが実行されて、依存関係の解決をやってくれます。
Mavenリポジトリにあるものや、Playのプラグインリポジトリにあるものは暗黙的に解決してくれますし、それ以外のライブラリを解決したい場合は、dependencies.ymlに下記のように書けばいいです。

require:
    - play
    - Some -> SomeLib 1.4
    - Some -> SomeUtil 0.5
repositories:
    - SomeExternalLib:
        type:       http
        artifact:   "http://somedomain/repo/Some/[artifact]/[revision]/[artifact]-[revision].[ext]"
        contains:
            - Some -> SomeLib 1.4
            - Some -> SomeUtil 0.5

ただここで問題なのは、repositoriesのtypeです。
typeをiBiblioにすれば、Maven的に解釈してくれるので(バージョン番号じゃなくてmd5見て変更検知してくれる)、本来はそれでいいんですが、事情によりhttpにしたい場合ありますよね。

httpにしてしまうと、ライブラリに変更が入っても検知してくれないんですね。
というわけでちょっと(かなり?)強引ですが、ivyのキャッシュを強制クリアするオプションを作って取り込んでもらいました。
https://github.com/playframework/play/pull/322


これは次の1.2.4でリリースされると思うので、dependenciesで困ってるひとは活用してもらえると嬉しいです。キャッシュのクリアがかなり強引ですがね。。



以上です。次は@kara_dさんです。僕よりもさらに輪をかけたPlayラバーなので、期待できると思います!!

*1:Promiseが出てきます

*2:Continuationの実装があります

*3:ちなみにJavaも動きます。1.xはJavaで書かれたScalaも動くJavaフレームワーク、だったのが、2.0は逆にScalaで書かれたJavaも動くScalaフレームワーク、になったわけです