Play Framework 2.0 で Eclipse を使ってデバッグする

方法を知ったのがわりと後になってからだったので、早く知っとけばよかったなーという意味も込めて、
ちゃんとマニュアル読めば書いてあるはなしかもですけど、
Eclipse でのデバッグの方法をまとめておきますね。

1. Play! 起動時にデバッグコマンドで起動する

Windows で Play! サーバーを起動する場合、
次のようなコマンドを記載したバッチファイルを作っておけば便利です。

1行目の set _JAVA_OPTIONS=”-Dfile.encoding=SJIS” は、
Play! のエラーがコマンドプロンプトに表示されるときの文字化けを防いでくれます。
Java からのアウトプットが UTF-8 なので、何も設定しないと文字化けしちゃうんですよね。
かといって、次のようにコマンドプロンプト自体を UTF-8 にして

処理しようとすると、動作がとっても重くなって使い物にならないわけで。
コマンドプロンプトは cp932 のまま、Java 側のアウトプットを SJIS にするのが正解です。
なぜ cp932 でなくて SJIS か‥‥? この辺、追いかけ始めると結構面白そうですが‥‥。
とりあえず今のところ、うちの手元では SJIS で元気に動いてるから良しとしましょうか。

3行目では play debug run という風に、debug キーワードを追加して run しています。
実行するとプロンプトには以下のように表示されます

注目するのは

の1行です。

9999 番ポートでデバッグ用の dt_socket をリッスンしていますよーというメッセージ。
この 9999 番ポートを Eclipse のリモートデバッグで接続先として指定すると、
Eclipse のデバッグで socket を横取りしてデバッグできるという仕組み。
詳しい解説はここらへんかしら?

Play! 側で用意するのはこれだけです。

2. Eclipse 側でデバッグの設定

次は Eclipse 側です。
具体的には、Eclipse 上でこんな風に設定します。
まず、「実行」→「デバッグの構成」を開きます。
左ペインの「リモート Java アプリケーション」を右クリックし「新規」を選択。
play-debug-eclipse
こんな風に、接続プロパティーに「ホスト:localhost」「ポート:9999」を設定します。
設定ができたら右下「デバッグ」ボタンをクリック。

3. あとはいつものようにブレークポイントを設定して

4. Play! アプリを動作させるだけ

指定したブレークポイントでちゃんと停止して、デバッグパースペクティブを開けますし、
ステップ実行もできちゃいます。

デバッグを中止するときは、デバッグパースペクティブのデバッグビュー上の「切断」をクリック。
また、再度デバッグを行いたいときは、Eclipse の実行メニューの「ヒストリーのデバッグ」に、
さっき実行したデバッグの設定が残っています。

Play! アプリの開発も、デバッグさえできればこっちのものですよね!

Play Framework 2.0 で Windows サーバー上に本番環境を構築する

Play Framework は手元で簡単に開発環境が構築できるのが魅力です。
自分ひとりであれこれ実験するにはうってつけ。
じゃあ、本番環境を構築するにはどうすればいいのか?それもWindowsサーバーに・・・
この情報が意外と少なかったので、まとめてみました。

ちょっとメモとして書いとくと、Play Framework を利用するにあたっては、
環境や言語などに依存して、ある程度自由度が異なってきます。
Linux > Windows ですし、2.0以降では Scala > Java で自由度が違います。
あえてWindows + Javaを選択してるうちってば・・・

今回参考にした情報はここらへんです。
参考記事では Windows 7 で動作したことを確認されているようですが、
同様の手法で Windows XP、Windows Server 2008 R2 でも動作することを確認しています。

簡単にまとめると、「Distributionパッケージ」を作成し、「NettyServerをYAJSWラッパー」を用いて
サービスとして常駐しちゃうよ、という方法です。
以下、手順としてまとめてみますね。

1. アプリケーションのアプリ名とアプリバージョンを修正しておきましょう
project/Build.scala にある appName と appVersion をそれぞれお好みのものに変更します

2. コマンドプロンプトで 作成した Play! アプリのフォルダへ移動し、以下のコマンドを実行します

play dist

3. Play! アプリのフォルダ内に「dist」フォルダが作成され、以下のファイル名でDistributionパッケージが出来上がります

[appName]-[appVersion]-yyyyMMdd.zip

4. 出来上がったzipを展開します。Windowsのバージョンによっては展開時にフォルダが2重になるので注意が必要です。

5. [appName]-[appVersion]-yyyyMMdd フォルダ内に「start」というファイルがあるはずです。
これは Linux 向けのシェルファイルなので、Windows 用のバッチファイルを同じフォルダに作成します。
以下の1行を記述し、「start.bat」と名前を付けます。

