java開発の強力な相棒として今すぐ使えるgroovy

144
Yasuharu Nakano / @nobeans Java開発の強力な相棒として今すぐ使える 2015-04-11 JJUG CCC 2015 Spring #ccc_g6

Upload: yasuharu-nakano

Post on 15-Jul-2015

5.181 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Java開発の強力な相棒として今すぐ使えるGroovy

Yasuharu Nakano / @nobeans

Java開発の強力な相棒として今すぐ使える

2015-04-11 JJUG CCC 2015 Spring #ccc_g6

Page 2: Java開発の強力な相棒として今すぐ使えるGroovy

中野 靖治@nobeans

所属:NTTソフトウェア株式会社 Grails推進室

職業:Grails Advocate

Page 3: Java開発の強力な相棒として今すぐ使えるGroovy

概要

Page 4: Java開発の強力な相棒として今すぐ使えるGroovy

Groovyとは

“Javaをもっとすごくしたもの” 「ポストJava」ではなく「Java強化外骨格」もしくは「Java拡張パック」のイメージ

Java VM上で動作する動的型付け言語 Rubyによく似た文法を持ち、生産性が高い Groovy界隈はRubyへのリスペクト成分が高め Grailsの旧名「Groovy on Rails」

2003年生まれ(平成生まれ)

Page 5: Java開発の強力な相棒として今すぐ使えるGroovy

in Java

//  HelloWorld.java  public  class  HelloWorld  {          public  static  void  main(String...  args)  {                  System.out.println("Hello,  World!");          }  }  

//=>  Hello,  World!

Page 6: Java開発の強力な相棒として今すぐ使えるGroovy

in Groovy

//  HelloWorld.groovy  public  class  HelloWorld  {          public  static  void  main(String...  args)  {                  System.out.println("Hello,  World!");          }  }  

//=>  Hello,  World!

Groovyとしてもvalidなコードなので拡張子を変えるだけでOK

Page 7: Java開発の強力な相棒として今すぐ使えるGroovy

in Groovy

//  HelloWorld.groovy  public  class  HelloWorld  {          public  static  void  main(String...  args)  {                  System.out.println("Hello,  World!");          }  }  

//=>  Hello,  World!

セミコロンは省略可能

Page 8: Java開発の強力な相棒として今すぐ使えるGroovy

in Groovy

//  HelloWorld.groovy  public  class  HelloWorld  {          public  static  void  main(String...  args)  {                  System.out.println("Hello,  World!")          }  }  

//=>  Hello,  World!

Object#println()が使える(GDKのひとつ)

Page 9: Java開発の強力な相棒として今すぐ使えるGroovy

in Groovy

//  HelloWorld.groovy  public  class  HelloWorld  {          public  static  void  main(String...  args)  {                  println("Hello,  World!")          }  }  

//=>  Hello,  World!

スクリプト形式で実行可能(クラスが不要)

Page 10: Java開発の強力な相棒として今すぐ使えるGroovy

in Groovy

//  HelloWorld.groovy  println("Hello,  World!")  

//=>  Hello,  World!

メソッド呼び出しの丸括弧は省略可能

Page 11: Java開発の強力な相棒として今すぐ使えるGroovy

in Groovy

//  HelloWorld.groovy  println  "Hello,  World!"  

//=>  Hello,  World!

Page 12: Java開発の強力な相棒として今すぐ使えるGroovy

動的型付け言語

Groovyは基本的に動的型付け言語

Page 13: Java開発の強力な相棒として今すぐ使えるGroovy

動的型付けの例

Integer  num  =  "Hello"  

//=>  GroovyCastException:  Cannot  cast  object  'Hello'  with  class  'java.lang.String'  to  class  'java.lang.Integer'

groovycでコンパイルには成功する

しかし、実行すると例外が発生する

Page 14: Java開発の強力な相棒として今すぐ使えるGroovy

静的型付けサポート

Groovy 2.0から静的型付けのための機能が追加 @TypeChecked コンパイル時に静的に型チェックする ただし、実行時は動的型付けのまま

@CompileStatic 静的にコンパイルする 実行時に動的型付けによる機構は使われない Javaとほぼ同等レベルの性能に(理論上)

どちらもクラス単位、メソッド単位で指定できる ただし、明示的な型指定が省略できない 動的を前提とした一部の機能も使えなくなる

http://beta.mybetabook.com/showpage/508402720cf2ffb79bb046db

Page 15: Java開発の強力な相棒として今すぐ使えるGroovy

Java言語との密な関係

Java(7以前)との文法の互換性が高い Java開発者なら非常にとっつきやすい ただし、Java 8のラムダ記法は未対応 代わりにクロージャを使う

すべてのJava APIがシームレスに呼び出せる 標準API、サードパーティのクラスもすべて普通に使える 更に「Groovy JDK(GDK)」と呼ばれる超便利メソッド群が標準クラスに追加されている!

コンパイルするとclassファイルになる 最低限、Java VMとgroovy-all.jarだけあれば実行できる

Page 16: Java開発の強力な相棒として今すぐ使えるGroovy

Groovyの使いどころ

メインのプログラミング言語 Grails/Spring Boot/Vert.x/Android

設定ファイルの記述言語(as DSL) Gradle/Spring Boot/Spring Framework

システムのプラグイン機構/拡張ポイント Javaから外部のGroovyスクリプトを簡単に実行できる Jenkins

プロジェクトの開発支援スクリプト DBのセットアップ、Excel操作等

Page 17: Java開発の強力な相棒として今すぐ使えるGroovy

Groovyの使いどころ

メインのプログラミング言語 Grails/Spring Boot/Vert.x/Android

設定ファイルの記述言語(as DSL) Gradle/Spring Boot/Spring Framework

システムのプラグイン機構/拡張ポイント Javaから外部のGroovyスクリプトを簡単に実行できる Jenkins

プロジェクトの開発支援スクリプト DBのセットアップ、Excel操作等

今日は後半でこの辺を中心に紹介します

Page 18: Java開発の強力な相棒として今すぐ使えるGroovy

Groovy入門その前にまずは

Page 19: Java開発の強力な相棒として今すぐ使えるGroovy

Javaとの文法の違い

Page 20: Java開発の強力な相棒として今すぐ使えるGroovy

Javaとの文法の違い

セミコロンは省略可能 returnも省略可能 チェック例外のthrows宣言も省略可能 型宣言も省略可能 プリミティブ型はラッパー型 各種リテラル 数値/文字列/リスト/マップ

アクセス修飾子 メソッド呼び出し

Page 21: Java開発の強力な相棒として今すぐ使えるGroovy

セミコロンは省略可能

//  セミコロンは不要  

int  a  =  1  

//  セミコロンはあってもOKだが、付けない方がお勧め  

int  b  =  2;

Page 22: Java開発の強力な相棒として今すぐ使えるGroovy

returnも省略可能

String  hello()  {          //  returnは省略できる  

       //  Ruby等と同様に最後に評価された値が返る  

   "Hello"  }  

assert  hello()  ==  "Hello"

Page 23: Java開発の強力な相棒として今すぐ使えるGroovy

チェック例外のthrows宣言も省略可能

String  doWithoutThrows()  {          throw  new  Exception("チェック例外!")  

}  

try  {          doWithoutThrows()          assert  false  }  catch  (Exception  e)  {          assert  e.getMessage()  ==  "チェック例外!"  

}

throwsがなくてもOK!

Page 24: Java開発の強力な相棒として今すぐ使えるGroovy

型宣言も省略可能def  キーワード Object型の別名として宣言時に使える

以下の場合、型宣言自体を省略可能(→Object型) メソッドや変数で、privateやstaticなどの修飾子が1つ以上ある場合 メソッドの仮引数

final  helloPrefix  =  "Hello,  "  

public  hello(name)  {        def  message  =  helloPrefix  +  name        return  message  }

省略はできるが、ドキュメンテーションとして考えると、公開APIのシグネチャでは型を明記する方が好ましい

def  hoge  =  "ほげ"

Page 25: Java開発の強力な相棒として今すぐ使えるGroovy

プリミティブ型で宣言しても実体はラッパー型 ただし、nullは代入不可能 また、最適化機構により、可能な場合において内部的にもプリミティブ型のまま扱われる場合もある

プリミティブ型はラッパー型

assert  1.getClass()  ==  java.lang.Integer  

double  d  =  1.0  assert  d.getClass()  ==  java.lang.Double  

