2012年6月29日金曜日

Java 7 の try-with-resources をさわってみるを、突っ込まれる的な

はい、Javaバイトコードが読めないみけです。



本題


昨日のこのタイトルとほぼ同名の記事を書いた後にさくらばさんに

アドバイスもらいました。



おお、そういえば、いろふさんブログにもあったような…

Throwable#getSuppressed() なるものがあって、最初に投げられた例外に

そのあとに投げられた例外が保存されているようです。


気を取り直して


昨日のコードを書きなおしてみました。



catchの部分で他に例外がsuppressされていないか確認してみました。

で、実行結果がこれです。



メソッド実行中とクローズ中に発生した例外について、

メソッド実行中の例外にクローズ中に発生した例外がsuppressされているのが確認できます。

実際、どうなってんの?


さて、さくらばさんからこんなアドバイスももらっています。



というわけで、デコンパイルしてみようとしたらJDってツールがダウンロード出来ない…(´・ω・`)

Jadの方をダウンロードしてデコンパイルしてみました。



ところどころ残念なことになってはいますが、まあ読めますね。

メソッド実行中とクローズ中の例外に例外が発生するパターンでは…

  • 52行目のtryからが本来のtryに該当するところで、55行目のact.something()で例外が発生。
  • 63行目と64行目の条件はtrueになるので、67行目のact.close()を実行して例外が発生。
  • 二度目に発生した例外は69行目のcatchで捕まって、71行目で最初に発生した例外にaddSuppressed(java.lang.Throwable)される。
  • 76行目以降の同じようなコードはここまで例外が発生しなかった場合のautoclose()処理ですかね。
  • 92行目以降のe;ってなってるのは本来のJavaコードのcatch部分で、各例外のハンドリングが実施される。

といった感じでしょうか。

なるほど、こういう風にコンパイル時にコードが展開されるんですね。

副作用


というわけで、昨日の記事を訂正したんですが、

どうやらバイトコードに興味を持ちました。

で、そういったあたりをTwitterで呟いたら



ツイッター怖っ!

JavaとJUnit雑感

こんちは。

みけです。

昨日はいろんなもののリリースというか発表というかありましたね。

2012年の半分も過ぎたわけで、成果発表という感じでしょうか。

アノテーション


僕はまあ、SIerにでっぷり浸かって、目先の仕事に追われていた時期が

長かったため、最近になってやっとプログラムに目覚めた感じの

残念な中年のおっさんなわけですが、

アノテーションとかAPT、PAP-APIとかを知ったあたりで、

結構衝撃があったわけですね。

Javaでメタ情報を扱えると。


JUnit


で、その衝撃を持ったまま、

Androidテスト部の勉強会に参加して、

「テストの自動化?そんなの普通だよ」という人達の

お話を聞いたものですから、

なんとなくの勘というか直感だったのですが、

「アノテーションでJUnit回せるんじゃね?」という

妙な自信みたいなものが生まれてきました。



人間の直感というのは時に熟考よりも的確な場合があるもので、

昨日(2012/06/28)のtry-with-resourcesの記事を書いていた時に、

テスト条件をenumで回す実装を書いてて、

「アノテーションとenumをPAP-APIから使えば、

コンパイル時にテストできそうだな」という確信に似たものを

なんか持ったようです。


どうなんだろう、ちょっとやってみたい気もするなぁ…

2012年6月28日木曜日

Groovy2.0キタ━(゚∀゚)━!

こんにちわ。

みけです。

とりま


Groovy2.0が来ました。

さて、新機能として、static type checkingが追加されたようです。

というわけで、早速試してみました。


左がGroovy2.0で右がGroovy1.8.6です。

これまでは実行時まで型の安全性を保証できなかったのですが…

(とはいえ、IDEが頑張ってくれてた)

TypeCheckedをつけるだけで、あら不思議、

コンパイル時に型チェックしてくれます。


結局Groovy型安全じゃないじゃんという批判には耳を貸しません( ー`дー´)キリッ


ちなみにJava7のinvoke dynamicにも対応して実行時性能が向上したそうです。

その他いろいろについてはinfoQの記事を参照。

Java 7 の try-with-resources をさわってみる

こんにちわ。みけです。

Java6のEOLが今年(2012年)の11月に迫っています。

