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