assert  true.getClass()  ==  java.lang.Boolean  

//  もちろんメソッドも呼べる  

assert  d.plus(2.5)  ==  3.5  

//  nullは代入不可能  

d  =  null  //=>  GroovyCastException:  Cannot  cast  object  'null'  with  class  'null'  to  class  'double'.

Page 26: Java開発の強力な相棒として今すぐ使えるGroovy

リテラル:数値

Groovyの浮動小数リテラルはBigDecimal型 桁あふれや誤差を気にしないで演算できる プリミティブ型のように通常の中置演算子が使える

assert  5.3.getClass()  ==  java.math.BigDecimal  

//  普通に中置演算子も使える  

assert  (1.0  /  3)  ==  0.3333333333  assert  (1.0  /  3).getClass()  ==  java.math.BigDecimal  

//  Javaでは誤差が発生するが、GroovyはBigDecimalなので一致する  

assert  (1.0  -­‐  (1.0  /  3.0))  ==  (2.0  /  3.0)

#ccc_cd3 でBigDecimal話がありましたね

Page 27: Java開発の強力な相棒として今すぐ使えるGroovy

リテラル:文字列//  基本はJavaと同じくダブルクォーテーション  

println  "Hello,  World!"    //=>  Hello,  World!  

//  ${}によって変数を展開できる(紛らわしくなければ{}も省略できる)  

String  name  =  "World"  assert  "Hello,  ${name}!"  ==  "Hello,  World!"  

//  厳密にはGString型のリテラル  

assert  "Hello,  ${name}!".getClass()  ==  org.codehaus.groovy.runtime.GStringImpl  

//  純粋にString型が必要な場合はシングルクォーテーションを使う  

//  Javaではchar型リテラルだったが、Groovyではchar型リテラルは無し  

assert  'Hello,  ${name}!'  !=  "Hello,  World!"

Page 28: Java開発の強力な相棒として今すぐ使えるGroovy

リテラル:文字列

//  トリプル「ダブルクォート」(ややこしい)  

//  改行や単体のクォート文字列自体を含められる(GString型)  

//  トリプル「シングルクォート」にすると単なるString型になる(展開無し)  

def  s  =  "Third"  println  """First,  "Second",  ${s}.  """  

//=>  //  First,  //  "Second",  //  Third.

ヒアドキュメント風に使える

Page 29: Java開発の強力な相棒として今すぐ使えるGroovy

リテラル:文字列

//  開始行の行末エスケープとString#stripMargin()を使うと、  

//  いい感じにインデントできて、読みやすい  

def  s  =  "Third"  println  """\          |First,          |"Second",          |${s}.          |""".stripMargin()  

//=>  //  First,  //  "Second",  //  Third.

GDKのString#stripMargin()と合わせて使うとインデントもいい感じにできる

Page 30: Java開発の強力な相棒として今すぐ使えるGroovy

リテラル:文字列

//  スラッシュクォート  

//  単体バックスラッシュを特殊文字として扱わないため、エスケープが不要。  

//  正規表現をシンプルに書ける  

assert  (/This  is  backslash  '\n'/  ==  "This  is  backslash  '\\n'")  assert  "Hello,  World!".matches(/Hello,\s.*/)  

//  Pattern型ではなく、あくまでString型  

assert  (/Not  Pattern,  But  String/.getClass()  ==  String)  

//  丸括弧で囲まないとコンパイルエラーになるケースがあるので注意  

assert  /Naked  Slashed/          //=>  "1  compilation  error:  unexpected  token:  /"

正規表現を書くときは断然コレ

Page 31: Java開発の強力な相棒として今すぐ使えるGroovy

リテラル:リスト//  専用リテラルの導入により、シンプルにリストを記述できる  

def  l  =  [1,  2,  3,  4,  5]  

assert  l.size()  ==  5  assert  l.getClass()  ==  java.util.ArrayList  

//  空リスト  

assert  [].size()  ==  0  

//  要素へのアクセス  

assert  l[0]  ==  1  assert  l[2..3]  ==  [3,  4]  

assert  l.first()  ==  1  assert  l.last()  ==  5  

assert  l.head()  ==  1  assert  l.tail()  ==  [2,  3,  4,  5]

Page 32: Java開発の強力な相棒として今すぐ使えるGroovy

(参考)リテラル:セット

//  セット専用のリテラルはないが、asによる型変換で表現できる  

def  s  =  [1,  2,  3,  4,  5]  as  Set  

assert  s.size()  ==  5  assert  s.getClass()  ==  java.util.LinkedHashSet  

Page 33: Java開発の強力な相棒として今すぐ使えるGroovy

リテラル:マップ

//  専用リテラルの導入により、シンプルにマップを記述できる  def  m  =  ['a':  1,  'b':  2,  'c':  3]  

assert  m.size()  ==  3  assert  m.getClass()  ==  java.util.LinkedHashMap  

//  空マップ  

assert  [:].size()  ==  0  

//  キーに文字列を指定する場合はクォートを省略できる  

assert  m  ==  [a:  1,  b:  2,  c:  3]  

//  要素へのアクセス  

assert  m['a']  ==  1    //  連想配列風  

assert  m.a  ==  1          //  プロパティアクセス風

Page 34: Java開発の強力な相棒として今すぐ使えるGroovy

アクセス修飾子

アクセス修飾子は基本的に飾りです privateメンバにもアクセスできる IDEなどで一応警告が出るぐらい

無印=public パッケージプライベートは存在しない 一応、アノテーションで強引に宣言できる

@PackageScope  

基本は無印(public)でよい その他、ドキュメンテーション目的として... クラス内部だけで利用するものにprivateを付けたり 積極的に継承を想定しているものにprotectedを付けたり

Page 35: Java開発の強力な相棒として今すぐ使えるGroovy

メソッド呼び出し

//  引数の丸括弧が省略できる  

println("Hello")  println  "Hello"  

//  引数がない場合は省略できない  

println()  

Page 36: Java開発の強力な相棒として今すぐ使えるGroovy

メソッド呼び出し

def  hello()  {          "Hello!"  }  

//  Stringでメソッド名を指定できる  

assert  "hello"()  ==  "Hello!"  

//  GStringを使ってもOK  

def  methodName  =  "hello"  assert  "$methodName"()  ==  "Hello!"

Page 37: Java開発の強力な相棒として今すぐ使えるGroovy

メソッド呼び出し

//  名前付き引数?  

def  hello(Map  map)  {          "Hello,  ${map.name}${map.period}"  }  

assert  hello(period:  "!",  name:  "World")  ==  "Hello,  World!"  

//  これの[]を省略できるイメージ  

assert  hello([period:  "!",  name:  "World"])  ==  "Hello,  World!"

Page 38: Java開発の強力な相棒として今すぐ使えるGroovy

メソッド呼び出し

//  引数のデフォルト値  

def  bye(name  =  "World")  {          "Good-­‐bye,  ${name}."  }  

assert  bye()  ==  "Good-­‐bye,  World."  assert  bye("Yesterday")  ==  "Good-­‐bye,  Yesterday."

Page 39: Java開発の強力な相棒として今すぐ使えるGroovy

コンストラクタ呼び出し

class  Sample  {          String  a          String  b          int  c  }  

//  引数を受け取るコンストラクタを自前で書いていなければ、  

//  パラメータ付き引数を指定できる便利なコンストラクタが自動生成される  

def  sample  =  new  Sample(a:  "A",  c:  3,  b:  "B")  

println  sample.dump()  //  デバッグ時に便利なGDK:  Object#dump()  

       //  =>  <Sample@3909c9e9  a=A  b=B  c=3>

Page 40: Java開発の強力な相棒として今すぐ使えるGroovy

Groovyの各種機能

Page 41: Java開発の強力な相棒として今すぐ使えるGroovy

クロージャ

他言語の第1級関数オブジェクトやクロージャと同等 JavaScript, Ruby, Perl, Lisp, ....

第一級オブジェクトとして、変数に代入したり引数に渡したりできる

高階関数

無名内部クラスやJava 8のラムダ記法よりも次の点で強力 クロージャを宣言した文法上のスコープ(レキシカルスコープ)にある変数(ローカル変数を含む)を参照・変更できる

Page 42: Java開発の強力な相棒として今すぐ使えるGroovy

クロージャ:定義と実行

//  クロージャを定義する  

Closure  c  =  {          return  "Hello,  Closure!"  }  

//  実行する  

