jBatchをgradle使ってSE環境で動かしてみる
- JSR352-Batch Applicationを試してみた(Batchlet編) - しおしお(´・ω・`)
- jBatch(JSR-352) on Java SE 環境 | 寺田 佳央 - Yoshio Terada
しおしおさんの書いたブログを見て、jBatch触ってみるかーという気になりました。
おれもそろそろjbatchかな
— いろふ@楽と雑を追い求めて (@irof) 2015, 6月 5
適当に書いてデプロイしたら動くとは思うんですが、EEサーバーどれにしようかとか面倒になったので、もうSEでやろうとなったわけです。 でまぁclasspathにjar突っ込むとかは面倒なので、gradleで出来んだろと。
てことで軽くやってみた。
たぶんミニマム構成。Batchlet
です。とりあえず動く感じ。
javax.inject
入れてないのでフィールド書いた瞬間落ちたりするけど、この辺はおいおい見ていこうと思います。
TimeUnitという物体
小ネタ。
java.util.concurrent.TimeUnit
というクラスはご存知だろうか。ご存知?なら回れ右してください。お疲れさまでした。またの機会によろしくお願いします。
...
さて、読み進めているならばご存知でないはずなので、まずJavadocのリンクをば。
J2SE 5.0 からいらっしゃるので、別段目新しくないどころか古参とも言えるクラスです。 クラスというかenumです。定義されている列挙はナノ秒、マイクロ秒、ミリ秒、秒、分、時、日の7種類。名前の通りTimeのUnitです。できることはその時間に応じた何かしら。
TimeUnit
を使えば、3日が何時間かとかすぐに出せます。忘れがちな「1日が何秒か?」とかにも答えてくれます。
long 三日の時間数 = TimeUnit.DAYS.toHours(3); long 一日の秒数 = TimeUnit.DAYS.toSeconds(1);
便利ですね!こんな使い方をしたことはありませんが。
...
なんで今回こんな記事を書いているか?それはこんなコードをなるべく見たくないからです。
// 3分スリープする Thread.sleep(3 * 60 * 1000);
3分とかコメントに書いてしまうと、コードを変更する時にコメントも変更しなきゃいけないです。二重メンテですね。で、コメントは変更しなくても動くので忘れられがちですし、変更忘れに気づいても対応は後回しにされがちです。なので書く必要がないならば書かないほうがいい。(このあたりは過去の記事を参照くださいませ。)
に対して、それっぽく書けるのがTimeUnit
さんです。
TimeUnit.MINUTES.sleep(3);
これならコメントも要らないですし、定型的な掛け算をしなくてもいいです。1000や60の意味を気にしなくて良くもなります。
掛け算せずに計算後の数字を180000
とか書いて0の数を間違えたりして、「そこで数値リテラルのアンダースコアだ!180_000
と書くんだ!」とか無理にProjectCoinを使おうとせずにTimeUnit
を使ったほうがいいと思うんです。
そんな事態に遭遇したことはないですけど。
Calendar.Builderとやらを触ってみた
知らなくても生きていけるけど、知ってるとちょっと便利っぽいもの。 みんな知ってるのかもしれないけど、私は今日まで知らなかったから書いておきます。
もともとは今日 @khasunuma さんがされていた一連のツイートからです。その中で紹介されたスライドに乗っかってたので。
Date and Time APIを使わない場合に間違いなく「使える」と思ったので書いておきます。 というかこんなクラス作ったことあるわ……。
なにものか?
FQCNだとjava.util.Calendar.Builder
になります。Calendar
クラスにネストされたstaticなクラスです。
追加されたのはJavaSE8になってからなので、それ以前には入ってないです。JavaSE7以前の環境で使いたいと思ったらバージョンあげてください:p
名前の通りCalendar
のインスタンスを作るものです。
従来の作り方よりも私の趣味には合います。使いやすいかどうかは人それぞれなところもありますので、使ってみて考えてください。とりあえずコードとか置いておくので参考にどうぞ。
Date and Time API使えば要らないんじゃ?
JavaSE8を使うからといって、Date and Time API(JSR310)を使うのが常に正解にはならないと思っています。むしろ現時点のライブラリの対応状況や開発者の理解度、運用実績などを勘案すると使用はチャレンジの領域になってしまう感も否めません。扱える体制が整っているなら使ってった方が良いとは思いますが。
なので、まだしばらくDate
やCalendar
との付き合いは続くと想像しています。
ということで、Calendar
の補助として入ったCalendar.Builder
の使い方を覚えておくことは価値があるんじゃないかと思って触ってみました。
コード
Calendar calendar = new Calendar.Builder() .setDate(2015, Calendar.MAY, 9) .setTimeOfDay(23, 47, 16) .build();
これで 2015/5/9 23:47:16 のCalendar
インスタンスがつくれます。どうでもいいですけどこの文章を書いている時間です。
第二引数の月は通常のCalendar
通り0ベースですので今まで通り基本的に定数を使いましょう。
設定していないところは勝手に今の時間が入るわけではなくカレンダーのデフォルト値(だいたい0)が入るので取り回しは良さそうです。
また、Date
インスタンスやEpoc値から設定するsetInstant
もあるので、だいたい用は足りそうだなと思いました。
setDate
やsetTimeOfDay
などのフィールドを設定するメソッドと、setInstant
の両方を呼び出すと例外になるところとかも良いですね。インタフェースを工夫すれば片方を呼べばもう一方のメソッドを呼べなくするようなBuilder
も作れますが、そこまですると過剰にも思えるのでこれで十分でしょう。
動くコードとどうでもいいコメントは、いつものごとくGitHubの方に置いておきます。
脱線: メソッド名について
GitHubに上げたコードのコメントでも書き殴っていますが、Calendar.Builder
のメソッド名を単体で見た場合に不満はありません。しかしながらこれがCalendar
クラスのbuilderであると考えると、従来のメソッド名との齟齬は気になるところです。
Instantは今までのjava.util.Calendar
の世界にはなかった言葉で、使用する際に「Calendar#setTime
をしたいときはsetInstant
」という変換が必要になってきます。既存のCalendar
に沿うものとして作成されたにしてはこのあたりは少し微妙。
とはいえCalendar
クラスのsetTime
メソッドって名前もたいがいアレなんですよね。引数型まで含めて書くとCalendar#setTime(Date)
なので、お前は一体何を言っているんだって感じだし。そもそもDate#getTime
が合ってはいるんだろうけどTimeって名前を迂闊に使ったのが云々。長年付き合ってるから慣れてはいるんだけど、見るたびにもんにょりしてます。
個人的趣味ではオーバーロードをCalenda.Builder#setInstant
のように使うのが好きですが、APIの整合性を崩す方がまずいんじゃ無いかなーと思ったりしつつ、Calendar.Builder#setDate
はまさに欲しかった物体なのでsetDate(Date)
とする訳にもいか無いからsetInstant
でいいのかな、とかもやもやしました。結局は過去とどこで折り合いをつけるかだけの話だと思いますし、現在の選択も悪くは無いと思います。
- 微妙に掠る過去記事: オーバーロードの誤用 - 日々常々
まとめ
悪くない。少なくともCalendar
インスタンスを作る場面では積極的に使いたいと思いました。
JavaSE8でBuilder
が入ったり、ファクトリメソッドのof
ができたり、なんかJava標準ライブラリらしからぬものが増えてきているので、長年古き良きJavaに慣れ親しんでいた方々には抵抗があるかもしれないなと思いつつ。
Builderを使ったインスタンス生成が一般的になれば、生成対象インスタンスをイミュータブルにしやすくなるので個人的には嬉しいところです。(そもそもコンストラクタやシンプルなファクトリメソッドでインスタンス化できない時点でクラス設計負けてる感はありますが。) イミュータブルが基本になれば、もう少し世界は平和になるはず。と思ってる。