ラベル Groovy の投稿を表示しています。 すべての投稿を表示
ラベル Groovy の投稿を表示しています。 すべての投稿を表示

2017年1月28日土曜日

Gradle / 事始め

今更感がありますが、Gradleを初めてちゃんと触れたので、メモメモ


メモ

Mac OSXでのJAVA_HOME設定
$ export JAVA_HOME=`/usr/libexec/java_home`
バッククォートです。
注意点は、JDK変えた時に改めてexportしないといけないことですか。
$ /usr/libexec/java_home --help
Usage: java_home [options...]
Returns the path to a Java home directory from the current user's settings.
ログインユーザの環境でのjava_homeを返します。

gvmもといSDKMAN
Groovy/Grails関連のパッケージ管理ソフト
$ curl -s "https://get.sdkman.io" | bash
でインスト

$ gvm install gradle
gradleのインストール
Installing: gradle 3.3
Done installing!


Setting gradle 3.3 as default.
で終わり。

バージョンを指定したインスト
$ gvm list gradle
DL可能なバージョンを表示
$ gvm install gradle 3.2.1
など。

デフォルトバージョンの設定
$ gvm default gradle [version]

$ gradle --version
とりあえず、パス通っているかを確認

Groovy / 文字列
'シングルクォート:文字列(charじゃない)
"ダブルクォート:GString($で変数を入れることができる...「なんだと」)

Groovy / メソッド呼び出し時のカッコ
引数がないとき、メソッドの引数としてメソッドを使うとき、式の右辺でメソッドを使うときは、()が必須 その他のケースで、引数があるときはなくてもOK
1つのメソッド呼び出しする行の時だけですね。

Groovy / defによる変数の宣言
def age = 99
型を省略して変数を宣言できます。
Javaにおける、Object型の変数と同じ扱いになるそうです。

ダックタイピング
実際の値が、処理に適したものかどうかでメソッドやプロパティを捉える。

クロージャ
{}で定義する
def closure = { param -> println "$param" }
引数に対して->処理を行う
$itをつかって、引数を省略することも可能
呼び出しは、
closure.call()または、closure()
カッコの省略はメソッドと同様。

<<によってタスクに定義することも可能
task printParam << { println "$it" }

分けて書く場合、
def closure = { param-> println "$param" }
task printParam {}
printParam.leftShift(closure)

built-in task
あらかじめ利用できるgradleのタスク
$ gradle tasksで一覧表示が可能
$ gradle tasks
The Task.leftShift(Closure) method has been deprecated and is 
 ..scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
        at build_441sas0jfgrsmxsyzaz0sazay.run
        (/Users/Shogo/gitdir/gradle_git/build.gradle:1)
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
buildEnvironment
 - Displays all buildscript dependencies declared in root project 'gradle_git'.
components
 - Displays the components produced by root project 'gradle_git'. [incubating]
dependencies
 - Displays all dependencies declared in root project 'gradle_git'.
dependencyInsight
 - Displays the insight into a specific dependency in root project 'gradle_git'.
dependentComponents
 - Displays the dependent components of components in root project 'gradle_git'. [incubating]
help
 - Displays a help message.
model
 - Displays the configuration model of root project 'gradle_git'. [incubating]
projects
 - Displays the sub-projects of root project 'gradle_git'.
properties
 - Displays the properties of root project 'gradle_git'.
tasks
 - Displays the tasks runnable from root project 'gradle_git'.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task 

BUILD SUCCESSFUL

Total time: 0.957 secs


Build Setup tasks / Help tasksのグループが確認できる