assert  c.call()  ==  "Hello,  Closure!"  

//  callを省略することもできる  

assert  c()  ==  "Hello,  Closure!"

Page 43: Java開発の強力な相棒として今すぐ使えるGroovy

クロージャ:クロージャでの引数の受け取り//  引数なし  

def  c0  =  {-­‐>          "Hello,  Closure!"  }  assert  c0.call()  ==  "Hello,  Closure!"  

//  引数1つ  

def  c1  =  {  String  name  -­‐>          "Hello,  ${name}!"  }  assert  c1.call("Closure")  ==  "Hello,  Closure!"  

//  引数2つ(片方を型省略してみる)  

def  c2  =  {  greeting,  String  name  -­‐>          println  "${greeting},  ${name}!"  }  assert  c2.call("Hello",  "Closure")  ==  "Hello,  Closure!"  

//  引数宣言部「xx..  -­‐>」を省略した場合、暗黙引数の「it」が使える  

def  c  =  {  "Hello,  ${it}!"  }  assert  c.call("Closure")  ==  "Hello,  Closure!"  assert  c.call()  ==  "Hello,  null!"  //  引数を省略時はnull

Page 44: Java開発の強力な相棒として今すぐ使えるGroovy

クロージャ:クロージャを引数として渡す

//  渡されたクロージャを指定されたnameで実行するだけのメソッド  

def  justDoIt(String  name,  Closure  closure)  {          closure.call(name)  }  

//  普通に丸括弧の中にクロージャを書いた場合  

justDoIt("Taro",  {  name  -­‐>  println  "Hello,  ${name}!"  })  //=>  Hello,  Taro!  

//  最後の引数がクロージャの場合はこのように丸括弧の外に出して書ける  

justDoIt("Taro")  {  name  -­‐>  println  "Hello,  ${name}!"  }    //=>  Hello,  Taro!  

//  このように、専用の文法があるかのように独自APIを定義できる  

justDoIt("Taro")  {  name  -­‐>          println  "Hello,  ${name}!"  }

最後の引数がClosure型であるところがポイント

Page 45: Java開発の強力な相棒として今すぐ使えるGroovy

(参考)クロージャ:高階関数とレキシカルスコープの例

def  createIdGenerator(prefix)  {    //  この実引数と  

       int  counter  =  1                            //  このローカル変数が(finalではない!)  

       Closure  c  =  {                  "${prefix}-­‐${counter++}"  //  クロージャごとに個別に保持される  

       }          return  c  //  クロージャを返す  

}  

def  genA  =  createIdGenerator("A")  assert  genA()  ==  "A-­‐1"  assert  genA()  ==  "A-­‐2"  assert  genA()  ==  "A-­‐3"  

def  genB  =  createIdGenerator("B")  assert  genB()  ==  "B-­‐1"  assert  genB()  ==  "B-­‐2"  assert  genB()  ==  "B-­‐3"  

assert  genA()  ==  "A-­‐4"

元々createIdGeneraterメソッドのローカル変数であるcounter

が、クロージャごとに個別に管理されているのがわかる

Page 46: Java開発の強力な相棒として今すぐ使えるGroovy

assertキーワード/Power Assert

Spockから正式採用したPower Assertが使える Spockの方が更に先に進んでいて若干高機能(適合率を表示するとか)

Assertion  failed:    

assert  a.collect  {  it  *  2  }.reverse()  ==  [6,  4,  0]                |  |                                    |                  |                |  [2,  4,  6]                    [6,  4,  2]  false                [1,  2,  3]  

  at  ConsoleScript78.run(ConsoleScript78:2)

//  わざと3つ目を間違えてみる  

def  a  =  [1,  2,  3]  assert  a.collect  {  it  *  2  }.reverse()  ==  [6,  4,  0]

Page 47: Java開発の強力な相棒として今すぐ使えるGroovy

Groovy JDK/GDK

GroovyがJavaの標準APIに追加した便利なAPI群 Javaの不便な点をAPIレベルで改善できる

printlnもObjectに実装されたGDK APIのひとつ System.out.printlnに委譲しているだけ

後述するコレクションAPIもGDKとして実装されている

すべての品揃えは以下のAPIドキュメントを参照のこと http://docs.groovy-lang.org/docs/latest/html/groovy-jdk/

Page 48: Java開発の強力な相棒として今すぐ使えるGroovy

GDKの例

//  Groovy本家サイトのHTMLを表示する  

println  new  URL("http://groovy-­‐lang.org/").getText()  

//  ファイルの中身を表示する  

println  new  File("/my/some.text/").getText()

Page 49: Java開発の強力な相棒として今すぐ使えるGroovy

コレクション操作

各種の内部イテレーション記法が使える 外部イテレーション forやiteratorなどで外側から要素を回す

内部イテレーション 各要素に適用すべき処理をクロージャ/ラムダなどでコレクションに渡して、コレクション自体が内部でループする GroovyのコレクションAPIは、GDKとして提供されている Java 8のStream APIもこちら

Page 50: Java開発の強力な相棒として今すぐ使えるGroovy

コレクション操作:リスト

List  l  =  [1,  2,  3,  4,  5]  

//  各要素に対してクロージャの処理を適用する  

l.each  {  number  -­‐>  print  number  }  //=>  12345  

//  各要素に対してクロージャの処理を適用した結果のリストを取得する  

assert  l.collect  {  it  *  2  }  ==  [2,  4,  6,  8,  10]  

//  各要素に対してクロージャの処理を適用した結果が真の要素のみを残す  

assert  l.findAll  {  it  %  2  ==  0  }  ==  [2,  4]  

//  指定したセパレータで結合した文字列を返す  

assert  l.join(":")  ==  "1:2:3:4:5"  

//  合計値を算出する  

assert  l.sum()  ==  15

Page 51: Java開発の強力な相棒として今すぐ使えるGroovy

コレクション操作:マップMap  m  =  [a:  1,  b:  2,  c:  3]  

//  クロージャ引数を1つだけ宣言すると、Map.Entryが受け取れる  

m.each  {  Map.Entry  entry  -­‐>          print  entry.key  +  entry.value  }  //=>  a1b2c3  

//  クロージャ引数を2つ宣言すると、それぞれキーと値が受け取れる  

m.each  {  key,  value  -­‐>          print  key  +  value  }  //=>  a1b2c3  

//  各要素に対してクロージャの処理を適用した結果のリストを取得する  

assert  m.collect  {  "${it.key}:${it.value}"  }  ==  ["a:1",  "b:2",  "c:3"]  

//  クロージャの返す値が最も大きい要素を取得する  

assert  m.max  {  it.value  }.key  ==  "c"

マップにも基本的に同じAPIが用意されている(コレクションの特性上、微妙に品揃えは違う)

Page 52: Java開発の強力な相棒として今すぐ使えるGroovy

デフォルトimport済みパッケージ

高頻度で使うこれらのパッケージはデフォルトでimport済み java.lang.*  java.io.*  java.net.*  java.util.*  groovy.lang.*  groovy.util.*  java.math.BigDecimal  java.math.BigInteger  

(参考)別名をつけてimportすることもできるimport  java.lang.NullPointerException  as  NPE  

throw  new  NPE("aliased  import  sample")

Page 53: Java開発の強力な相棒として今すぐ使えるGroovy

GroovyBeans

JavaBeansに対するGroovyの強化サポート プロパティに対するgetter/setterの自動生成

class  Book  {          String  title  }  def  book  =  new  Book(title:  "プログラミングGROOVY")  

//  getterが自動生成されている  

assert  book.getTitle()  ==  "プログラミングGROOVY"  

//  setterが自動生成されている  

book.setTitle("JavaからGroovyへ")  

assert  book.getTitle()  ==  "JavaからGroovyへ"

Page 54: Java開発の強力な相棒として今すぐ使えるGroovy

GroovyBeansclass  GroovyBeansSample  {          public  String  p  =  "PUBLIC"          final  String  f  =  "FINAL"          String  g  =  "GetterImplemented"          String  getG()  {  "getGの戻り値:  $g"  }  

}  

def  sample  =  new  GroovyBeansSample()  

//  publicなどをアクセス修飾子を付けるとgetter/setterは自動生成されない  

sample.getP()          //=>  groovy.lang.MissingMethodException  sample.setP("x")    //=>  groovy.lang.MissingMethodException  

//  finalを付けるとsetterは自動生成されない  

