Hatena::ブログ(Diary)

bluepapa32’s Java Blog このページをアンテナに追加 RSSフィード Twitter

2014-12-24

Gradle Wrapper をカスタムしてみる

今年も残りわずかとなりましたが、今年最初となるエントリーは『 G*アドベントカレンダー 2014』の第24日目の記事です。

早いもので Gradle をはじめてから、まもなく4年が経とうとしています。 今年は長年の悲願であった業務への導入にも成功し、非常に充実した一年になりました。


そこで今回は業務で実際に使ってみて、とっても便利だった機能の一つ 『カスタム Gradle Wrapper』 (実は正式名は不明...) を紹介したいと思います。


いくつものプロジェクトで Gradle を使っていると、いつもお決まりの Gradle スクリプトを書いていることに気づき、いくら Ant や Maven よりも記述量が少なくて済むとはいえ、ちょっと気が滅入る?ことがありますよね...


例えば、JavaエンコーディングUTF-8 にする場合

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

のようなスクリプトをプロジェクトが立ち上がる度に build.gradle に書かないといけないんです。 これだけならまだしも、こんなのがたくさんあると...


と言うことで…
こんなときは、Gradle Wrapper ディストリビューション(gradlew を実行すると勝手にダウンロードされる Gradle)に『init スクリプト』を組み合わせたカスタムディストリビューションを作ってしまいましょう。