java %1 -cp “./lib/*;” play.core.server.NettyServer .

最後のピリオドも必要です。
また、アプリをデフォルトの9000番ではなく特定ポートを指定して起動したいなーという場合は、以下のようにします。

java %1 -Dhttp.port=80 -cp “./lib/*;” play.core.server.NettyServer .

6. 5.で作成したバッチファイルを実行します。
起動すると、コンソールにサーバーのPIDが表示されるので、これを覚えておきます。

7. YAJSW をダウンロードして、わかりやすい場所に展開しておきます。

8. コマンドプロンプトを開き、7.で展開したYAJSWの中のbatフォルダに移動して、次のコマンドを実行します。

genConfig.bat [6.で起動したPID]

9. サービスラッパーが自動的に構成され、保存されます。サービス名はNettyServerになっていますので、
アプリ名に書き換えたいときは YAJSW/conf/wrapper.conf 内の以下の設定を書き換えます。

wrapper.ntservice.name=アプリ名
wrapper.ntservice.displayname=アプリ名

10. コンソール上でサービスを動作させる場合は yajsw\bat の runConsole.bat を起動します。
起動したサービスを停止させたい場合は、開いているコンソール上で「Ctrl+C」を入力します。

11. 誤って10.のコンソールをそのまま閉じてしまった場合や、開いたままシステムをシャットダウンしてしまった場合、
次回起動時にNettyServerが正常起動しません。
この時は、アプリケーションのフォルダ([appName]-[appVersion]-yyyyMMdd フォルダ)内にある
「RUNNING_PID」というファイルを削除すると、正常に起動することができるようになります。

12. アプリの起動をWindowsのサービスに登録することもできます。
サービスに登録するときは「installService.bat」、サービスの起動は「startService.bat」、
サービスの停止は「stopService.bat」、サービスから削除するときは「uninstallService.bat」を
それぞれ使用します。
サービス名は9.で設定した内容で登録されます。

Windows では、「play start」コマンドも正常に動作しないという話ですし、
いろいろを考慮すると、これが一番安定した本番環境構築の方法なんじゃないかなーと思います。

Play Framework 2.0 + Java + Ebean でストアドプロシージャをコールする

Ebean はモデル一体型のORMフレームワーク。
DBの型をクラスに落としこんでなんぼの仕組みです。

ORマッパーってなんじゃらほい?というところはまだ理解できてませんけどね。
ここはそのうち追々‥‥

Ebean を使ってると、クラスとDBをマッチングさせるだけで、
SQLを書く必要もほとんどなくなっちゃいます。便利です。
Play Framework と Ebean についての解説は@ITのこの記事が分かりよいです。

でも、時には直接SQLを発行してみたいときもありますよね。
ストアドプロシージャをコールしたいな~と思ったりだとか。
そういう時は、Ebeanのexecuteメソッドを使います

static int Ebean.execute(CallableSql callableSql)

CallableSqlはプリペアドステートメントを提供するインタフェースです。

実際の簡単な使い方はこんな感じ。

簡単。
SqlQueryインタフェースと違って、パラメータに名前ラベルを使えないっぽいところが玉に瑕?

さっそく実行すると・・・あれ?プロシージャ実行されない。
executeメソッドの戻り値には “-1” が返ってきます。
“-1” ってなんだっけ・・・うーん?
探っていると、execute(SqlUpdate sqlUpdate)メソッドに記述がありました。

Returns:
the number of rows updated or deleted. -1 if executed in batch.

なんだ、じゃあちゃんと実行されてるんじゃない。
じゃなんでDB側に反映されてないんだろ?

イロイロ調べるうちに、上の書き方が悪いのかプロシージャの書き方が悪いのか、
executeをコールするだけだと、プロシージャの処理が完了していないっぽい様子。
うーん‥‥どうすりゃいいっていうんよ。

詳細わかんないですが、ここらへんを参考に、
トランザクションで括って、commitを多めに発行してみましたー。どうかな?

実行実行‥‥動いたー!
最後2度commitしてることになりますけど、これでちゃんと動いてくれたからまあいっか。

ちなみに、今回のお相手のDBはSqlServer2008Expressです。
なので、プロシージャの呼び出しもSQLServer風味。

Oracleだと “{ call StoredProcedure_1(?,?) }” みたいになるんでしょうか?
Oracle詳しくないからなー。
ブラケットは自動的にBEGINとCOMMITに置き換えられるそうな。
でも、ブラケットとの間にスペースを空けないと、ちゃんと動かないよー!
みたいな議論がここらへんにあったので一応メモっておきましょうか‥‥