assert  sample.getF()  ==  "FINAL"  sample.setF("x")    //=>  groovy.lang.MissingMethodException  

//  自前で実装したアクセサメソッドは自動生成されない  

assert  sample.getG()  ==  "getGの戻り値:  GetterImplemented"  

sample.setG("xxx")  assert  sample.getG()  ==  "getGの戻り値:  xxx"

常に無条件で自動生成するわけではない

Page 55: Java開発の強力な相棒として今すぐ使えるGroovy

GroovyBeans

プロパティアクセスの簡略記法class  Book  {          String  title  }  def  book  =  new  Book(title:  "プログラミングGROOVY")  

//  インスタンス変数への直接参照のようにみえるがgetterを経由している  

assert  book.title  ==  "プログラミングGROOVY"  

//  インスタンス変数への直接代入のようにみえるがsetterを経由している  

book.title  =  "JavaからGroovyへ"  

assert  book.title  ==  "JavaからGroovyへ"  

//  getXxx()という名前の引数なしのメソッドであればプロパティ記法でアクセスできる  

//  つまり、GroovyBeansに限らず名前規約が一致していれば、この簡略記法は使える  

assert  book.class  ==  book.getClass()

Page 56: Java開発の強力な相棒として今すぐ使えるGroovy

Grape

Mavenリポジトリから直接Jarをダウンロードし、クラスパスに通してからスクリプトを実行できる ダウンロードしたファイルは $HOME/.groovy/grapes配下に格納される

@Grab('org.apache.commons:commons-­‐lang3:3.2')  import  org.apache.commons.lang3.StringUtils  

List  l  =  [1,  2,  3,  4,  5]  

assert  StringUtils.join(l,  ':')  ==  "1:2:3:4:5"  

//  本当はこの程度の処理であればGDKで十分  

assert  l.join(':')  ==  "1:2:3:4:5"後半で示すサンプルはGrapeを使って即実行できるスクリプト形式にしている

Page 57: Java開発の強力な相棒として今すぐ使えるGroovy

便利な演算子

等値演算子 == Javaではインスタンスの同一性のための使うが、Groovyではequals呼び出しになっている Stringの比較で普通に==が使える! インスタンス同一性のチェックにはObject#is()を使う

エルビス演算子 ?: A  ?:  B  

三項演算子 A  ?  A  :  B  の省略形

セーフナビゲーション演算子 ?. a?.b?.c()  

nullではない場合のみ、右側の呼び出しを続行する

展開ドット演算子 *. [a:1,  b:2,  c:3]*.value  ==  [1,  2,  3]  

collect  {  it.value  }  の短縮形のイメージ

#ccc_cd1 で紹介されました!

#ccc_cd1 で紹介されました!

Page 58: Java開発の強力な相棒として今すぐ使えるGroovy

レンジ(範囲)

範囲を表すコレクション groovy.lang.Range 始点と終点を指定してその間の要素をIterableに扱う

for  (int  i  :  1..9)  {  //  閉区間(9を含む)  

       print  i  }  //=>  123456789  

for  (int  i  :  1..<9)  {  //  半開区間(9を含まない)  

       print  i  }  //=>  12345678  

//  Range#toList()でリストに変換できる  

assert  (1..5).toList()  ==  [1,  2,  3,  4,  5]

Page 59: Java開発の強力な相棒として今すぐ使えるGroovy

正規表現サポート

正規表現をサポートする演算子やリテラルがある

//  「==~」完全一致によるマッチング結果の真偽値を返す  

assert        "abc"  ==~  /a.c/  assert  !  ("abc"  ==~  /bc/)    //  部分一致ではない  

//  実際は、Matcher#matches()の呼び出しになっている  

assert      "abc".matches(/a.c/)  assert  !  "abc".matches(/bc/)  

//  「=~」部分一致によるマッチング結果のMatcherオブジェクトを返す  

assert  "abc"  =~  /a.c/  assert  "abc"  =~  /bc/              //  部分一致OK  

//  実は、演算自体の戻り値はMatcherオブジェクトになっている  

//  Matcherが真偽値判定されるタイミングで、  

//  Matcher#find()が裏で呼ばれてその結果が返っている  

assert  ("abc"  =~  /a.c/).getClass()  ==  java.util.regex.Matcher

Page 60: Java開発の強力な相棒として今すぐ使えるGroovy

論理値/Groovy Truth

Groovyではboolean/Boolean以外の値についても、真偽判定できる

assert  !  0                                            //  整数:  0は偽  

assert      1                                            //  整数:  0以外は真  

assert  !  []                                          //  リスト:  空リストは偽  

assert      ["a"]                                    //  リスト:  空リスト以外は真  

assert  !  [:]                                        //  マップ:  空マップは偽  

assert      [key:'value']                    //  マップ:  空マップ以外は真  

assert  !  ""                                          //  文字列:  空文字列は偽  

assert      "a"                                        //  文字列:  空文字列以外は真  

assert  !("abcdefg"  =~  /a.*X/)      //  正規表現:  マッチしないと偽  

assert      "abcdefg"  =~  /cde/          //  正規表現:  マッチすると真  

assert  !  null                                      //  nullは偽  

assert      new  Object()                      //  それ以外のオブジェクト:  null以外は真

Page 61: Java開発の強力な相棒として今すぐ使えるGroovy

演算子オーバーロード

GroovyではJavaと同等の各種演算子が使える 実は、それぞれの演算子は対応する特定のメソッド呼び出しに変換されている つまり、演算子オーバロードが可能 GDKでも多数活用されている 例えば、「+」→「plus()」、「-」→「minus()」、「<<」→「leftShift()」

演算子と対応するメソッドの一覧 http://groovy-lang.org/operators.html#Operator-Overloading

class  MyObject  {          String  name          MyObject(name)  {  this.name  =  name  }          MyObject  plus(MyObject  o)  {                  return  new  MyObject(name  +  ":"  +  o.name)          }  }  

def  obj1  =  new  MyObject("OBJECT_1")  def  obj2  =  new  MyObject("OBJECT_2")  

def  obj3  =  obj1  +  obj2  assert  obj3.name  ==  "OBJECT_1:OBJECT_2"

Page 62: Java開発の強力な相棒として今すぐ使えるGroovy

AST変換

抽象構文木(Abstract Syntax Tree)レベルでのコード変換技術 コンパイルの過程で、アノテーションでマーキングした対象箇所に、任意のコードの追加・置換ができる Groovyシンタックスの意味自体を改変する「グローバルAST変換」技術もあるがあまり使われない

例 Grape(@Grab) ロギング(@Log, @Commons, @Log4j, @Slf4j) シングルトン(@Singleton) 不変オブジェクト(@Immutable) 自前クラスの基本要素(@ToString, @EqualsAndHashCode, @Canonical, @InheritConstructors)

Page 63: Java開発の強力な相棒として今すぐ使えるGroovy

AST変換: @Grabと@Log

//  Mavenセントラルリポジトリからダウンロード&クラスパスに指定  

@Grab("log4j:log4j")  import  groovy.util.logging.Log4j  

@Log4j  class  Sample  {          def  doIt()  {                  //  ロガーとしてlog変数が使える  

               log.fatal  "Hello"          }  }  

new  Sample().doIt()  //=>  FATAL  -­‐  Hello

Page 64: Java開発の強力な相棒として今すぐ使えるGroovy

AST変換: @Singleton

@groovy.lang.Singleton  class  Sample  {          String  value  }  

//  インスタンス初期化機構とgetInstance()クラスメソッドが  

//  追加されるので、シングルトンとしてすぐに使える  

assert  Sample.getInstance().value  ==  null  Sample.instance.value  =  "シングルトン"  

assert  Sample.instance.value  ==  "シングルトン"  

//  もちろん同一インスタンス  

assert  sample.instance.is(Sample.instance)

Page 65: Java開発の強力な相棒として今すぐ使えるGroovy

AST変換: @Immutable

@groovy.transform.Immutable  class  Sample  {          String  value  }  

def  sample  =  new  Sample(value:  "HOGE")  

sample.value  =  "変更できない"  

//=>  groovy.lang.ReadOnlyPropertyException:  //          Cannot  set  readonly  property:  value  for  class:  Sample  

Page 66: Java開発の強力な相棒として今すぐ使えるGroovy

AST変換: @ToString, @EqualsAndHashCode, @TupleConstructors