ちなみに『init スクリプト』は build.gradle を実行する前に、予め所定のディレクトリに配置しておいた Gradle スクリプトを実行してくれるという便利な機能です。(詳細はこちら
『Gradle Wrapper』と組み合わせて使う場合は Gradle Wrapper ディストリビューションの init.d 配下に実行したい『init スクリプト』を配置しておくだけで OK です。


では、早速、Javaのエンコーディングを UTF-8 に変更したカスタムディストリビューションを作成してみましょう。

まず、以下の URL から Gradle Wrapper ディストリビューションの ZIP ファイルをダウンロードして、適当な場所に解凍します。

http://services.gradle.org/distributions/gradle-2.2.1-bin.zip

バージョン番号は 使用したいモノに合わせて変更してください。
今回使用するバージョンは 最新版の 2.2.1 です。

ZIP ファイルを解凍すると

gradle-2.2.1
|-- bin/
|-- init.d/
|-- lib/
|-- media/
|-- LICENSE
|-- NOTICE
|-- changelog.txt
`-- getting-started.html

のような構成になってます。


次に、解凍したディレクトリ直下の init.d 配下に

allprojects {
    tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
    }
}

のように記述した Gradle ファイル(ベース名は任意)を作成します。
今回は コンパイルについての設定を記述した Gradle ファイルなので compile.gradle としておきます。
ちなみに init.d 配下に配置した Gradle ファイルは辞書順で実行されるようなので、複数ファイルを作成する場合は実行したい順番になるようにいい感じでファイル名を付けましょう。


最後に、もう一度 ZIP ファイルにアーカイブしなおせば、カスタムディストリビューションの出来上がりです。
作成した ZIP ファイルは どこかダウンロード可能な場所に置いておきましょう。


あとは カスタムディストリビューションを使いたいプロジェクトの build.gradle に

wrapper {
    distributionUrl = 'http://xxx.xxx.xxx/xxxx/gradle-2.2.1-xx.zip'
}

のように ZIPファイルのダウンロードURLを指定して、いつものように
gradle wrapper

を実行するだけです。 もちろん、作成されたファイルは VCS にコミットしておきましょう。 これで 各プロジェクトの build.gradle に
tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

のようなお決まりのスクリプトを記述しなくても、
./gradlew build
で UTF-8 で書かれた Java ファイルをコンパイルできるようになるんです。


どうですか?
たったこれだけで いつも何も考えずに書いていた お決まりの Gradle スクリプトから解放されるなんて便利じゃないですか?
もし、みなさんも日頃同じような悩みをかかえているようでしたら、ぜひお試しください。


明日はいよいよ大トリの touchez_du_bois さんです。
それでは、みなさん良いクリスマスを!!

2013-12-12

Gradle Watch Plugin を作ってみた

今年も残りわずかとなりましたが、今年最初となるエントリーは 『G* Advent Calendar 2013』の12日目です。


皆さん Gradle 使ってますか?

自分はと言うと…
残念ながら、今年も業務への本格導入はできなかったので、 来年こそは導入するぞという意気込みも込めて、Gradle プラグインを作ってみました。


今回作成した Gradle プラグインですが、簡単に言ってしまうと grunt-contrib-watch のようなプラグインです。というかパクリです。
grunt-contrib-watch は ファイルが変更されたタイミングで任意のタスクを実行する GruntJavaScript 製ビルドツール)用のプラグインです。


最近、G* つながり?で Grunt にも少し手を出し始めているのですが、(まだ、Gradle さえ本格導入できていないのに) その中でも grunt-contrib-watch プラグインがとっても便利。
早速、Gradle でも同じプラグインがないか探してみたのですが、残念ながら見つけることができませんでした。
Java プログラマIDE 前提だし、こういったプラグインの需要はないのかなとも 思いましたが、そんなことは気にせず、ないなら作っちゃえばいいんじゃねと言うことで、さくっと作ってみました。


プラグインの使い方の前に、まずはいろいろと言い訳…
時間がなくてかなり適当な作りになっています。(今後、ちゃんとしていく予定)
また、Java7 の NIO.2 を使っているので Java7 以上でないと動きません。
もちろん、良い子の皆さんは Java6 とか使ってないですよね。
もしかして、良い子はもうすでに Java8 使ってるのかな?
あと、Mac OS X 使ってるみなさん、(私もその一人ですが)残念ながら、WatchService のファイル更新の通知が遅いので、動作がモサッとしていてちょっとイラっときます。


と言うことで、Gradle Watch Plugin の使い方ですが とっても簡単です。
まず、このプラグインを利用したいプロジェクトの build.gradle に

buildscript {
    repositories { maven { url 'http://bluepapa32.github.io/maven/' } }
    dependencies { classpath 'com.bluepapa32.gradle.plugins:gradle-watch-plugin:0.1.0' }
}

apply plugin: 'watch'

を追加して、Gradle Watch Plugin を適用します。あとは
watch {

    java {
        files files('src/main/java')
        tasks 'compileJava'
    }

    resources {
        files fileTree(dir: 'src/main/resources',       // FileTree で指定
                       include: '**/*.properties')
        tasks 'processResources'
    }

    hoge {
        files files('foo/bar', 'foo/boo/hoo.txt')       // 複数のディレクトリを監視
        tasks 'hogehoge', 'hugohugo'                    // 複数のタスクを実行
    }
}
と watch ブロック内に 任意の名前を付けたブロック(watch ブロック内でユニークであれば何でも可)を定義して、そのブロック内に
名前説明
files監視したいディレクトリ または ファイルFileCollection
tasksファイルが変更された際に実行するタスクString[]
を定義して、
gradle watch
と実行するだけで、常駐プロセスがファイルを監視して、変更があったタイミングで指定したタスクを実行してくれるようになります。
上の例の場合、src/main/java 配下のファイルが更新されると compileJava タスクが実行され、src/main/resources 配下の プロパティファイルが更新されると processResources タスクが実行されます。


もし、興味があれば、ぜひ使ってみてください。
ちなみにソースは GitHub に公開しています。


せっかくなので、今回プラグインを作成するにあたり、いくつか新しい機能を使ってみたので簡単に紹介したいと思います。
その前に、Gradle プラグインの基本的な作り方ですが、

がかなり参考になるので、プラグインを作成する場合は一読することをおススメします。

今回使ってみた新しい機能(もう新機能ではないかもしれませんが...)は

の2つです。


extension オブジェクト

まず、extension オブジェクトですが、ざっくり言うと独自でDSLを拡張できる仕組みです。
例えば、上記の watch ブロックは この機能を使って追加したものです。


更に 今回の場合、watch ブロック内部で自由にブロックを追加できるのですが、これ は NamedDomainObjectContainer というクラスを使って実現しています。

以下がそれを実現しているコードです。たったこれだけです。とっても簡単ですね。


class WatchPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.watch = project.container(WatchTarget) { name ->
            project.extensions.create(name, WatchTarget, name)
        }
        ...
    }
}

NamedDomainObjectContainer は Project クラスの container メソッドで生成することができます。
今回の場合 watch が NamedDomainObjectContainer に対応しています。
container メソッドの引数に指定している型が NamedDomainObjectContainer内の要素の型、 その後ろのクロージャが実際に NamedDomainObjectContainer 内の要素を生成する部分になります。
今回の場合、watch ブロック内の java, resources, hoge を順番に name 変数で受け取り、 クロージャ内で WatchTarget を生成しています。
もちろん生成された WatchTarget には files や tasks で定義した値が勝手に設定されます。
たったこれだけで自由にDSLを拡張できるなんて、便利な世の中になりましたね。


Gradle tooling API

もう一つ利用した機能が Gradle tooling API ですが

ProjectConnection connection = GradleConnector.newConnector()
    .forProjectDirectory(new File("someProjectFolder"))
    .connect();

try {
    connection.newBuild().forTasks("taskA", "taskB").run();
} finally {
    connection.close();
}
のように書くだけで、Gradle以外の(例えば IDE みたいな)アプリケーションから直接 Gradle のタスクが実行できるようになるという便利な機能です。
今回は Gradle プラグインから実行しているのでアレですが…


と言うことで…
今年の冬休みは みなさんも Gradle プラグインを作ってみてはいかがでしょうか?


明日は あの きょんくん が再び登場です。
それでは 少し早いですが 良いクリスマスを!!

2012-12-21

GroovyFX で GUI アプリケーション開発をはじめよう!!

今年もあとわずかとなりましたが、今年最初となる(しかも 多分 今年最後になるであろう)記念すべきエントリーは 『G* Advent Calendar 2012』の21日目です。
昨年はすっかり出遅れて寂しい思いをしましたが、今年は間に合いましたよ!!

で、早速ですが...
皆さん Gradle 使ってますか? (GroovyFX の話はちょっとおいといて...)

自分はというと...
Gradle の正式版がリリースされたにも関わらず、今年も本格的に導入することができず、ちょっとしたプロトタイプ プロジェクトのビルドやツールとして利用する程度という残念な結果に...

とは言え 泥臭い現場では ちょっとしたツールというのが結構大事なんですよね。
でも それを周りにも使ってもらおうとすると 『コマンドライン はちょっと...』 ということ よくありますよね?


そこで GroovyFX ですよ!!
GroovyFX なら とっても簡単に GUI ツールが作れちゃうんです。


GroovyFX って何? という人のために 簡単に言うと

 Groovy で JavaFX 2.x を簡単に扱うための ライブラリ

です。(名前のまんまですが...)
詳細はこちら


もちろん GroovyFX だけでも OK ですが、Gradle で更に快適に...
f:id:bluepapa32:20121220014124p:image:w360
のような画面を表示するだけであれば

  hellofx
  |-- src/main/groovy/
  |   `--  hellofx/Main.groovy
  `-- build.gradle
のような ディレクトリ構成で

Main.groovy

package hellofx

import static groovyx.javafx.GroovyFX.start

start {
    stage(title: 'Hello, GroovyFX', visible: true) {
        scene(fill: BLACK, width: 500, height: 250) {
            hbox(padding: 60) {
                text(text: 'Groovy', font: '80pt sanserif') {
                    fill linearGradient(endX: 0, stops: [PALEGREEN, SEAGREEN])
                }
                text(text: 'FX', font: '80pt sanserif') {
                    fill linearGradient(endX: 0, stops: [CYAN, DODGERBLUE])
                    effect dropShadow(color: DODGERBLUE, radius: 25, spread: 0.25)
                }
            }
        }
    }
}

build.gradle

apply plugin: 'groovy'
apply from:   'http://repository-javafx-gradle-plugin.forge.cloudbees.com/snapshot/javafx.plugin'

repositories { mavenCentral() }

dependencies {
    groovy 'org.codehaus.groovy:groovy-all:2.0.5'
    groovy 'org.codehaus.groovyfx:groovyfx:0.3.1'
}
のような2つのファイルを用意して
gradle run
と実行するだけです!!
たったこれだけで GUI アプリケーションが作れるなんていい時代になったものです。
これを使わない手はないですよね。

# もちろん、皆さん JDK 7u10 はインストールしてますよね!! JRE ではダメですよ。
# もしインストールしていないという方は まずは JDK をインストールしましょう!!
# あっ、それともちろん Gradle も...


更に

gradle build
と実行すれば build/distributions 配下に
  • JAR 形式
  • JNLP形式
  • 開発環境により Windows の場合 hellofx.exe、Mac OS X の場合 hellofx.app
のような配布ファイルまで生成できちゃいます。

これらは Gradle JavaFX Plugin により実現されています。
残念ながら 今のところ 公式な JavaFX 2.x 用の プラグインはないようですが、このプラグインはかなりいいですね。
早く 公式プラグインとして採用されるとよいのですが...
このプラグインは

apply from:   'http://repository-javafx-gradle-plugin.forge.cloudbees.com/snapshot/javafx.plugin'
を追加するだけで適用され、JavaFX のビルド、実行に必要な設定やタスクが追加されます。
このプラグインを適用した際のタスクはこんな感じ...
Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles the main classes.
clean - Deletes the build directory.
cssToBin - Converts CSS to Binary CSS.
generateDebugKey - Generates the JAvaFX Debug Key.
jar - Assembles a jar archive containing the main classes.
jfxDeploy - Processes the JavaFX jars and generates webstart and native packages.
jfxJar - Jars up the classes and adds JavaFX specific packaging.
jfxSignJar - Signs the JavaFX jars the JavaFX way.
packageClasses - Assembles the package classes.
testClasses - Assembles the test classes.

Documentation tasks
-------------------
groovydoc - Generates Groovydoc API documentation for the main source code.
javadoc - Generates Javadoc API documentation for the main source code.

Execution tasks
---------------
debug - Runs the applicaiton and sets up debugging on port 5005.
run - Runs the application.

Tools tasks
-----------
scenicview - Adds the ScenicView agent to all Execution Tasks.

Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.
ちなみに このプラグインでは 命名規約が決まっていて デフォルトでは
<プロジェクト名>.Main
が メインクラスになるようです。今回の場合
  hellofx.Main
ですね。

今回作成したサンプルプロジェクトは こちら です。 興味のある方はどうぞ!!
もし ZIP 形式でダウンロードする場合は 解凍後のディレクトリ名を hellofx に変更してください。


手っ取り早く、GroovyFX を試してみたものの、これだと GroovyFX & JavaFX のよさがわかりづらいので、もうちょっと それらしいものを!!
ということで、GitHub からサンプルプロジェクトをダウンロードして実行する GUI ツールを作成してみました。

こんな感じ...

f:id:bluepapa32:20121221005450p:image

で 今回 GroovyFX を試してみてわかったことは 簡単な GUI ツールを作成する程度であれば、GroovyFX の (と言うより Groovy のかな?) 強力なビルダー機能を使って地道に画面を作成するよりも JavaFX 2.x の JavaFX Scene Builder を使った方が楽ってことですね。

今回初めて JavaFX Scene Builder を使ってみたのですが、これ かなりいいですね。
簡単なツールの開発ぐらいなら、これで 十分ではないかな...


f:id:bluepapa32:20121220075400p:image

このツールを使うメリットは もちろん『GUI 画面で 画面のデザインができる』ということもありますが、 それよりもむしろ『画面のデザインとコントロールが完全に分離できる』ということではないでしょうか?
実際はこのツールというより FXML を使うメリットと言った方が正しいのかもしれませんが...

JavaFX Scene Builder を使えば

  • FXML (JavaFX Scene Builder で作成されるXMLファイル)
  • CSS (リファレンスは こちら
  • Groovy(FX)
といった 皆さんおなじみの HTML + CSS + JavaScript みたいな感じで開発できるようになるんですよ。
これって結構すごくないですか?これでかなり敷居が下がると思うんですよね。


で 今回作ったものはこんな感じの構成になります。

gradlefx
|-- build.gradle
`-- src
      `-- main
            |-- groovy
            |    `-- gradlefx
            |          |-- Controller.groovy
            |          `-- Main.groovy
            `-- resources
                   |-- gradlefx.css
                   `-- gradlefx.fxml

詳しい話はまたの機会にするとして...
たった 4(+1) ファイルで GUI ツールが作成できるので皆さんも ぜひ 何か作ってみてください。


今回作成したサンプルプロジェクトは こちら です。 興味のある方はどうぞ!!
もし ZIP 形式でダウンロードする場合は 解凍後のディレクトリ名を gradlefx に変更してください。


G* Advent Calendar 2012 も もう終盤に差し掛かったこの時期に 今更ではありますが G* Advent Calendar 2012 をカレンダー形式で参照できる GUI アプリケーションも作成してみました。
興味のある方は こちら もどうぞ!!
もし ZIP 形式でダウンロードする場合は 解凍後のディレクトリ名を groovyfx に変更してください。


f:id:bluepapa32:20121221005104p:image

各日付の参加者のリンクをクリックすると ATND のコメントが表示されます。コメントのリンクを押すとブラウザでブログがみれちゃいます。
時間がなくてかなり中途半端なデキですが、GroovyFX の勉強(WEB サービス連携、非同期処理、ブラウザ連携 等々)にはかなり役に立ったので まぁ ヨシとしとこうかな。
それなりに苦労したので、また、時間があるときに ブログにまとめていこうと思います。


明日は いよいよ @ さんですよ!!
では、みなさん よいクリスマスを!!

2011-12-22

Apache Solr を 60 秒で試してみる

今回も Java全文検索です。
前回は Apache Lucene を試しましたが 『検索エンジンの常識をApache Solrで身につける』 ということで Apache Solr のデモも試してみました。
もちろん、今回も誰でも 60秒で デモを試せるように Gradle スクリプトを作ってみました。


Solr も Gradle を使えば たった 3ステップ + α で気軽に試せるので、 全文検索に少しでも興味のある方は ぜひ、試してみてください。

  1. build.gradle 作成
  2. Solr 起動
  3. インデックス作成
  4. 全文検索 実行
  5. Solr 停止

build.gradle 作成

まずは適当なディレクトリに 次のスクリプトを build.gradle と言う名前で保存します。
以下の 「view raw」の リンク先を保存するのが簡単です。
もちろん今回も スクリプトの詳細は抜きと言うことで、Solr を楽しみましょう。


Solr 起動

まずは いきなり Solr を起動してみましょう。

gradle start
を実行すれば、初回起動時に 勝手に必要なファイルをダウンロードしてカレントディレクトリに 展開します。
自分でわざわざ環境を作る必要はありません。
今回は Solr のデモを試すだけなので もちろん example に含まれている Jetty を使っています。

初回起動時は 少し時間がかかりますが、"BUILD SUCCESS" と表示されれば OK です。
これで Solr が起動されたはずなので 好きなだけ 全文検索を楽しみましょう。
手始めに http://localhost:8983/solr/admin にアクセスしてみましょう。
以下のような 管理画面が表示されるはずです。


f:id:bluepapa32:20111223030121p:image

と言っても まだ インデックスを作成していないので検索しても何もヒットしませんが ANALYSIS あたりで遊んでみると面白いかもしれません。


インデックス作成

では 早速インデックスを作成してみましょう。
通常はここで XML ファイルを手で作成して Solr に POST するというのが慣例のようですが そんなの面倒なので

gradle index
を実行しましょう。
これで前回と同様に lucene-core-3.5.0-sources.jar 内のソースファイルの内容が Solr に POST されて インデックスが作成されます。
今回は solrj と言う Java 用のクライアントライブラリを使用しているので
    def server = new CommonsHttpSolrServer(serverurl)
    server.deleteByQuery("*:*")
    server.add(fileTree(dir: 'src').collect { f ->
        println f
        def doc = new SolrInputDocument()
        doc.addField( "id", f.path, 1.0f )
        doc.addField( "text", f.text)
        return doc
    })
    server.commit()
を実行して、Solr 起動時に あらかじめ src 配下に展開しておいた lucene-core-3.5.0 のソースファイルの情報を Solr に送信しています。
がんばって XML なんて書かなくたって たったこれだけで大量のインデックスが作成できるんです。とても簡単ですね!!
しかも 実際は HTTP で通信しているだけですので どんな言語からでも利用できると言うのがすばらしい。


全文検索 実行

折角なので ブラウザから検索してみましょう。
http://localhost:8983/solr/select?q=reader&rows=1000 をクリックしてみてください。
ブラウザに XML が表示されるはずです。

XML を表示しても なんかピンとこないので

gradle ?reader
を実行して 前回と同じように該当するファイルのパスを出力してみましょう。
今回の全文検索に必要なコードは
def query = new SolrQuery(taskName[1..-1]).set("rows", 1000)
new CommonsHttpSolrServer(serverurl).query(query).results.each {
    println it.getFieldValue("id")
}
の4行だけです。とっても簡単ですね。
たったこれだけで Solr にリクエストを投げて返ってきた検索結果を利用できるんです。


Solr 停止

全文検索を十分満喫したら

gradle stop
で Solr を停止しておきましょう。

うまく Solr を満喫できましたか?
Solr を使えば クライアント側から全文検索を分離できるので開発が楽にできそうです。
もちろん、全文検索側のチューニング等はいろいろと大変そうですが...
ちなみに今回も日本語の検索は正しくできません。
次回は 日本語を考慮した検索も試せるようにしてみようかな...

2011-12-13

Apache Lucene を 60 秒で試してみる

今更ながら Java全文検索です。とりあえず Apache Lucene の デモを試してみようと思ったのですが、最新リリースの 3.5.0 の情報が見当たらなかったので、この際、誰でも 60秒で デモを試せるように Gradle スクリプトを作ってみました。

デモのために わざわざ 自分でファイルをダウンロードして、解凍して、あれしてこれして なんて面倒ですよね。
Gradle を使えば たった 3 ステップで試せます。(もちろん、今時の人たちは 既に Gradle はインストール済みですよね...)

  1. build.gradle 作成
  2. インデックスファイル 作成
  3. 全文検索 実行

build.gradle 作成

まずは 適当なディレクトリに build.gradle を作成して 次のスクリプトをコピーしましょう。
今回は Lucene がメインなので Gradle スクリプトの細かい説明は省略。結構がんばったんですけど...


インデックスファイル 作成

次に 以下のコマンドを実行して全文検索のためのインデックスファイルを作成しましょう。

gradle index

このコマンドを実行すると

  1. デモの実行に必要なライブラリを Maven リポジトリから取得
  2. lucene-core-3.5.0-sources.jar を Maven リポジトリから取得して src ディレクトリに展開
  3. src 配下のソースファイルをもとに インデックスファイル生成

のような処理が実行されます。


全文検索 実行

あとは 以下のコマンドの <query> に検索したい単語を指定して全文検索するだけです。

gradle ?<query>

例えば "reader" を検索したい場合

gradle ?reader

のように実行します。もし複数の単語を指定したい場合は

gradle ?'reader AND search'

のようにクォートしましょう。main 関数を含むファイルを検索したいなら

gradle ?'"public static void main("'

のような感じで OK...

<query> の詳しい指定方法については http://lucene.apache.org/java/3_5_0/queryparsersyntax.html を参照してください。


Gradle 使えば こんなに簡単に全文検索できちゃうんですね。
なぜ今まで試さなかったんだろうか?
今度は 日本語の全文検索を試してみようかな?
もちろん Gradle で...