なので、Java6を使っている人はJava7に切り替え始めましょう。

Javaの最新7の5分の1のバージョンを使っている人(つまりJava1.4を使っている人)はとっととアップデートして下さい。

Java1.4のEOLは2008年10月30日です。

Sunと契約している場合を除いて、契約していない人たちは泣き言を言わずアップデートしましょう。


…以前も同じ事書いた記憶が…

本題


昨日(2012/06/27) java-jaの『Log.debug("nice catch!")』に行って来ました。

開催者のよしおりさん、やましろさん、いつもご苦労さまです。

まあ、ツイッターとかまとめられているので、当日の様子については

そっちを御覧ください。しんやさん本当ご苦労さまです。

で、例外ハンドリングということで、Java7の例外ハンドリング、

try-with-resourcesが話題になったので、少し調べてみました。


ggrks


まあ、調べるったって、ggrだけなんですが、

たくさんエントリーありますね(白目。

なので、詳しい話はそっちを見て下さい。


そうは言っても


僕は自分の指を動かしたことしか理解できない単純な構造をしているので、

他のブログのエントリーと同様にコードを書いてみました。



まあ、テストの形をとっているのが他のブログと少しだけ違うかな。

で、テスト条件は次のWhen.javaというenumです。



enumにメソッドが実装できるのは周知の話で、

今回はenumの各値に条件を返すような実装を与えました。

  • onConstructorメソッドはコンストラクターで例外が発生する・しないを表します。
  • onMethodメソッドはメソッドの途中で例外が発生する・しないを表します。
  • onCloseメソッドはjava.lang.AutoCloseableで定義されているvoid close()メソッドで例外が発生する・しないを表します。

まあ、コード見ればわかりますが、

テスト条件を日本語でメモっとくとこんな感じ。

  • OnConstructorOnly
    • コンストラクター : 発生する
    • メソッド : 発生しない
    • クローズ : 発生しない
  • OnConstructorWithClose
    • コンストラクター : 発生する
    • メソッド : 発生しない
    • クローズ : 発生する
  • OnMethodOnly
    • コンストラクター : 発生しない
    • メソッド : 発生する
    • クローズ : 発生しない
  • OnMethodWithClose
    • コンストラクター : 発生しない
    • メソッド : 発生する
    • クローズ : 発生する
  • OnCloseOnly
    • コンストラクター : 発生しない
    • メソッド : 発生しない
    • クローズ : 発生する
  • NoException
    • コンストラクター : 発生しない
    • メソッド : 発生しない
    • クローズ : 発生しない

そうそう、これやってて気づいたんですが、

enum使えば、デシジョンテーブル系のテストをすんなり記述できますね。

まあ、enumをテスト対象に挟みこむにはインターフェースを使わないと難しいですが…


テスト実行


テスト実行しました。

コンソール出力は次のとおりです。



これをみててわかるのはclose()メソッド中に例外が発生した場合、

  • 例外発生後に例外が発生した場合は握りつぶす!
  • 正常に終了しているときに例外が発生した場合は例外を通知する

という動きをしていますね。

まあ、リソース処理系の例外の処理ってだいたいそうですけどね…


ロギング


ちなみにSlf4jでログを出力していますが、

ログ実装はLog4jです(´・ω・`)

なお、ログ実装については



ってことで、Markerについても覚えておきたいですね。

ちなみに日本語で最も正しいMarkerの使い方は

たいちさんの『設計と実装の狭間』でだそうです。



2012年6月27日水曜日

JavaFXのApplication Threadと戯れる-その2

ニャル子さんが終わったので、アイコンを元に戻しました。

みけです。

スレッド周り


Fx-Js-JUnitの話で少しだけ触れましたが、

JavaFXアプリケーションはスレッド周りが大変です。

単品のJavaFXアプリケーションを作る分には、

それほど問題はありませんが、

JUnitと合体させたものを作ろうとすると、

スレッドに関する知識がないと

マジで難しくなります。

死ねます。

死なないで下さい。


プログラムが処理されていく順番をしっかり覚える


というわけで、マルチスレッドなプログラムの処理順を

しっかり抑えておくことが大切です。

というわけで、アプリケーションの起動から終了に至るまでの

順番をログに出力するサンプルコードを書いてみました。



これは単純にアプリケーションを起動して、

終了するだけのコードです。


クイズ


さて、ここで問題です。

Application.launch(App)の後にある

アプリ起動したというログが出力されるのは何番目でしょうか?


宣伝


7月2日に@skrbさん主催の

『第 7 回 JavaFX 勉強会 ツール特集』にてLTやります。

ユーストもあります。

ぜひお楽しみに!


答え


実行した結果を以下に示します。



アプリ起動したは、アプリ終わっちゃうの?の後に着ていますね。

要するにApplication.launch(App)の後はスレッドは残ったまま、

アプリケーションの終了を待機してしまいます。

したがって、「アプリを起動して、それから何かの操作をアプリに対して実行して」

というシナリオでテストを書く場合には、

必ず別スレッドでアプリケーションを起動する

ようにしましょう。

2012年6月18日月曜日

JavaFXのApplication Threadと戯れる

みなさんJavaFXで遊んでいますか?

みけです。

ふと気になったこと


Fx-Js-JUnitはいい感じに出来上がりつつ有るのですが、

そういえば、複数のJavaFXアプリケーションを起動できるのか

気になったので、ちょっとやってみました。




複数のスレッドからJavaFXアプリケーションを起動することで同時実行できるか確認します。




JavaFXアプリケーションはGroovyで書いているので、Class#forName(java.lang.String)

使っています。

JavaFXアプリケーションはこんな感じです。





では、おもむろに実行します。




java.lang.IllegalStateExceptionが出てますね。

アプリケーションの起動は一回までと怒られています。


(´・ω・`)

JavaFXアプリケーションの同時実行はできないようです。


じゃあシングルスレッドならどうなの?


マルチスレッドでJavaFXアプリケーションを起動できないなら、

シングルスレッドで何度も起動できるのか?

これも試してみました。




単純にApplication#launch(java.lang.Class)Platform#exit()を繰り返す

コードです。

例のごとく、JavaFXのアプリケーション本体はGroovyで記述しています。





では起動してみましょう。





一回目の起動時はちゃんと起動して終了まで行っていますね。

ただ二回目以降はすべて落ちているようです。


結論


JavaFXアプリケーションは二度以上起動することはできぬ!

2012年6月15日金曜日

Java NIO2 をいじろう - その2


続きを書くのが面倒くさくなっていました。

みけです。

今回もjava.nio.file.Pathのメソッドを見ていきたいと思います。

iterator()

そのパスに含まれるパスを返してくれるのかとおもいきや、

トップパスからのパスをiteratorにして返してくれます。

かつ、ちょっと面白いことが発生します。

groovy:000> home = System.env['HOMEPATH']
===> \Users\mike
groovy:000> dir = new File(home)
===> \Users\mike
groovy:000> path = dir.toPath()
===> \Users\mike
groovy:000> path.iterator().each { println "$it -> ${it.toAbsolutePath()}" }
Users -> C:\Users\mike\Users
mike -> C:\Users\mike\mike
===> sun.nio.fs.AbstractPath$1@44eeef95

親パスになっていると思ったら、

子パスになっている(´・ω・`)

このメソッドを使う場合は気をつけないといけませんね。


relativize(java.nio.filePath)

これは結構便利だと思いました。

あるパスから別のパスへ相対パス化してくれます。

groovy:000> ghome = System.env['GROOVY_HOME']
===> C:\Groovy\1.8.6
groovy:000> jhome = System.env['JAVA_HOME']
===> C:\Program Files\Java\jdk1.7.0_02
groovy:000> gPath = new File(ghome).toPath()
===> C:\Groovy\1.8.6
groovy:000> jPath = new File(jhome).toPath()
===> C:\Program Files\Java\jdk1.7.0_02
groovy:000> jPath.relativize(gPath)
===> ..\..\..\Groovy\1.8.6


register(WatchService, WatchEvent.Kind<?>)

一番面白そうな感じのするメソッドなのですが、

調べ上げられていません。

また、いずれの機会にか…

己を知る ( Know yourself )

あれ、なんかBloggerの入力ページが変わっちゃいましたね。

みけです。

本題


己を知るという大層なタイトルにしましたが、

別にどうってことのないこと書いています。

「オレはこういうことできるんだよ~」とか、

「オレはこういう人だ!」とか

そういう自己暗示的というか意識的なことではありません。

もっと身体に即した部分のことです。


例えば


僕は比較的早起きな傾向があります。

季節にもよりますが、朝4時には目が覚めています。

これは無意識的に目が覚めてしまうので、

どうしようもないです。

さて、こうなると、睡眠時間はちゃんと確保したいものです。

なるべく10時前には寝るように心がけています。


他にも挙げてみよう


他にどんなのがあるでしょうか?

  • ある程度作業の見通しがたったら、やる気が無くなるというか飽きる
  • 朝の6時半頃に二度寝したくなる。
  • 昼1時から3時までとにかく眠い。

僕は多分根が真面目すぎるので、最初の状況になった時に、

後になってから(ここが大事)、「なんで最後までやらないかな?」と

過度に自分を責めてしまいます。

その結果、自分で自分を傷つけてしまいます。


二つ目の点は結構一日の生活そのものに影響があって、

ここで寝てしまうと一日のやる気が無くなってしまいます。

ただ、これにはちょっとしたヒントというか、癖があって、

二週間という周期をもって、この状態に対する評価が変わります。

悪い時は、寝てしまったら、それを取り返そうと無駄に意識だけが空回りして、

結局何も出来ません。

今週は悪い方の週です。

良い時は、寝てしまっても、まあできることだけやろうと、

のんびり構えて、できることを少しだけやります。

先週はこんな感じでした。

悪い方の週だと、「今日一日何もやってないじゃん」と

また自分を過度に責めてしまいます。


昼に眠くなる現象


これは皆さん良くあることだと思います。

ガムを噛む、散歩する、コーヒーを飲むなど対策がありますね。

僕はすべて試してみた結果、全部だめだったので、

諦めて寝ることにしています。

ちゃんと昼の2時間の睡眠を取ることで、

3時から夕方6時までの生産性を向上させるということに

しています。

実際に「よし寝るぞ!」と意気込んで寝ると、

3時から6時までの3時間、

この何かをひとつやりあげるのに十分な時間の3時間が

非常に有意義になります。


結論


というわけで、皆さんも自分のことをよく知ってみるように心がけてみてはいかがでしょうか?



2012年6月12日火曜日

Fx-Js-JUnitの改良1



誰か、Retina MBP僕に下さい。

みけです。

今のまずい点


まず、まったくもっていただけないのが、Fx-Js-JUnitがエンベデッドのサーバーしか想定していないところ。

昨日のテストコードで@ClassRuleアノテーションを付与した箇所を見てみましょう。

    @ClassRule
    static public UseFxWebView fxWebView = UseFxWebView
                                                .defaultServer()
                                                .identifiedBy('JsJUnitTest')
                                                .get()

このUseFxWebViewというクラスが実はエンベデッドサーバーに依存しているのです。





ここはもうすこしちゃんとビルダーの設計をしてFx-Js-JUnitのコア(JavaFXでJavascriptのコードをJavaから呼び出す)部分とFx-Js-JUnitのエンベデッドサーバー(自プロジェクトのJavascriptを読み込めるようにする)を分離したいと思っています。

2012年6月11日月曜日

JavaFX + JUnit で javascriptのunit testできるようにしてやるんで、これからハマっていってやんよ - 4

前回のポストから約2ヶ月半、やっとできましたよFxJsJUnit。

みけです。


ひらめき


JavaFX2.0の発表を聞いた時にWebViewがwebkitを搭載するということで、

すぐにjavascriptのテストをJavaで書けるようになると閃いて、

今年の3月くらいにとりかかりました。

桜庭さんからJavaからJavascriptを呼び出すにはjavafx.scene.web.WebEngine#executeScript(java.lang.String)を叩けばよいと聞いていたので、

実際、初回に叩いてみたわけですが

JavaFXのコンポーネントはJavaFXスレッドで立ち上げないとダメということで、挫折しました。


成功?!


その後、桜庭さんのブログエントリーで色々とアドバイスを頂いたりしました。


それを参考にしてコードを書いてみたら、テスト1つは通ったのですが、複数回のテストが実行できないという残念な結果に終わりました


スレッド、スレッド、スレッド


もともと業務SEさんで、スレッドとか興味なかったのでスレッドの制御に悩みました。

3月末頃にはコードがグダグダになってきていて、どうしようもなくなっていたようです。

この頃は何に悩んでいたかというと、

  • テストを起動→Webサーバー起動→JavaFXアプリケーションを起動という順番で実行
  • JavaFXアプリケーションが起動完了したところで、何も動かなくなる

といった状態でどのスレッドで何がどうなっているかが全く?になっていました。

JUnitとWebサーバーとJavaFXアプリケーションとWebViewと4つのスレッドの同期化を図りつつ実行していかなければならないので、

スレッドの知識がない僕には何がどうなっているのか全くわからない状態でした。


Java並行処理プログラミング


そこで、スレッドで悩まないために、Java並行処理プログラミング ―その「基盤」と「最新API」を究める―を読みました。



桜庭さんの記事にもあるように4つのスレッドの制御のためにはjava.util.concurrent.BlockingQueue>T<や、java.util.concurrent.ExecutorServiceを押さえとかないと厳しいです。

僕もこの本のお陰でBlockingQueueとかがなんとなくわかるような気がしてきました。

で、やっとうまく行った実装では次のようにスレッドを作っています。


これらのスレッドにBlockingQueueで値を受け渡しさせることで同期化を図っています。


テストコード


テストコードを書く人(ユーザー)には、これらのスレッドのあたりを意識させない(隠蔽して)ようにするのが望ましい形です。

そこで、JUnitの@ClassRuleでテストクラスの実行前に準備することで、

ユーザーにはjavascriptの呼び出しだけを提供できるようにしました。

サンプルのテストコードは次のとおりです。

JsJUnitTest.groovy



コードはGroovyで書いていますが、Javaに近い形で書いていますので、

それほど読みづらくないと思います。


テスト対象のJavascriptは次のとおりです。

test.js




技術的なこと


実は苦労話ばかり書いていて、技術的なことは何も触れてないですね。

そのあたりは、7/2(月)にある桜庭さん主催の『第7回 JavaFX 勉強会』でお話しようと思います。

まあ、JavaFXの話は殆どなしで、javascriptとスレッドの話になりそうですが…


TODO


一応スタティックなWebサーバーのjavascriptのテストが実行できるようになったわけですが、

まだまだ、javascriptのJavaにおける扱いに関して不明な点が多くありますし、全然型安全でありません。

また、ajaxなどのテストも書けませんし、DOMでassertする部分のサポートも不十分です。

さらにGitHubリポジトリーも作ってないですし、今のgradleスクリプトではMac以外では動きません( ー`дー´)キリッ

というわけで、次のような課題があります。

  • Windows/Linux対応
  • リポジトリ公開
  • javascript→POJOマッピング対応
  • function型の扱い
  • ServletコンテナもしくはJavaEEコンテナ搭載

このあたりはボチボチとやっていきたいと思います。

2012年6月8日金曜日

Java NIO2 をいじろう - その1

こんにちわ。みけです。

Java6のEOLが今年(2012年)の11月に迫っています。

なので、Java6を使っている人はJava7に切り替え始めましょう。

Javaの最新7の5分の1のバージョンを使っている人(つまりJava1.4を使っている人)はとっととアップデートして下さい。

Java1.4のEOLは2008年10月30日です。

Sunと契約している場合を除いて、契約していない人たちは泣き言を言わずアップデートしましょう。


本題


さて、Java7になってから登場したNIO2をちょっといじってみたいと思います。

NIO2によって、Javaではいままで扱えなかったシンボリックリンクとか、ファイルの更新日付とか、ファイルパーミッションとかが扱えるようになりました。

その中心にあるのはPathインターフェースです。

というわけで、Pathインターフェースについて、ちょっとおさらいします。

java.nio.file.Path


まあ、PathのJavadocを見ればだいたい分かるんですが、

どういう値が返ってきているかわからないので、1つずつ試してみましょう。

C:\Users\mike>groovysh
Groovy Shell (1.8.6, JVM: 1.7.0_02)
Type 'help' or '\h' for help.
-----------------------------------------------------------
groovy:000> home = System.env['HOMEPATH']
===> \Users\mike
groovy:000> dir = new File(home)
===> \Users\mike
groovy:000> path = dir.toPath()
===> \Users\mike
groovy:000> path.class
===> class sun.nio.fs.WindowsPath

まず、Pathはインターフェースなのでnew演算子でインスタンス化することは出来ません。

というわけで、java.io.File#toPath()からインスタンスを取得します。

Windows7で実行していますが、実体はsun.nio.fs.WindowsPathです。


メソッド


では、ひとつずつメソッドを確認して行きましょう。

getFileName()

Pathの名前を返します。

groovy:000> path.fileName
===> mike

getName(int index)getNameCount()

getNameCountPathを構成するPathの要素数を返します。

getNameは引数で指定された位置のPathの名前を返します。

groovy:000> Integer.metaClass.define {
groovy:001>     collect = {Closure c ->
groovy:002>         def collection = []
groovy:003>         delegate.times {
groovy:004>             collection << c(it)
groovy:005>         }
groovy:006>         return collection
groovy:007>     }
groovy:008> }
===> groovy.lang.ExpandoMetaClass@65ad9b63[class java.lang.Integer]
groovy:000> path.nameCount.collect { path.getName(it) }
===> [Users, mike]

getParent()getRoot()

まあ、名前のとおりです。

groovy:000> path.parent
===> \Users
groovy:000> path.root
===> \

isAbsolute()toAbsolutePath()

isAbsolute()はOS用のちゃんとしたPath名であるか判断します。

toAbsolutePath()はまた、OS用のちゃんとしたPath名を取得します。

プロジェクトなどでsrc/main/resourcesとやった場合などに使えそうですね。

groovy:000> path.absolute
===> false
groovy:000> path.toAbsolutePath()
===> C:\Users\mike

続きは、その2で。

2012年6月7日木曜日

Spring Roo始めました。 その3

今日は、JSR303 (Bean Validation)の話


制約を設ける


セレブが入会する会員制クラブをつくろう!としています。

そこで、メンバーテーブルを作ります。



基本的な制約をここでかけています。

  • 名前
    • not null / 最低2文字 / 最大40文字
  • 姓名
    • not null / 最低3文字 / 最大40文字
  • 年齢
    • 最低20 / not null
  • 収入
    • not null
  • 会員登録日
    • 過去

出来上がったMembershipクラスは次のようなコードになっています。



この段階で自動生成されたテストを流します。



自動生成されたテストのデータというのは、Spring Rooが出力したテストデータ生成用のクラスMembershipDataOnDemandクラスによって作成されます。


ビジネス的な制約の導入


ところでセレブがくる会員制クラブですので、若いヤンキーニーチャンを入会させたくありません。

そこで、30歳未満の人には高めの収入(100,000ドル以上)を持っていることを制約条件に加えようと思います。

まず、テストに上の条件のユーザーの制約を書いてみます。



テストを流します。



30歳未満で収入の低い人が入会できないことを確認するテストyoungMemberCannotBeAppliedが落ちていることがわかります。

では、この条件を実装していきます。

ここで使うのがJSR303のBean Validation APIの@AssertTrueです。

@AssertTrueは指定したフィールドまたはメソッドがtrueを返すことを強制する制約です。

これを用いて条件を実装します。



では確認のためにテストを流しましょう。



追加したテストの方は通ったようですが、あれれ、自動生成されたテストは軒並み落ちていますね。

まあ、勝手に追加した条件なのでSpring Rooの方では検知できないのでしょう。よく考えればそうですね。


git


んで、よく見てみると、モデルに変更を加えた後になぜかAspectJのコードが変化しているようです。



何が変わったのでしょうか?





40文字以上だったら40文字に直してくれてたコードが、直してくれなくなっていますね。

また、年齢が20未満だったら20に直してくれていたコードが直してくれなくなっていますね。

日付についても現在より10,000,000Lだけ前に修正してくれていたコードが現在時間+αになるように変更されています。

Spring Roo君はなんてことをしてくれるんだ!


Push in


こうなったら、AspectJのコードをJavaの方にPush Inして調整する必要があるようです。

変更されてしまったメソッドにカーソルを当てた状態で、IntelliJ IDEAのRefactorメニューからPush ITDs Inを選択します。

(eclipse…知らん…)

その後、MembershipDataOnDemand.javaのPush Inされたメソッドをテストが通る(と言うよりはビジネス的に問題のないデータが提供される)ように修正します。



では再度テストを実行してみます。



はい、通りました。

結論


はい、Spring RooのBean Validation API関連の作業について見てきました。

多少面倒なところはあるもののテストデータを自動で生成してくれたり、テストを自動で生成してくれているところは助かります。

ただ、複数のフィールドにまたがるビジネス上の制約についてはRooはアホなくらい鈍感ですね。

このあたりは慣れるしかなさそうです。

2012年6月5日火曜日

"fizzになる数字をn個挙げる"をGroovyで

@irofさんのホームページの課題『"Buzzになる数字をn個挙げる"をGroovyで…やろうと思ったんだけど』

やってみました。

IntRangeとかInteger#timesとか使ったほうがいいんだけど、無駄な計算しているよなということで、

結局Integer.metaClassをいじってしまいました。



結果



多分、もっといい書き方はきょんくんがやってくれるでしょう。

Spring Roo初めてみました。 その2

プロジェクトの作り方。


以下のコマンドを打つべし。

01 project --topLevelPackage your.app.pkg --projectName pjname

データベースの設定


以下のコマンドを打つべし。

01 jpa setup --database MYSQL --provider HIBERNATE

データベースで設定できるのは次のデータベースたち

  • DATABASE_DOT_COM
  • DB2_400
  • DB2_EXPRESS_C
  • DERBY_CLIENT
  • DERBY_EMBEDDED
  • FIREBIRD
  • GOOGLE_APP_ENGINE
  • H2_IN_MEMORY
  • HYPERSONIC_IN_MEMORY
  • HYPERSONIC_PERSISTENT
  • MSSQL
  • MYSQL
  • ORACLE
  • POSTGRES
  • SYBASE

JPAのプロバイダーで設定できるのは次のプロバイダーたち

  • DATANUCLEUS
  • ECLIPSELINK
  • HIBERNATE
  • OPENJPA

その他の設定可能なオプションたち

  • applicationId
    • Google App Engine用のオプション。GAEのapplication idを設定します。
  • hostName, databaseName, userName, password
    • データベースの場所や名前、スキーマ名やパスワードを設定します。
  • jndiDataSource
    • JDBCでなく、JavaEEサーバーが提供するJNDIを用いる場合にJNDI名を指定します。
  • persistenceUnit, transactionManager
    • transactionManagerはSpringのどのtransactionManagerを使うかを設定します。persistenceUnitはJPAの環境を指定します…よくわかっていないorz


なお、Spring Rooでのjpa setupコマンドは何度でも打ち直すことが可能で、そのたびにデータベースの設定を変えられます。

開発環境では開発環境用の設定をして、実際に動かす環境ではまた別の設定をするということが可能です。

なお、Google App Engineで利用する場合は、providerDATANUCLEUSだけだそうです。

Spring Roo初めてみました。

久々にブログ書いています。


みけです。


Spring Rooとは


CUIベースでアプリを作っていけるツールです。

JavaのRADツールですね。

RubyにはRoR、GroovyにはGrailsがあるように、JavaでもRADしたいという思いから生まれたようです。


なんで?


日本ではあまりやる人いないようなので、

まあ、ニッチなところを目指して初めてみました。

書籍『Spring Roo in Action』 も手に入ったことですし。


どんな感じ?


とりあえず、次のようなモデルを作ってみました。

  • タスクを管理するモデル
  • タイトル : 文字列
  • 詳細 : 文字列
  • 終わった? : boolean

Rooだと以下のようなコマンドを入力します。



これにより、作成されるファイルが、javaファイル1つと、aspectJのファイルが5つです。













Spring Rooでは、Javaでコードを書くときに冗長になりがちな部分を単純にして、Javaのコードをすっきりさせるそうですが、

うむ、AspectJのコードだらけでんな。


僕はこのあたりはGrailsの方が好きだったりします。

Grailsのモデルなら、こんな感じでしょうか…



仕組み


AspectJもGroovyもコンパイル時にやっていることはだいたい同じで、

AspectJがコンパイル時にJavaコードにウィービングするのと同様に、

Groovyではコンパイル時にAST変換します。

RooでのコンパイルではAspectJによって、getter/setterやtoStringがJavaに入れられてからコンパイルされるのと同様に、

Groovyではgetter/setterやtoStringを一度生成してから、コンパイルされます。


まあ、まだ両方とも全然さわれていないので、また何かわかったら書こうかな…

おわり。