@groovy.transform.TupleConstructor  @groovy.transform.ToString  @groovy.transform.EqualsAndHashCode  class  Sample  {          String  a          String  b          int  c  }  

//  @TupleConstructorによって宣言したフィールドの順に引数を受け取るコンストラクタが生成される  

def  sample  =  new  Sample("A",  "B",  3)  

//  @ToStringによってそれっぽい文字列を構成するtoString()が生成される  

println  sample.toString()  //  =>  Sample(A,  B,  3)  

//  @EqualsAndHashCodeによって、プロパティの値をベースにした等値判定をするequals()が生成される  

assert  sample  ==  new  Sample("A",  "B",  3)  assert  sample  !=  new  Sample("A",  "B",  123)  

//  もちろん、equals()の実装契約として必須であるhashCode()も合わせて実装されている  

assert  sample.hashCode()  ==  new  Sample("A",  "B",  3).hashCode()  assert  sample.hashCode()  !=  new  Sample("A",  "B",  123).hashCode()  

//  (参考)  @Canonicalは、@ToStringと@EqualsAndHashCodeの組み合わせのエイリアス

Page 67: Java開発の強力な相棒として今すぐ使えるGroovy

静的Groovy

@TypeChecked コンパイル時に静的型チェックする lintのようなもの 実行時はいつも通り動的に

@CompileStatic 指定した範囲を静的型付けとしてコンパイルする 実行時も静的に(性能的に有利) Groovyの動的な側面に依存した機能が使えない ダックタイピング、privateの呼び出し、など

性能的にカリカリにしたい箇所に、部分的に付けると良い

Page 68: Java開発の強力な相棒として今すぐ使えるGroovy

静的Groovy: @TypeCheckedclass  MyList  {          private  List<String>  list  =  []                      def  store(name)  {                  list  <<  name          }  }  

def  list  =  new  MyList()  list.store  "A"  list.store  "B"  list.store  "C"  

println  list.dump()  //=>  <MyList@5c042a81  list=[A,  B,  C]>

StringインスタンスをObject型で受けとって、listに追加する

期待通り動く

Page 69: Java開発の強力な相棒として今すぐ使えるGroovy

静的Groovy: @TypeCheckedclass  MyList  {          private  List<String>  list  =  []                    @groovy.transform.TypeChecked          def  store(name)  {                  list  <<  name          }  }  

def  list  =  new  MyList()  list.store  "A"  list.store  "B"  list.store  "C"  

println  list.dump()  //=>  [Static  type  checking]  -­‐  Cannot  call  <T>  java.util.List  <String>#leftShift(T)  with  arguments  [java.lang.Object]      at  line:  7,  column:  9

コンパイル時にエラーが発生する

このメソッドを静的型チェックすると...

Page 70: Java開発の強力な相棒として今すぐ使えるGroovy

静的Groovy: @TypeCheckedclass  MyList  {          private  List<String>  list  =  []                    @groovy.transform.TypeChecked          def  store(String  name)  {                  list  <<  name          }  }  

def  list  =  new  MyList()  list.store  "A"  list.store  "B"  list.store  "C"  

println  list.dump()  //=>  <MyList@5c042a81  list=[A,  B,  C]>

String型を明示すると...

また動くようになった!

Page 71: Java開発の強力な相棒として今すぐ使えるGroovy

静的Groovy: 非@CompileStaticlong  fib(long  n)  {          if  (n  <  2)  return  1          return  fib(n  -­‐  2)  +  fib(n  -­‐  1)  }  

def  start  =  System.currentTimeMillis()  

def  num  =  40  def  ans  =  fib(num)  println  "fib($num)  =  ${ans}"  

println  "Total:  ${System.currentTimeMillis()  -­‐  start}  msec"  

//=>  fib(40)  =  165580141  //      Total:  1575  msec

Page 72: Java開発の強力な相棒として今すぐ使えるGroovy

静的Groovy: @CompileStaticimport  groovy.transform.CompileStatic  

@CompileStatic  long  fib(long  n)  {          if  (n  <  2)  return  1          return  fib(n  -­‐  2)  +  fib(n  -­‐  1)  }  

def  start  =  System.currentTimeMillis()  

def  num  =  40  def  ans  =  fib(num)  println  "fib($num)  =  ${ans}"  

println  "Total:  ${System.currentTimeMillis()  -­‐  start}  msec"  

//=>  fib(40)  =  165580141  //      Total:  569  msec 約3倍!<1575 msec

Page 73: Java開発の強力な相棒として今すぐ使えるGroovy

(参考)AST変換: @Memoizedimport  groovy.transform.Memoized  

@Memoized  long  fib(long  n)  {          if  (n  <  2)  return  1          return  fib(n  -­‐  2)  +  fib(n  -­‐  1)  }  

def  start  =  System.currentTimeMillis()  

def  num  =  40  def  ans  =  fib(num)  println  "fib($num)  =  ${ans}"  

println  "Total:  ${System.currentTimeMillis()  -­‐  start}  msec"  

//=>  fib(40)  =  165580141  //      Total:  4  msec !!!!!!?????? <569 msec <1575 msec

参照透過な関数の場合、メモ化(引数と結果の組み合わせをキャッシュ)の効果が強力に活

用できる場合がある

Page 74: Java開発の強力な相棒として今すぐ使えるGroovy

Groovy コードの実行

Page 75: Java開発の強力な相棒として今すぐ使えるGroovy

実行可能なコード形式

Page 76: Java開発の強力な相棒として今すぐ使えるGroovy

実行可能なコード形式

Groovyプログラムとして実行可能なのは... mainメソッド持つクラス(Javaと同等) Groovyスクリプト JUnitのテストケース Runnableの実装クラス

Page 77: Java開発の強力な相棒として今すぐ使えるGroovy

mainメソッド持つクラス

//  in  HelloMain.groovy  

class  HelloMain  {          static  void  main(String...  args)  {                  println  "Hello,  Main!"          }  }  

//=>  Hello,  Main!

Page 78: Java開発の強力な相棒として今すぐ使えるGroovy

Groovyスクリプト

//  in  hello.groovy  

println  "Hello,  Script!"  

//=>  Hello,  Script!

クラスの外側のルートレベルで直接コードが書かれている=Groovyスクリプト

ちなみに、コンパイルされると、Scriptクラスのインスタンスになる

public  class  hello  extends  groovy.lang.Script  {      public  static  transient  boolean  __$stMC;      public  hello();      public  hello(groovy.lang.Binding);      public  static  void  main(java.lang.String...);      public  java.lang.Object  run();      protected  groovy.lang.MetaClass  $getStaticMetaClass();  }

Page 79: Java開発の強力な相棒として今すぐ使えるGroovy

JUnitのテストケース

//  in  HelloTest.groovy  

import  junit.framework.TestCase  

class  HelloTest  extends  TestCase  {          void  testHello()  {                  println  "Hello,  JUnit!"          }  }  

//=>  .Hello,  JUnit!  //  //      Time:  0.047  //  //      OK  (1  test)  //

GroovyがJUnitを同梱しているので別途JARを用意する必要はない

Page 80: Java開発の強力な相棒として今すぐ使えるGroovy

Runnableの実装クラス

//  in  HelloRunnable.groovy  

class  HelloRunnable  implements  Runnable  {          void  run()  {                  println  "Hello,  Runnable!"          }  }  

//=>  Hello,  Runnable!

Page 81: Java開発の強力な相棒として今すぐ使えるGroovy

実行可能なコード形式

Groovyプログラムとして実行可能なのは... mainメソッド持つクラス(Javaと同等) Groovyスクリプト JUnitのテストケース Runnableの実装クラス

今回のケースではとりあえず、これで十分

Page 82: Java開発の強力な相棒として今すぐ使えるGroovy

実行方法

Page 83: Java開発の強力な相棒として今すぐ使えるGroovy

各種実行方法

groovy java -jar groovy-all.jar

groovyc + java groovyConsole groovysh GroovyServ スクリプト起動の高速化

Groovy Web Console https://groovyconsole.appspot.com/

Page 84: Java開発の強力な相棒として今すぐ使えるGroovy

各種実行方法

groovy java -jar groovy-all.jar

groovyc + java groovyConsole groovysh GroovyServ スクリプト起動の高速化

Groovy Web Console https://groovyconsole.appspot.com/

だいたいこの辺を使っておけばOK

Page 85: Java開発の強力な相棒として今すぐ使えるGroovy

groovyコマンド

Page 86: Java開発の強力な相棒として今すぐ使えるGroovy

