Easy Going Groovy(Groovyを気軽に使いこなそう)

3,398 views

Published on

Easy Going Groovy(Groovyを気軽に使いこなそう)

  1. 1. Groovyを気軽に つかいこなそう JJUG CCC 2010 BOF C-2 NTTソフトウェア株式会社 上原 潤二 2010.10.182010年10月19日火曜日
  2. 2. はじめに Slide # 2 JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  3. 3. 自己紹介 上原潤二 NTTソフトウェア株式会社 JGGUG運営委員 ブログ Grな日々 http://d.hatena.ne.jp/uehaj/ Grails徹底入門 2章執筆 JavaWorld記事執筆 3 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  4. 4. 本日の内容 Groovyはやわかり Groovyを使うとこんなに便利 GroovyServ Groovy 1.8の新機能 4 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  5. 5. Groovyはやわかり Slide # 5 JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  6. 6. Groovy JVM上で動作するスクリプト言語 簡潔・高機能 記述量Java比1/2∼1/5 Javaとの高い相互運用性 Groovy Class=Java Class Groovy Object=Java Object Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  7. 7. コード例: Javaimport java.io.*; BufferedReader bis = new BufferedReaderimport java.net.*; (new InputStreamReader(ins)); String line;public class SocketAccess { while ((line = bis.readLine()) != null) { System.out.println(line); public static void main(String[] args) { } Socket soc = null; } InputStream ins = null; catch (IOException e) { OutputStream outs = null; e.printStackTrace(); try { try { soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); } outs = soc.getOutputStream(); catch(IOException ex) {} outs.write("GET / HTTP/1.0nn".getBytes }()); } } 7 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  8. 8. コード例: Groovy!import java.io.*; BufferedReader bis = new BufferedReaderimport java.net.*; (new InputStreamReader(ins)); String line;public class SocketAccess { while ((line = bis.readLine()) != null) { System.out.println(line); public static void main(String[] args) { } Socket soc = null; } InputStream ins = null; catch (IOException e) { OutputStream outs = null; e.printStackTrace(); try { try { soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); } outs = soc.getOutputStream(); catch(IOException ex) {} outs.write("GET / HTTP/1.0nn".getBytes }()); } } 8 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  9. 9. コード例: Groovy!import java.io.*; BufferedReader bis = new BufferedReaderimport java.net.*; (new InputStreamReader(ins)); String line;public class SocketAccess { while ((line = bis.readLine()) != null) { System.out.println(line); public static void main(String[] args) { } Socket soc = null; } InputStream ins = null; catch (IOException e) { OutputStream outs = null; e.printStackTrace(); try { try { soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); } outs = soc.getOutputStream(); catch(IOException ex) {} outs.write("GET / HTTP/1.0nn".getBytes }()); } ポイント: 正しいJavaコードは一般に正 } しいGroovyコードでもある(例外もある) 8 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  10. 10. コード例: Groovy!import java.io.*; BufferedReader bis = new BufferedReaderimport java.net.*; (new InputStreamReader(ins)); String line;public class SocketAccess { while ((line = bis.readLine()) != null) { System.out.println(line); public static void main(String[] args) { } Socket soc = null; } InputStream ins = null; catch (IOException e) { OutputStream outs = null; e.printStackTrace(); try { try { soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); } outs = soc.getOutputStream(); catch(IOException ex) {} outs.write("GET / HTTP/1.0nn".getBytes }()); } } 9 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  11. 11. コード例: Groovy!import java.io.*; BufferedReader bis = new BufferedReaderimport java.net.*; (new InputStreamReader(ins)); String line;public class SocketAccess { while ((line = bis.readLine()) != null) { System.out.println(line); public static void main(String[] args) { } Socket soc = null; } InputStream ins = null; catch (IOException e) { OutputStream outs = null; e.printStackTrace(); try { try { soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); } outs = soc.getOutputStream(); catch(IOException ex) {} outs.write("GET / HTTP/1.0nn".getBytes } ポイント: java.io.*, java.net.*などは()); } 暗黙にimport済み } 9 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  12. 12. コード例: Groovy! BufferedReader bis = new BufferedReader (new InputStreamReader(ins)); String line;public class SocketAccess { while ((line = bis.readLine()) != null) { System.out.println(line); public static void main(String[] args) { } Socket soc = null; } InputStream ins = null; catch (IOException e) { OutputStream outs = null; e.printStackTrace(); try { try { soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); } outs = soc.getOutputStream(); catch(IOException ex) {} outs.write("GET / HTTP/1.0nn".getBytes }()); } } 10 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  13. 13. コード例: Groovy! BufferedReader bis = new BufferedReader (new InputStreamReader(ins)); String line;public class SocketAccess { while ((line = bis.readLine()) != null) { System.out.println(line); public static void main(String[] args) { } Socket soc = null; } InputStream ins = null; ポイント: クラス定義、mainメソッドは catch (IOException e) { OutputStream outs = null; 省略可 e.printStackTrace(); try { try { soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); } outs = soc.getOutputStream(); catch(IOException ex) {} outs.write("GET / HTTP/1.0nn".getBytes }()); } } 10 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  14. 14. コード例: Groovy! BufferedReader bis = new BufferedReader (new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } Socket soc = null; } InputStream ins = null; catch (IOException e) { OutputStream outs = null; e.printStackTrace(); try { try { soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); } outs = soc.getOutputStream(); catch(IOException ex) {} outs.write("GET / HTTP/1.0nn".getBytes }()); 11 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  15. 15. コード例: Groovy! BufferedReader bis = new BufferedReader ポイント: チェック例外 (new InputStreamReader(ins)); も非チェック扱い String line; while ((line = bis.readLine()) != null) { System.out.println(line); } Socket soc = null; } InputStream ins = null; catch (IOException e) { OutputStream outs = null; e.printStackTrace(); try { try { soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); } outs = soc.getOutputStream(); catch(IOException ex) {} outs.write("GET / HTTP/1.0nn".getBytes }()); 11 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  16. 16. コード例: Groovy! BufferedReader bis = new BufferedReader (new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } Socket soc = null; InputStream ins = null; OutputStream outs = null; soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0nn".getBytes()); 12 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  17. 17. コード例: Groovy! BufferedReader bis = new BufferedReader ポイント: 変数の型宣言 (new InputStreamReader(ins)); は省略可能 String line; while ((line = bis.readLine()) != null) { System.out.println(line); } Socket soc = null; InputStream ins = null; OutputStream outs = null; soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0nn".getBytes()); 12 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  18. 18. コード例: Groovy! bis = new BufferedReader(new InputStreamReader(ins)); def line = null; while ((line = bis.readLine()) != null) { System.out.println(line); } def soc = null; def ins = null; def outs = null; soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0nn".getBytes()); Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  19. 19. コード例: Groovy! bis = new BufferedReader(new ポイント: 読み込みスト InputStreamReader(ins)); リームの自動クローズなど def line = null; while ((line = bis.readLine()) != null) { System.out.println(line); } def soc = null; def ins = null; def outs = null; soc = new Socket("www.java-users.jp", 80); if (soc != null) soc.close(); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0nn".getBytes()); Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  20. 20. コード例: Groovy! bis = new BufferedReader(new InputStreamReader(ins)); def line = null; while ((line = bis.readLine()) != null) { System.out.println(line); } } new Socket("www.java-users.jp",80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".getBytes()); 14 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  21. 21. コード例: Groovy! bis = new BufferedReader(new ポイント: 行読み込みス InputStreamReader(ins)); トリームに対する行単位 def line = null; の処理と、自動クローズ while ((line = bis.readLine()) != null) { System.out.println(line); } } new Socket("www.java-users.jp",80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".getBytes()); 14 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  22. 22. コード例: Groovy! ins.eachLine{ line -> System.out.println(line); } } new Socket("www.java-users.jp",80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".getBytes()); 15 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  23. 23. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".getBytes()); ins.eachLine { line -> System.out.println(line); } } 16 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  24. 24. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".getBytes()); ins.eachLine { line -> System.out.println(line); } } 17 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  25. 25. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".getBytes()); ins.eachLine { line -> System.out.println(line); } } ポイント: プロパティア クセス記法でgetterを呼 び出せる 17 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  26. 26. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".bytes); ins.eachLine { line -> System.out.println(line); } } 18 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  27. 27. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".bytes); ins.eachLine { line -> System.out.println(line); } } ポイント: System.out.println, Ssytem.out.printなどは println,printと書ける 18 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  28. 28. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".bytes); ins.eachLine { line -> println(line); } } 19 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  29. 29. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".bytes); ins.eachLine { line -> println(line); } } ポイント: クロージャの引数 が1つなら、暗黙のクロー ジャ引数itで参照できる。 19 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  30. 30. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".bytes); ins.eachLine { println(it); } } 20 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  31. 31. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".bytes); ins.eachLine { println(it); } } ポイント: 行末のセミコロ ンは多くの場合省略可 20 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  32. 32. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".bytes) ins.eachLine { println(it) } } 21 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  33. 33. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0nn".bytes) ins.eachLine { println(it) } } ポイント: 式文のトップレ ベルがメソッド呼び出しな ら引数の括弧は省略可能 21 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  34. 34. コード例: Groovy! new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write "GET / HTTP/1.0nn".bytes ins.eachLine { println it } } 22 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  35. 35. HTTPに限れば println new URL("http://www.java-users.jp").text 23 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  36. 36. HTTPに限れば println new URL("http://www.java-users.jp").text JavaからGroovyに書き直すと、大抵数 分の1程度にはなる。 マップリテラル、リストリテラルなどもコードが短 くなる要因として良く示されるが、Java 7で採用さ れるので割愛。 23 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  37. 37. Groovy Eco System フレームワーク 付属ライブラリ群 Gaelyk Grails(Web) GSQL GSP,GORM SwingBuilder Griffon(GUI) MarkupBuilder 既存ツールへの組み込み Groovy GMaven,Maven3 設定ファイル記述/DSL Hudson JBoss Gant FreeMind 先進的な取り組み Gradle Spock,EasyB Gpars Groovy++ 24 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  38. 38. Groovyを使うとこん なに便利 Slide # 25 JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  39. 39. ケース1 やりたいこと 指定ファイルをbzip2圧縮して httpファイルアップロード 開発時に使用するツールとして メンバーの大半はJava開発者なので Javaで書きたい 26 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  40. 40. でも… Javaだと作成したプログラムをメン バーに配布するのが面倒! コンパイルして 実行可能Jarに? 依存Jar群(commonsのjarとか)をダ ウンロードしてもらって いやいっそ、Mavenで pom書いて いっそ、RubyやPerlで… orz 27 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  41. 41. そんな時こそGroovyですよ! @Grab(net.sourceforge.htmlunit:htmlunit:2.8) import com.gargoylesoftware.htmlunit.WebClient; // AntのBzip2タスクを使って圧縮 new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2") // HtmlUnitを使ってファイルアップロード url = "http://pukiwiki.example.com/index.php? plugin=attach&pcmd=upload&page=test" page = new WebClient().getPage(url) file = page.getElementById(_p_attach_file) file.valueAttribute = args[0]+".bz2" page.getByXPath("//input[@value=アップロード]")[0].click() 28 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  42. 42. そんな時こそGroovyですよ! @Grab(net.sourceforge.htmlunit:htmlunit:2.8) import com.gargoylesoftware.htmlunit.WebClient; // AntのBzip2タスクを使って圧縮 new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2") // HtmlUnitを使ってファイルアップロード url = "http://pukiwiki.example.com/index.php? plugin=attach&pcmd=upload&page=test" page = new WebClient().getPage(url) file = page.getElementById(_p_attach_file) file.valueAttribute = args[0]+".bz2" page.getByXPath("//input[@value=アップロード]")[0].click() Java資産の有 効活用 (HtmlUnit, Ant) 28 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  43. 43. そんな時こそGroovyですよ! @Grab(net.sourceforge.htmlunit:htmlunit:2.8) import com.gargoylesoftware.htmlunit.WebClient; // AntのBzip2タスクを使って圧縮 new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2") // HtmlUnitを使ってファイルアップロード url = "http://pukiwiki.example.com/index.php? plugin=attach&pcmd=upload&page=test" page = new WebClient().getPage(url) file = page.getElementById(_p_attach_file) file.valueAttribute = args[0]+".bz2" page.getByXPath("//input[@value=アップロード]")[0].click() Java資産の有 依存ライブ 効活用 ラリの実行時 (HtmlUnit, Ant) 28 自動取得 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  44. 44. そんな時こそGroovyですよ! @Grab(net.sourceforge.htmlunit:htmlunit:2.8) import com.gargoylesoftware.htmlunit.WebClient; // AntのBzip2タスクを使って圧縮 new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2") // HtmlUnitを使ってファイルアップロード url = "http://pukiwiki.example.com/index.php? plugin=attach&pcmd=upload&page=test" page = new WebClient().getPage(url) file = page.getElementById(_p_attach_file) file.valueAttribute = args[0]+".bz2" page.getByXPath("//input[@value=アップロード]")[0].click() Java資産の有 依存ライブ コンパイル 効活用 ラリの実行時 不要 (HtmlUnit, Ant) 28 自動取得 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  45. 45. もうちょっと詳しくー1 @Grab(net.sourceforge.htmlunit:htmlunit:2.8) import com.gargoylesoftware.htmlunit.WebClient; group指定 module指定 versoin指定 Grape Groovyスクリプト用の依存 Jarのダウンロード・管理機構 Apache Ivyベース Mavenリポジトリも扱える 29 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  46. 46. もうちょっと詳しく-2 // AntのBzip2タスクを使って圧縮 new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2") argsはコマンドライン引数を表す 暗黙引数 Antは組み込まれている 他に、JUnit, commons-logging, commons-cli, jlineなどがGroovy 配布パッケージに同梱 30 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  47. 47. ケース2 やりたいこと 指定したCSVファイルの内容を 処理してDBテーブルに投入 DBにクエリをかける 開発システムに含まれるJavaコードで処 理した結果を投入する必要があるとする 31 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  48. 48. ケース2 やりたいこと 指定したCSVファイルの内容を 処理してDBテーブルに投入 DBにクエリをかける 東京,35676000,日本 ニューヨーク,19040000,アメリカ合衆国 ブリッジポート=スタンフォード,1018000,アメリカ合衆国 フィラデルフィア,5492000,アメリカ合衆国 開発システムに含まれるJavaコードで処 理した結果を投入する必要があるとする 31 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  49. 49. ケース2 やりたいこと 指定したCSVファイルの内容を 処理してDBテーブルに投入 DBにクエリをかける 東京,35676000,日本 ニューヨーク,19040000,アメリカ合衆国 都市名, 人口, 国名 ブリッジポート=スタンフォード,1018000,アメリカ合衆国 フィラデルフィア,5492000,アメリカ合衆国 開発システムに含まれるJavaコードで処 理した結果を投入する必要があるとする 31 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  50. 50. そんな時にはGroovyですよ! @Grab(com.h2database:h2:1.2.143) @GrabConfig(systemClassLoader=true) import groovy.sql.Sql sql = Sql.newInstance("jdbc:h2:cities") sql.execute """ CREATE TABLE Cities (                   id INT IDENTITY PRIMARY KEY, name VARCHAR,                   population DECIMAL(10), country VARCHAR)""" cities = sql.dataSet("Cities") new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理   cities.add(name:f1, population:f2, country:f3) } assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == [東京, 大阪=神戸 (阪神), 京都, 名古屋, 福岡] 32 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  51. 51. そんな時にはGroovyですよ! @Grab(com.h2database:h2:1.2.143) @GrabConfig(systemClassLoader=true) import groovy.sql.Sql sql = Sql.newInstance("jdbc:h2:cities") sql.execute """ CREATE TABLE Cities (                   id INT IDENTITY PRIMARY KEY, name VARCHAR,                   population DECIMAL(10), country VARCHAR)""" cities = sql.dataSet("Cities") new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理   cities.add(name:f1, population:f2, country:f3) } assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == [東京, 大阪=神戸 (阪神), 京都, 名古屋, 福岡] H2 DBも自 動でダウン 32 Slide #ロード JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  52. 52. そんな時にはGroovyですよ! @Grab(com.h2database:h2:1.2.143) @GrabConfig(systemClassLoader=true) import groovy.sql.Sql sql = Sql.newInstance("jdbc:h2:cities") sql.execute """ CREATE TABLE Cities (                   id INT IDENTITY PRIMARY KEY, name VARCHAR,                   population DECIMAL(10), country VARCHAR)""" cities = sql.dataSet("Cities") new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理   cities.add(name:f1, population:f2, country:f3) } assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == [東京, 大阪=神戸 (阪神), 京都, 名古屋, 福岡] H2 DBも自 where句の 動でダウン 自動生成 32 Slide #ロード JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  53. 53. そんな時にはGroovyですよ! @Grab(com.h2database:h2:1.2.143) @GrabConfig(systemClassLoader=true) import groovy.sql.Sql sql = Sql.newInstance("jdbc:h2:cities") sql.execute """ CREATE TABLE Cities (                   id INT IDENTITY PRIMARY KEY, name VARCHAR,                   population DECIMAL(10), country VARCHAR)""" cities = sql.dataSet("Cities") new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理   cities.add(name:f1, population:f2, country:f3) } assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == [東京, 大阪=神戸 (阪神), 京都, 名古屋, 福岡] H2 DBも自 where句の insertも簡 動でダウン 自動生成 単 32 Slide #ロード JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  54. 54. そんな時にはGroovyですよ! @Grab(com.h2database:h2:1.2.143) Javaコード @GrabConfig(systemClassLoader=true) import groovy.sql.Sql は自由に呼 sql = Sql.newInstance("jdbc:h2:cities") べる sql.execute """ CREATE TABLE Cities (                   id INT IDENTITY PRIMARY KEY, name VARCHAR,                   population DECIMAL(10), country VARCHAR)""" cities = sql.dataSet("Cities") new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理   cities.add(name:f1, population:f2, country:f3) } assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == [東京, 大阪=神戸 (阪神), 京都, 名古屋, 福岡] H2 DBも自 where句の insertも簡 動でダウン 自動生成 単 32 Slide #ロード JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  55. 55. もうちょっと詳しく-3 @Grab(com.h2database:h2:1.2.143) @GrabConfig(systemClassLoader=true) import groovy.sql.Sql Grabは、実行ダウンロード&クラスパ スへの追加 デフォルトだとGroovyClassLoaderで 読み込まれる Class.forName()で読み込めるように、 システムクラスローダーを指定 jdbcの初期化で必要 33 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  56. 56. もうちょっと詳しく-4 cities = sql.dataSet("Cities") new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理   cities.add(name:f1, population:f2, country:f3) } DataSetは簡易なSQLインターフェー ス splitEachLineはGDKメソッド addでinsert フィールド名はMapのキーで指定 34 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  57. 57. もうちょっと詳しく-5 cities = sql.dataSet("Cities") : assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == [東京, 大阪=神戸 (阪神), 京都, 名古屋, 福岡] 上は以下と同じ cities = sql.dataSet("Cities") : assert cities.findAll{ it.country=="日本" } .findAll{ it.population>1000000 }.rows()*.name == [東京, 大阪=神戸 (阪神), 京都, 名古屋, 福岡] findAllの式は遅延評価されて最後にSelect が1回実行。 35 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  58. 58. 他の例…g100pon(1) 実用スクリプト例の集成 Groovyスクリプト100本切り JGGUG合宿2010の企画 実用スクリプト群100本をよって たかって作っちゃえ! 本成果は、11/09 JGGUG主催G* ワークショップにて報告予定(後述) http://kokucheese.com/event/index/5267/ 36 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  59. 59. g100pon(2) http://kokucheese.com/event/index/5267/ 37 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  60. 60. インストールも簡単 Slide # 38 JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  61. 61. Windows Installer 39 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  62. 62. MacOSX / Linux port install groovy apt-get install groovy やや古い(かも) 40 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  63. 63. GroovyServ http://kobo.github.com/groovyserv/ Slide # 41 JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  64. 64. GroovyServって何? Groovyスクリプト起動が爆速に! (x10∼20) Groovy処理系を常駐起動(groovyserver) Groovyスクリプト実行は、処理を groovyserverに移譲する小さなCプログ ラムで行う(groovyclient) server∼client間はsocket通信 Apache 2 Licenseでソース公開 MacOS X/Linux/Windows用バイナリ有 42 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  65. 65. 構成図 Shell Environment User Groovy Srcipt C LA SS . lin PA cm System.in TH d System.out en e v SYstem.err ar gs Ctrl-C groovyclient TCP/IP groovyserver n di st de t st dou rr JavaVM st exit status File System Authentication Cookie File Slide # JJUG CCC 2010 Fall / 2010.10.18 432010年10月19日火曜日
  66. 66. 通常のGroovy実行 User Groovy Shell Environment Srcipt C LA System.in SS . lin PA cm System.out TH d SYstem.err en e v ar gs Ctrl-C groovy n di st de t st dou JavaVM rr st exit status File System 44 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  67. 67. 起動速度向上効果(Win) 19.6 倍 groovy -e println hello world 実行時間(sec) 比率 normal groovy 3.041 1.0 Installer版groovy 1.262 2.4 groovyclient(C版) 0.155 19.6 groovyclient(Ruby版) 0.193 15.8 •Groovy 1.7.3, GroovyServ 0.4-SNAPSHOT, WinXP SP3,Core2Duo 2GHz,JDK1 Slide # •timeコマンドでreal時間を計測。10回実行した平均。 JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日 45
  68. 68. 起動速度向上効果(Mac) 35.8 倍 groovy -e println hello world 実行時間(sec) 比率 normal groovy 1.112 1.0 Mac Ports版groovy(1.7.2) 0.321 3.5 groovyclient(C版) 0.031 35.8 groovyclient(Ruby版) 0.041 27.1 •Groovy 1.7.3, GroovyServ 0.4-SNAPSHOT, MacOSX 10.6.3, MacBook Core2duo 2.53GHz, JDK1.6.0u20 46 •timeコマンドでreal時間を計測。10回実行した平均。 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  69. 69. 実行速度の向上効果(Win) Server VM の良いところ 取り利用 for (i=0; i<1000000; i++) {}; 実行時間(msec) groovy(Client VM) 593.7 groovy(Server VM) 243.8 groovyclient(Client VM) 454.6 groovyclient(Server VM) 197.0 47 •Groovy 1.7.3, GroovyServ 0.4, Windows XP SP3(cygwin 1.7.5),Core2duo 2.00GHz, JDK1.6.0u13 Slide # JJUG CCC 2010 Fall / 2010.10.18 •time コマンドで real 時間を計測。十回実行した平均。2010年10月19日火曜日
  70. 70. 応用例: scalacの高速化 Groovy限 定ではない for (i=0; i<1000000; i++) {}; 実行時間(msec) scalacとの比率 scalac 6.6 1.0 fsc 1.2 5.5 scalac/GroovyServ 1.1 6.6 fsc/GroovyServ 0.4 16.5 48 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  71. 71. Groovyスクリプト開発 Groovyは本来PerlやRubyにも対抗しうる機能を 持ったスクリプト言語 ワンライナー用オプション(-e, -p, -n, -i.bak, -l) フィルタ、パイプ コンパイル不要 でも、レスポンス悪いとやる気が出ない トライ&エラーを繰り返すため ➡ そこで、GroovyServですよ 49 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  72. 72. groovy-flymake GroovyServと組合せてgroovycをバックグ ラウンドで高速実行 http://gist.github.com/630992 50 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  73. 73. 苦労しているところ 本当は1つのJVMを、スクリプトごとに占有し ているように見せかける 並行実行は不可避(Groovyのフィルタスクリプトをpipeで繋いで実行) 異なるクラスローダで読み込ませる stdin/stdout/strerrを多重化して1ソケットで相互転送 カレントディレクトリをJNA(Java Native Access)で変更 System.exit()をトラップしてexit statusをクライアントに転送 セキュリティ対策 秘密のクッキーファイルをserver-clientで共有し、ファイルシステム のアクセス制御に基づいた保護 51 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  74. 74. 効果が薄い用途 サーバ開発 GUIアプリケーション CUIアプリでシェルのように起動して 操作するもの cronで定期的に起動するもの ➡ 起動レスポンスが重要ではないもの 52 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  75. 75. Groovy 1.8 Slide # 53 JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  76. 76. GEP3 ..メソッド呼び出しの括弧省略 Groovy 1.7.x m1(a1).m2(a2).m3(a3) Groovy 1.8.xでは以下のよ うに書ける m1 a1 m2 a2 m3 a3 54 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  77. 77. 日本語プログラミング言語Groovy(GEP3の応用例) まず 100 の 平方根 を 表示する そして 1 と 2 と 3 のうち、 奇数 それぞれに 対して { それ ->   二倍にした それ を 表示する } ついでに 1 から 100 のうち、 二の倍数.かつ(三の倍数) を 表示する 最後に 1 から 100 のうち、 二の倍数.かつ(三の倍数) それぞれに 対して { それ ->   とりあえず それ + "は6の倍数です" を 表示する } それはそれとして "以上" を 表示する http://d.hatena.ne.jp/uehaj/20100919/1284906117 10.0 18は6の倍数です 2 24は6の倍数です 6 [6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, : 78, 84, 90, 96] 6は6の倍数です 96は6の倍数です 12は6の倍数です 以上 55 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  78. 78. 日本語プログラミング言語Groovy(GEP3なしの時) まず(100).の(平方根).を(表示する) そして(1).と(2).と(3).のうち、(奇数).それぞれに(対して({それ ->   二倍にした(それ).を(表示する) })) ついでに(1).から(100).のうち、((二の倍数.かつ(三の倍数))).を(表示する) 最後に(1).から(100).のうち、(二の倍数.かつ(三の倍数)).それぞれに(対して ({ それ ->   とりあえず(それ + "は6の倍数です").を(表示する) })) それはそれとして("以上").を(表示する) 56 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  79. 79. 拡張子によってAST変換起動 例) GrUnit…拡張子*.grunitはGrUnitのテストコードとし て解釈 スクリプト用のユニットテスト記法 メソッド付属アノテーションの引数としてテストコードを書ける @Typed class Calculator { testTestsExists { private ArrayList<Double> list = [] assertTrue new File("./StdLibTest/ tests/").exists() @GrUnit({ } assertEquals(10d, calc.push(10d).list[-1]) }) testSuperclassName { Calculator push(double v) { assertEquals list.push(v) "groovy.util.GroovyTestCase", this this.class.superclass.name } } http://groovy.dzone.com/articles/grunit-groovy-way-unit-testing def finder = new FileNameFinder () http://groovy.dzone.com/articles/grunit-inline-tests-groovy 57 String [] names = finder.getFileNames Slide # ("./StdLibTest/tests/", "**/*.groovy") JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  80. 80. アノテーション引数にクロージャ指定 例)GContract…DbC(契約に よる設計)をGroovyに導入 @Invariant({ elements != null }) elements = preElements class Stack { } private List elements def boolean is_empty() { elements.isEmpty() @Ensures({ is_empty() }) } public Stack() { elements = [] @Requires({ !is_empty() }) } def last_item() { elements.last() @Requires({ preElements?.size() > } 0 }) @Ensures({ !is_empty() }) def count() { public Stack(List preElements) { elements.size() 58 http://github.com/andresteingress/gcontracts/wiki Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  81. 81. 多数のAST変換追加 @Log,@ScriptField,@Packag eScope,@Synchronized,@In heritConstructors,@Indexed Properties,@AutoClone,@Au toExternalize,@Canonical,@ EqualsAndHashCode,@ToSt ring,@TupleConstructor 59 http://canoo.com/blog/2010/09/20/log-groovys- Slide # JJUG CCC 2010 Fall / 2010.10.18 new-and-extensible-logging-conveniences/http://2010年10月19日火曜日 canoo.com/blog/2010/09/20/log-groovys-new-and-
  82. 82. @Logアノテーション @Log … オーバーヘッドなしロガーのインジェ クション(java.util.Logger) @Log4j…〃(Log4j) @Slf4j…〃(Slf4j) @Commons…〃(Commons Logger) import groovy.util.logging.Log @Log class MyClass { def invoke() { log.info(... an info message) log.fine(... a fine message) } } http://canoo.com/blog/2010/09/20/log-groovys-new-and-extensible-logging-conveniences/ 60 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  83. 83. まとめ Javaプログラマにとって Groovyは超便利 Groovは進化し続けている! 61 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  84. 84. まとめ Javaプログラマにとって Groovyは超便利 ケースによっては「使ったほうが 良い」を越え「 使うべき」レベル Groovは進化し続けている! 61 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  85. 85. まとめ Javaプログラマにとって Groovyは超便利 ケースによっては「使ったほうが 良い」を越え「 使うべき」レベル Groovは進化し続けている! 11/9のJGGUG G*ワークショップ@品川 受付 中!! http://kokucheese.com/event/index/5267/ 「Model on Grails-DCIアーキテクチャへの道すじ-」by 和智右桂 (@digitalsoul0124) 「JGGUG合宿2010報告」by 合宿参加メンバ代表 「G*なJavaOneレポート」 by 中野靖治(NTTソフトウェア), 関谷和愛 (JGGUG) 61 Slide # JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日
  86. 86. Q&A Slide # 62 JJUG CCC 2010 Fall / 2010.10.182010年10月19日火曜日

×