とりあえずのテスト
$ vim build.gradle
task hello << {
  println 'Hello Gradle world!'
$ gradle hello
Starting a Gradle Daemon (subsequent builds will be faster)
The Task.leftShift(Closure) method has been deprecated and is scheduled to 
 ..be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
        at build_441sas0jfgrsmxsyzaz0sazay.run
 ..(/Users/Shogo/gitdir/gradle_git/build.gradle:1)
:hello <-----タスク名
Hello Gradle world! <-----タスクの出力

BUILD SUCCESSFUL

Total time: 4.332 secs

$ gradle properties
ビルドスクリプトで定義されているプロパティの一覧を表示

gradleのデバッグ

-q:エラーログのみ出力する
-i:INFOレベル
-s:例外のスタックトレースを表示
-S:例外のフルスタックトレースを表示
-d:通常のスタックトレースを含むデバッグログを表示

$ gradle help --task
タスクを指定してヘルプを確認できる

ビルドスクリプトファイル名をデフォルト(build.gradle)以外のファイル名にする場合
$ gradle -b build_new.gradle hello
-bオプションでビルドファイルを指定する

initタスク
手順
  1. プロジェクトルートとなるディレクトリを作成する
  2. そのディレクトリに移動する
  3. $ gradle init --type java-library

タスクのライフサイクル
  • Internal:内部的にしか参照できない機能。ユーザが直接使うことはできない。
  • Incubating:実験的な公開
  • Public(default):公開中  どのライフサイクルステータスもつけられていないときはパブリック
  • Deprecated:廃止予定のタスク

JCenter
Mavenレポジトリ

dependency
gradle init --type java-libraryで作ったbuild.gradle
dependencies {
    // The production code uses Guava
    compile 'com.google.guava:guava:20.0'

    // Use JUnit test framework
    testCompile 'junit:junit:4.12'
}
compile:プロダクションコードのコンパイルと実行に必要なライブラリを記載 test:テストコードのコンパイルと実行に必要なライブラリを記載

Google Guava
Javaのコアライブラリ

タスクの一覧をGUIで確認する
$ gradle --gui

ビルドする
$ gradle build
Starting a Gradle Daemon (subsequent builds will be faster)
:compileJava
Download https://jcenter.bintray.com/com/google/guava/guava/20.0/guava-20.0.pom
Download https://jcenter.bintray.com/com/google/guava/guava-parent/20.0/guava-parent-20.0.pom
Download https://jcenter.bintray.com/com/google/guava/guava/20.0/guava-20.0.jar
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test <-- テストの実行
:check
:build

BUILD SUCCESSFUL

Total time: 17.849 secs
実行すると、プロジェクトルート配下にbuildディレクトリができます。
再度、$ gradle build 実行しても、変更がないタスクはスキップされます。

$ gradle clean
buildディレクトリが削除されます

テストの実行結果
build/reports/tests/test/index.html
にテスト結果が記載されます。

テストコードの実行
$ gradle test

$ gradle tomcatRunWar

Gradleでは型の宣言が必要
最低でもdefが必要(Object型)

システムプロパティの使用
System.properties['xxx']
$ gradle -Dxxx=hoge [task]

もしくは、gradle.propertiesに記述する
systemProp.message=hoge
この場合、自動でプロパティファイルを参照するので、
引数は不要
$ gradle [task]

taskの定義
タスクの設定
<<あり:実行処理
<<なし:設定処理

2017年1月22日日曜日

Groovy / Differences with Java

Groovyの公式ドキュメントを読んでみます。
参考:Differences with Java

実行環境:Groovy Version: 2.4.8 JVM: 1.8.0_111 IDE:IntelliJ IDEA 2016.3.3


Default imports

次のパッケージはデフォルトでインポートされていますので、
下記のパッケージのクラスは明示的にimportしなくても使えます。

  • java.io.*
  • java.lang.*
  • java.math.BigDecimal
  • java.math.BigInteger
  • java.net.*
  • java.util.*
  • groovy.lang.*
  • groovy.util.*
printlnで標準出力できます〜。(System.outがいらない)


Intellij IDE CEでJunitしてみる

プロジェクトを右クリックする
Open Module Settings
Libraries
+ button
Junitで検索
とりあえず現在の最新のjunit:junit:4.12を検索
OK

あとは実行クラスでassertするだけ

import org.junit.Assert;
Assert.assert();


Intellij IDE CEでgroovyしてみる

Groovyプロジェクトは最初から選べましたが、
実行してみるとSDKがないと怒られました。

実行環境がMax OSXなので、brew install groovysdkです。
先にgroovyだけでインストールしていると競合します。
(エラーメッセージにある通り、brew unlink groovy競合を回避できます)

...

が、しかし、
brewでのインストール先が、「/usr/local/Cellar/groovysdk/2.4.7」で
Intellijで選べないとこにあるわけです。
しょうがないので、公式からzipをダウンロードし、解凍したディレクトリを選択します。
これでコンパイルできます。


Multi-method(Runtime Dispatch)

オーバーロードされたメソッドについての話。
Javaだとコンパイル時にどのメソッドを呼ぶかが決まります。
一方、実行時の引数の型により、呼び出すメソッドが決まります。

公式のサンプルをIntelliJで実行できる形式にしたものが下記です。
※JUnitをライブラリに登録してあるものとします。

import org.junit.Assert;

int test(String arg) {
    return 1;
}
int test(Object arg) {
    return 2;
}
Object o = "Object";
int returnInt = test(o);

//println result;
Assert.assertEquals((long)1, (long)returnInt);


IntelliJの実行ショートカット

Ctl + Shift + r
MacでIntelliJを使うのに慣れていないものでして。。。

Array initializers

配列の初期化は[]でよろしくどうぞ。
{}はクロージャ(無名メソッド)で予約されているので、配列の初期化には使えないそうです。

unexpected token: 1 @ line 4, column 17.
   int[] array = { 1, 2, 3};
                   ^
こんな感じで怒られます。

クラスのフィールドのアクセス修飾子を省力するとprivateとなりgetter/setterが作られます

class Student {
    String name
}

Student person = new Student()
person.setName("hoge")

println(person.getName())
Javaだとデフォルトのアクセスレベルはパッケージプライベートです。

また、groovyで@PackageScopeアノテーションをつけることで、
パブリックではなく、パッケージプライベートにすることができるようです。
自分の環境だと下記のエラーでアノテーションとして認識してくれなかったのですが。。。

6: unable to resolve class PackageScope ,  unable to find class for annotation
 @ line 6, column 1.
   @PackageScope class Student {
コマンドラインで実行してもダメ、コンパイルの設定も問題なさそうでしたが。。。
stackoverflowでも同じ事例はなさそうで、
「Eclipseでクリーン実行したらエラーが消えた」という事例はありましたがIntelliJでクリーン実行なさげ。


EclipseでGroovyしてみる

上記のunable to resolve class PackageScope問題で、原因切り分けとして、
Eclipseで同じコードを実行してみます。
参考:Qiita Gradle + Spock + Eclipse環境
まずプラグインが入っていなかったので、入れます。
使用バージョンは、STS 3.8.3.RELEASE(Eclipse Neon.2(4.6.2))です。
Help → Install New Software... →
http://dist.springsource.org/snapshot/GRECLIPSE/e4.6/ に対して、groovyで検索してプラグインを入れます。
これで新規作成ウィザードでGroovy関連を使用できます。
結果、変わらず「PackageScope is not an annotation」でエラーでした。とりあえず次。


GroovyはTry with Resourceをサポートしていません

公式でARM(Automatic Resource Management)という言葉が出てきましたが、StackOverflowを見た限り、
Try with ResourceのことをARMとも呼ぶみたいです。
GroovyはTry with Resourceはサポートしていませんが、クロージャで代用することが可能みたいです。
該当するeachLineメソッドがドキュメントに載っていないので、定かではないのですが。。。
IOGroovyMethodsのpublic static <T> T eachLine(InputStream stream, Closure<T> closure)
が一番近しいですが、、、どうだか。


Static inner classes

若干Javaと異なるらしい

Static inner classes

これは全然変わらない。

Anonymous Inner Classes

インナークラスのインスタンス生成は、
outer.new.Inner()はサポートされず、new Outer(inner)で書く


Lambdas

Java8のラムダそのままの書き方ができないが、クロージャで代用できる。


GStrings

ダブルクォートで囲った文字列は、GStringとして解釈される。
ダラーマークを含む文字列が,JavaとGroovyで若干異なる出力になる可能性がある。
ただ、Java APIに沿ってGStringとStringをオートキャストしてくれる。
しかし、Objectクラスの場合は、実際の値がチェックされる。


String and Character literals

Groovyだとシングルクォートは文字列として扱われる。
char型の変数にシングルクォートの値が割り振られた時は、自動でcharにキャストする。
値を直接参照する時は、キャストされないので、明示的にキャストする必要がある。

キャスト方法

  1. (char)'a'
  2. 'a' as char
(char)'a'
String str = 'x'
char x = (char) str
println((Object)x.getClass().getCanonicalName())
println(x)
-----------
java.lang.Character
x
'a' as char
String str = 'x'
char x = str as char
println((Object)x.getClass().getCanonicalName())
println(x)
-----------
java.lang.Character
x


Primitives and wrappers

Groovyは変数を全てオブジェクトとして扱う、とさらっと書かれています。
そのため、プリミティブ型変数をラッパークラスに自動変換します。
Javaはボクシング(ラッパークラスからプリミティブ型変数への変換)より変数拡張を優先します。
Groovyでは、プリミティブ型変数の引数をラッパークラスとしてまずは扱うので、
JavaとGroovyとでオーバーライドしたメソッドの呼び出し先が異なる場合があります。


Behaviour of ==

==:値のチェック
a.is(b):参照のチェック
nullは==でいいみたいです。


Extra keywords

Javaのキーワードに加えて、Groovyはas, def, in, traitもキーワードです。


Conversions

時間があるときに、確認します。


参照サイト

公式以外はこれかな、、、
http://www.tutorialspoint.com/groovy/