java -jar groovy-all.jar == groovyコマンド

All-In-OneのJARファイルさえあれば、groovyコマンドがなくても実行できる!

Page 87: Java開発の強力な相棒として今すぐ使えるGroovy

groovyc + java

滅多に使わない

Page 88: Java開発の強力な相棒として今すぐ使えるGroovy

groovyConsole

編集して、Ctrl+Rで実行できる

実行結果を表示Ctrl+Wでクリア

引数なしでもOK

Page 89: Java開発の強力な相棒として今すぐ使えるGroovy

groovysh

限定的ながらもTabでコード補完ができる

Page 90: Java開発の強力な相棒として今すぐ使えるGroovy

高速起動 GroovyServ

http://kobo.github.io/groovyserv/

Page 91: Java開発の強力な相棒として今すぐ使えるGroovy

Groovy web console

クリックで実行

https://groovyconsole.appspot.com/

インストール不要で手軽に試せる

Page 92: Java開発の強力な相棒として今すぐ使えるGroovy

ユースケース

Page 93: Java開発の強力な相棒として今すぐ使えるGroovy

(再掲)Groovyの使いどころ

メインのプログラミング言語 Grails/Spring Boot/Vert.x/Android

設定ファイルの記述言語(as DSL) Gradle/Spring Boot/Spring Framework

システムのプラグイン機構/拡張ポイント Javaから外部のGroovyスクリプトを簡単に実行できる Jenkins

プロジェクトの開発支援スクリプト DBのセットアップ、Excel操作等

Page 94: Java開発の強力な相棒として今すぐ使えるGroovy

開発支援ツールとしての活用

Groovyは、たとえ対象システムの開発言語として採用しない場合でも、Javaによる開発を支援するツールとして非常に有用

なるほどね

Page 95: Java開発の強力な相棒として今すぐ使えるGroovy

Java APIのお試し

Page 96: Java開発の強力な相棒として今すぐ使えるGroovy

例えば

標準APIを試す ○○の場合はどういう動作をするんだったっけ? 正規表現はこれで良いのかな?

初めて使うサードパーティ製のライブラリを試す

Page 97: Java開発の強力な相棒として今すぐ使えるGroovy

お試し環境

groovyConsole上で試す シンプルなエディタで試行錯誤できる Grapeを使ってサードパーティライブラリも試せる わかりやすくてお手軽

groovyshで試す JavaとGroovyの標準APIであれば、Tabによるコード補完が効く点でちょっと便利

エディタ+groovy (or GroovyServ) エディタの機能ですぐに実行できる環境をつくると便利 (例)vim + quickrun.vim + GroovyServ http://nobeans.hatenablog.com/entry/20111024/1319435155

ちなみに、この資料のサンプルコードはほとんどgroovyConsoleで書きました

Page 98: Java開発の強力な相棒として今すぐ使えるGroovy

groovyConsoleの例

Page 99: Java開発の強力な相棒として今すぐ使えるGroovy

XMLのパース

Page 100: Java開発の強力な相棒として今すぐ使えるGroovy

例えば

設定ファイル内容の一覧を出力する JUnitのテストレポートをパースして自動的に進捗報告資料に追加する Rest APIの結果をチェックする

Page 101: Java開発の強力な相棒として今すぐ使えるGroovy

XmlParser/XmlSlurper

Groovy標準APIのXmlParserが便利 兄弟分として XmlSlurper(~すらーぱー)がある XmlParser:DOM的(インメモリ、変更可能) XmlSlurper:SAX的(ストリーム処理、参照専用)

細かい点で差異はあるものの、シンプルな参照に限定したAPIの使い勝手はほぼ同じ メモリ展開が難しい巨大なファイルを対象とするのでなければ、XmlParserを選択しておけばOK

Page 102: Java開発の強力な相棒として今すぐ使えるGroovy

XMLParserで属性やテキストを参照する例def  inputXml  =  """  <root>      <items>          <item  id="1"  name="あいうえお">OK</item>  

       <item  id="2"  name="かきくけこ">NG</item>  

       <item  id="3"  name="さしすせそ">OK</item>  

   </items>  </root>  """  def  root  =  new  XmlParser().parseText(inputXml)  //  <root>に対応するgroovy.util.Nodeオブジェクト  

//  すべてのitem要素をフォーマットして出力する  

root.items.item.each  {  Node  item  -­‐>          println  "${item.@id}:  ${item.@name}  =>  ${item.text()}"  }  //=>  1:  あいうえお  =>  OK  

//      2:  かきくけこ  =>  NG  

//      3:  さしすせそ  =>  OK  

//  OKのitem要素のみをフォーマットして出力する  

root.items.item.findAll  {  it.text()  ==  "OK"  }.each  {          println  "${it.@id}:  ${it.@name}  =>  ${it.text()}"  }  //=>  1:  あいうえお  =>  OK  

//      3:  さしすせそ  =>  OK

この時点でXMLはパースされて、Nodeツリーがメモリ上に展開済み

GPathという記法でNodeのコレクションを特定

属性値は「@+属性名」、子要素のテキストは「text()」で参照

each, findAllなどのコレクション操作がそのまま適用できる

Page 103: Java開発の強力な相棒として今すぐ使えるGroovy

HTML/XMLの出力

Page 104: Java開発の強力な相棒として今すぐ使えるGroovy

例えば

自動的に収集した情報を元にHTMLレポートを出力する システムにインポートするXMLファイルを生成する

Page 105: Java開発の強力な相棒として今すぐ使えるGroovy

MarkupBuilder

Groovy標準APIのMarkupBuilderが便利 タグでマークアップされたテキストを生成する 波括弧のブロックで階層構造を表現できる if文やループ制御構文が使える

Page 106: Java開発の強力な相棒として今すぐ使えるGroovy

マップの情報を元にHTMLを出力する例def  generateHtml  =  {  data,  writer  -­‐>      def  reportTitle  =  '試験実施日時報告'  

   def  formatCount  =  {  now,  latest  -­‐>          def  diffCount  =  now  -­‐  latest          return  "${now}  (${diffCount  >  0  ?  "+"  :  ""}${diffCount})"      }      new  groovy.xml.MarkupBuilder(writer).html  {          head  {              title  reportTitle          }          body(style:  "background:  #afa")  {              h1  reportTitle              h2  '試験件数等'  

           ul  {                  li  "試験項目数:  ${formatCount(data.tests,  data.latest.tests)}"  

               li  "終了件数:  ${formatCount(data.done,  data.latest.done)}"  

               li  "バグ件数:  ${formatCount(data.issues,  data.latest.issues)}"  

           }              h2  '備考'  

           if  (data.remarks)  {                  ul  {                      data.remarks.each  {                          li(it)      }  }  }  }  }  }  

def  data  =  [      tests:  1230,  done:      350,  issues:  123,      latest:  [tests:  1235,  done:      320,  issues:  93],      remarks:  ["進捗は特に問題なし",  "インフルエンザが流行中なので不安"]  

]  new  File("/tmp/daily-­‐test-­‐report.html").withWriter  {  writer  -­‐>      generateHtml(data,  writer)  }

Page 107: Java開発の強力な相棒として今すぐ使えるGroovy

マップの情報を元にHTMLを出力する例    //...      new  groovy.xml.MarkupBuilder(writer).html  {          head  {              title  reportTitle          }          body(style:  "background:  #afa")  {              h1  reportTitle              h2  '試験件数等'  

           ul  {                  li  "試験項目数:  ${formatCount(data.tests,  data.latest.tests)}"  

               li  "終了件数:  ${formatCount(data.done,  data.latest.done)}"  

               li  "バグ件数:  ${formatCount(data.issues,  data.latest.issues)}"  

           }              h2  '備考'  

           if  (data.remarks)  {                  ul  {                      data.remarks.each  {                          li(it)      }  }  }  }  }      //...

Page 108: Java開発の強力な相棒として今すぐ使えるGroovy

MarkupBuilderについてもう少し補足def  builder  =  new  groovy.xml.MarkupBuilder()  

def  existMethod(a)  {  "EXIST_METHOD:  ${a}"  }  

//  最初の呼び出しで使った名前がルート要素のタグ名になる  

builder.aaa  {          //  存在しないメソッド名で呼び出すと要素宣言と見なされる。引数は子要素になる。  

       bbb  "BBB"                    //  引数をマップで指定すると属性値になる  

       ccc(c1:  "C1",  c2:  "C2")  

       //  引数としてクロージャを渡すとネストになる  

       ddd  {                  xxx  "XXX"          }  

       //  制御構文がそのまま使える  

       if  (false)  {                  //  ここが実行されなければ出力されない  

               ignoredThis  "IGNORED"          }                    //  存在するメソッドであれば単にそのメソッドが呼ばれるだけで要素は生成されない  

       //  存在しないメソッドを実行しようとすることが、要素生成のトリガとなる  

       existMethod  "ただのメソッド呼び出し"  

}

<aaa>      <bbb>BBB</bbb>      <ccc  c1='C1'  c2='C2'  />      <ddd>          <xxx>XXX</xxx>      </ddd>  </aaa>  

このように、Groovyの「*Builder」は存在しないメソッド呼び出し(methodMissing)をトリガにして構造をビルドしていくクラスになっている

Page 109: Java開発の強力な相棒として今すぐ使えるGroovy

HTMLスクレイピング

Page 110: Java開発の強力な相棒として今すぐ使えるGroovy

例えば

定期レポートのための情報を収集する 開発中のWebアプリのテストの一環として、ある画面のHTMLを取得して、内容をチェックする

Page 111: Java開発の強力な相棒として今すぐ使えるGroovy

HTMLスクレイピング

URL#getText() HTMLテキストを取得すればいい場合は一番簡単

XmlParser/XmlSlurper 整形式であるXHMLの場合は単品でOK 非整形式のHTMLの場合はNekoHTMLを併用すればOK http://nekohtml.sourceforge.net/

jsoup jQuery風のセレクタAPIが使える http://jsoup.org/

Page 112: Java開発の強力な相棒として今すぐ使えるGroovy

HTMLスクレイピング: URL#getText()String  html  =  new  URL("http://groovy-­‐lang.org/").text  

//  1行ずつチェックしてURLをパースする  

def  urls  =  html          //  1行ずつのリストにする  

       .readLines()          //  行中にURLパターンがあったらそれを返す(なければnull)  

       .collect  {  line  -­‐>                  if  (line  =~  $/.*(https?://[a-­‐zA-­‐Z0-­‐9%?._]+).*/$)  {                          return  java.util.regex.Matcher.lastMatcher.group(1)                  }          }          //  nullを除外する  

       .findAll  {  it  !=  null  }          //  重複したURLを除去する  

       .unique()  

//  ソートして表示する  

urls.sort().each  {  println  it  }

Page 113: Java開発の強力な相棒として今すぐ使えるGroovy

HTMLスクレイピング: XmlParser + NekoHTML@Grab('net.sourceforge.nekohtml:nekohtml:1.9.21')  import  org.cyberneko.html.parsers.SAXParser  import  groovy.util.Node  

def  parser  =  new  XmlParser(new  SAXParser())  

Node  html  =  parser.parse("http://groovy-­‐lang.org/")  

//  1行ずつチェックしてURLをパースする  

def  urls  =  html          //  html配下のすべての子要素のaタグのhref属性値を集める  

       .'**'.A.@href          //  http(s)のものだけ抽出する  

       .findAll  {                    it  ==~  /https?:.*/          }          //  重複したURLを除去する  

       .unique()  

//  ソートして表示する  

urls.sort().each  {  println  it  }

Page 114: Java開発の強力な相棒として今すぐ使えるGroovy

HTMLスクレイピング: jsoup@Grab('org.jsoup:jsoup:1.8.1')  import  org.jsoup.Jsoup  import  org.jsoup.nodes.Document  

Document  doc  =  Jsoup.connect("http://groovy-­‐lang.org/").get()  

def  urls  =  doc          //  すべてのaタグのhref属性を集める  

       .select('a')*.attr("href")          //  http(s)のものだけ抽出する  

       .findAll  {                    it  ==~  /https?:.*/          }          //  重複したURLを除去する  

       .unique()  

//  ソートして表示する  

urls.sort().each  {  println  it  }

Page 115: Java開発の強力な相棒として今すぐ使えるGroovy

Groovy SQLによる RDBMS操作

Page 116: Java開発の強力な相棒として今すぐ使えるGroovy

例えば

テスト用ダミーデータをDBに大量投入する 定期レポートのための情報を収集する 保守のためデータベースの内容を定期的に監視する あるシステムから別のシステムにデータを移行する

Page 117: Java開発の強力な相棒として今すぐ使えるGroovy

Groovy SQL

Groovy標準APIのGroovy SQLが便利 クエリ発行と結果のResultSetからの値の取り出しなどが簡単に実行できる DataSetを使うと、コレクション操作のようにレコードの追加やイテレーションが実行できる

Page 118: Java開発の強力な相棒として今すぐ使えるGroovy

Groovy SQLでH2を操作する@Grab('com.h2database:h2')  @GrabConfig(systemClassLoader=true)  //  JDBCはシステムクラスローダから探されるので必要  

import  groovy.sql.Sql  

//  別途DataSourceやConnectionを用意するなら、Sqlのコンストラクタに渡せばOK  

def  db  =  Sql.newInstance("jdbc:h2:mem:sample",  "org.h2.Driver")  

//  Sql#execute()でDDLを実行する  

db.execute  """  create  table  person  (          name  varchar(255),          age  int  )  """  

//  Sql#executeUpdate()使うと、変更した行数が返る  

insertSql  =  "insert  into  person  (name,  age)  values  (?,  ?)"  assert  db.executeUpdate(insertSql,  ['Mike',    13])  ==  1  assert  db.executeUpdate(insertSql,  ['Junko',  14])  ==  1  

//  Sql#eachRow()は1行ごとに処理する(リソース低負荷)  

db.eachRow('select  *  from  person')  {  row  -­‐>          println  row.name  }  //=>  Mike  //      Junko  

//  Sql#rows()は結果をすべてメモリ上に取得する(リソース高負荷)  

println  db.rows('select  *  from  person').collect  {  it.name  }  //=>  [Mike,  Junko]

Page 119: Java開発の強力な相棒として今すぐ使えるGroovy

DataSetを使う例@Grab('com.h2database:h2')  @GrabConfig(systemClassLoader=true)  //  JDBCはシステムクラスローダから探されるので必要  

import  groovy.sql.Sql  

//  別途DataSourceやConnectionを用意するなら、Sqlのコンストラクタに渡せばOK  

def  db  =  Sql.newInstance("jdbc:h2:mem:sample",  "org.h2.Driver")  

//  Sql#execute()でDDLを実行する  

db.execute("""  create  table  person  (          name  varchar(255),          age  int  )  """)  

//  DataSetを使うとコレクションオブジェクト風にレコード操作ができる  

import  groovy.sql.DataSet  

DataSet  people  =  db.dataSet('person')  people.add(name:  'Mike',  age:13)  people.add(name:  'Junko',  age:  14)  people.add(name:  'Ken',  age:  23)  

people.each  {          println  "${it.name}  (${it.age})"  }  //=>  Mike  (13)  //      Junko  (14)  //      Ken  (23)

Page 120: Java開発の強力な相棒として今すぐ使えるGroovy

GExcelAPIによる Excel操作

Page 121: Java開発の強力な相棒として今すぐ使えるGroovy

例えば

ダミーデータの定義表として読み込む Excelデータから特定セルの値を読み込んで集計する コード生成の入力データとして

Page 122: Java開発の強力な相棒として今すぐ使えるGroovy

GExcelAPI

https://github.com/nobeans/gexcelapi Apache POIのGroovy風ラッパーライブラリ

POIを直接使った場合、セルを特定するインデックス指定がとても分かりづらい

GExcelAPIを使うと、Excelのセルラベルである「A1」でアクセスできる!

Page 123: Java開発の強力な相棒として今すぐ使えるGroovy

GExcelAPI@GrabResolver(name="bintray",  root="http://dl.bintray.com/nobeans/maven")  @Grab("org.jggug.kobo:gexcelapi:0.4")  import  org.jggug.kobo.gexcelapi.GExcel  

def  book  =  GExcel.open("/tmp/sample.xlsx")  def  sheet  =  book[0]    //  1シート目  

//  Excel風なDSLでセルの値を取得する  

println  sheet.A1.value    //=>  A1の値  

println  sheet.B2.value    //=>  B2の値  

println  sheet.C3.value    //=>  303.0  println  sheet.D4.dateCellValue.format("yyyy-­‐MM-­‐dd")  //=>  2015-­‐02-­‐29  

//  指定した矩形内でイテレーション  

sheet.A1_D4.each  {  row  -­‐>          println  row  }  //=>  [[A1の値,  B1の値,  301.0,  42041.0],  

//        [A2の値,  B2の値,  302.0,  42042.0],  

//        [A3の値,  B3の値,  303.0,  42043.0],  

//        [A4の値,  B4の値,  304.0,  42044.0]]

日付型のセルはプログラマが日付であることを意識して取得しなければならない

Page 124: Java開発の強力な相棒として今すぐ使えるGroovy

テンプレートエンジン

Page 125: Java開発の強力な相棒として今すぐ使えるGroovy

例えば

定型レポートをテンプレートから生成する 何らかの定義情報を元に、ソースコードを生成する

Page 126: Java開発の強力な相棒として今すぐ使えるGroovy

テンプレートエンジン?

複数行文字列リテラル+ String#stripMargin() SimpleTemplateEngine

Page 127: Java開発の強力な相棒として今すぐ使えるGroovy

複数行文字列リテラル+stripMargin()

String  applyTemplate(name,  title)  {          return  """\                  |こんにちは、${name}さん  

               |                  |本日は、${title}をご案内させていただきます。  

               |...                  |""".stripMargin()  }  

println  applyTemplate("日本  太郎",  "プログラミングGROOVY")  

//=>  こんにちは、日本  太郎さん  

//  //      本日は、プログラミングGROOVYをご案内させていただきます。  

//      ...

先頭行のエスケープ付き改行とstripMarginを使うことで、

インデントを自然な形に揃えられる

Page 128: Java開発の強力な相棒として今すぐ使えるGroovy

SimpleTemplateEngine

import  groovy.text.SimpleTemplateEngine  

String  applyTemplate(name,  title)  {          String  templateText  =  '''\                  |こんにちは、${name}さん  

               |                  |本日は、<%=  title  %>をご案内させていただきます。  

               |...                  |'''.stripMargin()          def  template  =  new  SimpleTemplateEngine().createTemplate(templateText)  

def  binding  =  [name:  name,  title:  title]  return  template.make(binding)  

}  

println  applyTemplate("日本  太郎",  "プログラミングGROOVY")  

//=>  こんにちは、日本  太郎さん  

//  //      本日は、プログラミングGROOVYをご案内させていただきます。  

//      ...

JSP形式の変数展開もできる

テンプレート文字列を外部ファイルから読み込むようにすると良い(例)new File("template.tpl").text

#ccc_g4 でGradleからの利用例が紹介されたらしい?

Page 129: Java開発の強力な相棒として今すぐ使えるGroovy

(再掲)Groovyの使いどころ

メインのプログラミング言語 Grails/Spring Boot/Vert.x/Android

設定ファイルの記述言語(as DSL) Gradle/Spring Boot/Spring Framework

システムのプラグイン機構/拡張ポイント Javaから外部のGroovyスクリプトを簡単に実行できる Jenkins

プロジェクトの開発支援スクリプト DBのセットアップ、Excel操作等

万が一時間があれば紹介したい

Page 130: Java開発の強力な相棒として今すぐ使えるGroovy

Javaから Groovyを使う

Page 131: Java開発の強力な相棒として今すぐ使えるGroovy

例えば

システムにプラグイン機構を追加する 頻繁に変更されるビジネスロジック部分をGroovyスクリプトとして外だしする アプリの一部だけでも良いからGroovyで書きたい

Page 132: Java開発の強力な相棒として今すぐ使えるGroovy

JavaからGroovyを使う

Groovyで実装したクラスをJavaから利用する コンパイルしたクラスを同梱する Groovyのコンパイルには、groovycコマンドやGradleを使う クラスパスにgroovy-all.jarが含まれてさえいれば、普通に使える

Groovyソースコードから動的にクラスをロードする groovy-all.jarはもちろん必要

GroovyスクリプトをJavaから動的に実行する(CGI風) GroovyShell ちょっとスクリプトを実行するぐらいの用途ならば手軽で便利

GroovyScriptEngine 対象ディレクトリを事前指定するため、複数のGroovyスクリプトを取り扱うようなプラグイン機構などに向いている

Page 133: Java開発の強力な相棒として今すぐ使えるGroovy

コンパイルしたクラスを同梱する

コンパイルしたGroovyのクラスがクラスパスに通っていれば、普通に使える

Page 134: Java開発の強力な相棒として今すぐ使えるGroovy

Groovyソースコードから動的にクラスをロードする

GroovyClassLoaderを使うと、Groovyソースコードから実行時に動的にクラスロードできる

Page 135: Java開発の強力な相棒として今すぐ使えるGroovy

GroovyスクリプトをJavaから実行する: GroovyShell

Bindingというマップ的なオブジェクトを利用して、スクリプト上で利用可能な暗黙変数を渡すことができる

Page 136: Java開発の強力な相棒として今すぐ使えるGroovy

GroovyスクリプトをJavaから実行する: GroovyScriptEngine

スクリプトのルートディレクトリをあらかじめ指定しておく

Page 137: Java開発の強力な相棒として今すぐ使えるGroovy

まとめ

Page 138: Java開発の強力な相棒として今すぐ使えるGroovy

Groovyの使いどころ

メインのプログラミング言語 Grails/Spring Boot/Vert.x/Android

設定ファイルの記述言語(as DSL) Gradle/Spring Boot/Spring Framework

システムのプラグイン機構/拡張ポイント Javaから外部のGroovyスクリプトを簡単に実行できる Jenkins

プロジェクトの開発支援スクリプト DBのセットアップ、Excel操作等

Page 139: Java開発の強力な相棒として今すぐ使えるGroovy

というわけで、まずはこの辺から始めてみませんか?

メインのプログラミング言語 Grails/Spring Boot/Vert.x/Android

設定ファイルの記述言語(as DSL) Gradle/Spring Boot/Spring Framework

システムのプラグイン機構/拡張ポイント Javaから外部のGroovyスクリプトを簡単に実行できる Jenkins

プロジェクトの開発支援スクリプト DBのセットアップ、Excel操作等

これもおすすめ

Page 140: Java開発の強力な相棒として今すぐ使えるGroovy

参考情報

Page 141: Java開発の強力な相棒として今すぐ使えるGroovy

プログラミングGroovy

Java技術者を対象に、Groovyの基本から応用までを丁寧に説明しています 対象のGroovyバージョンが1.8とだいぶ古いのですが、記載されている内容はほとんど陳腐化してないので、今でもお勧めの一冊

http://gihyo.jp/book/2011/978-4-7741-4727-7

Page 142: Java開発の強力な相棒として今すぐ使えるGroovy

Gradle徹底入門

2014/11発売 世界に現存するGradle本の中でここまで突っ込んで説明したものはほぼないレベル 分厚いですが、その分情報がたっぷりです (私もレビュアで参加)

http://www.shoeisha.co.jp/book/detail/9784798136431

Page 143: Java開発の強力な相棒として今すぐ使えるGroovy

その他、参考URL

サンプルコード https://github.com/nobeans/jjug-ccc-2015-spring-groovy

Groovy Home http://groovy-lang.org/

Groovy JDK http://docs.groovy-lang.org/docs/latest/html/groovy-jdk/

Groovy 演算子オーバロード http://groovy-lang.org/operators.html#Operator-Overloading

GVM http://gvmtool.net/

GroovyServ http://kobo.github.io/groovyserv/

GExcelAPI https://github.com/nobeans/gexcelapi

NekoHTML http://nekohtml.sourceforge.net/

jsoup http://jsoup.org/

プログラミングGROOVY別冊:第8章 Groovy 2.0の新機能

http://beta.mybetabook.com/showpage/506162510cf2ffb79bb046b1

実用的なGroovy: JavaアプリケーションにGroovyを混ぜ込む

http://www.ibm.com/developerworks/jp/java/library/j-pg05245/

Embedding Groovy(JavaからGroovyを使う)

http://groovy.codehaus.org/Embedding+Groovy

Groovyの使いどころ~7つの導入パターン~ http://www.slideshare.net/nobeans/the-report-of-javaone2011-about-groovy

Page 144: Java開発の強力な相棒として今すぐ使えるGroovy

Java開発の強力な相棒として今すぐ使えるGroovy

Yasuharu Nakano / @nobeans2015-04-11 JJUG CCC 2015 Spring #ccc_g6