とことん入門 def speaker = new Cast(name:"T.Yamamoto",version:"G*-2010-04-24") 1
Grailsとことん入門JGGUG@仙台
def speaker = new Cast(name:"T.Yamamoto",version:"G*-2010-04-24")
1
自己紹介山本 剛仕事:テクニカルDTPアーキテクトtwitter: @tyamaはてな id: mottsniteブログも↑
JGGUG名古屋支部長
「Grails徹底入門」共著 9~11を執筆
2
Web開発
3
Web開発
IDEBuild Tool
Servlet
Struts
Wicket
MySQL
PostgreSQL
SpringSeaser2
DI
AJAX
Javascript
XML
Maven
Apache
ORM
Hibernate
Ant
HTML
WS
JUnit
UML
REST
TDD
MDD
Flex
4
わかりやすい。→ 必要な部分を記述結果がちゃんとだせる。→ 動作させながらコードが読みやすい事。→ メンテナンス
要点だけを書くだけでできる開発。
5
ググる。
6
The search is over.“The search is over”by Survivor (1984) / Vital Sign
I was living for a dream, loving for a moment
Taking on the world, that was just my style
Now I look into your eyes, I can see forever
The search is over, you were with me all the while
技術を追い、つかのまの楽しみ
ググり続けるのが、Web開発だと思った
でもGrailsをみつけた、これで永遠にうまくいく
探索は終わった、Grailsは、いつだってそばにあるのだ。7
Grails!?
8
GrailsとはSpring、Hibernate等をベースに、Groovy DSLを活用して、効率よくWeb開発を行える、フルスタックフレームワーク既存のJava技術の複雑な部分を隠蔽してあり、DSLで記述できる。コア技術のパズルのような断片をプラグインで連携。プラグインの活用でモジュラな開発が可能。
よくRoRと比較されるが、ちゃんと独自のアーキテクチャを持っている。RoRのGroovy実装は間違い哲学はほぼ同じ。プロジェクト発足のきっかけである。
http://grails.org
9
Grails 哲学信頼された技術上に構築Spring,Hibernate
CoC - 設定よりも規約Groovy DSL
実用的なデフォルト 実用的で直ぐに始められる仕組み。
柔軟さを犠牲にせずシンプルさをアーカイブ
10
以下が直ぐに使用できますHibernate上に構築された、簡単に利用できるO/Rマッピングレイヤ表現豊かなビューテクノロジーGroovy Server Pages (GSP)コントローラレイヤは Spring MVCを利用コマンドラインスクリプト環境にはGroovy版のAnt Gantリロード可能に設定された組込 Tomcat組込 Spring DSLによる依存注入SpringのMessageSourceで実装されたi18n対応Springフレームワークのトランザクション実装によるサービスレイヤのトランザクション
データベースView
ビルドシステム
MVC2
コンテナ
DI 国際化
トランザクション11
Grailsの概略図基本部分はJavaで実装されている。DIコンテナにSpring (3.0.0)O/RマッパーにHibernate (3.3.1)
GrailsGroovy
Spring Hibernate SiteMeshGroovy
基礎部分はJava & Groovy基礎部分はJava & Groovy基礎部分はJava & Groovy基礎部分はJava & Groovy
JVMJVM
12
Grails
外部プラグイン
Grailsの仕組み
Quartz
QuartzCore
Codec
Controlleri18n
Domain
Service UrlMapping
Filters
JMS
Taggin
Security
MyPlugin
Flex
Web
Flow
13
Grailsの歴史2005/7/3
Steven Devijver氏による最初のコミット2006/3/29 - 0.1 リリース2006/7 ~ 9 - 0.2 - 0.2.2
2006年7月にドキュメント翻訳を開始2006年10月16日 Acegi on Grails をチュートリアルに掲載
2006/11 0.3 - 0.3.1 リリース2006年12月23日 最初のAcegiプラグインを公開
2007/1 ~ 3 0.4 - 0.4.2 リリース2007/5 ~ 6 0.5 - 0.5.6 リリース
2007年7月25日第1回 grails コード・リーディング
2007/8 - 0.6リリース2007/10 - 1.0 RC1 リリース
Grails eXchange 2007 (2007/10/17 - 2007/10/19) G2One Inc. 設立
2008/2/5 - 1.0リリース2008年8月25日 Grails徹底入門 出版!2008年9月27日 Groovyインアクション出版!
2008/11~G2OneがSpringSource傘下に!1.1-beta-1 ~ 1.1-RC2
2009/2 - JGGUG発足!2009/3 - 1.1リリース2009/5 - 1.1.1リリース2009/6 ~ 12
1.2-M1 ~ 1.2 RC22009/8
SpringSouceがVMware傘下に!2009/12/23 - 1.2 リリース2010/3 - 1.3 M1 ~
14
時代での変化0.1 ~ 0.3 Antでコマンドを実装。全体的にシンプルな実装。Quartzとか付属していた。Groovyの書式も少し違った @Propertyとか書いてた。
0.4 ~ プラグイン時代到来。プラグインの導入。Gant到来。ExpandoMetaClass。Spring 2.0。Beanビルダー
0.5 URLマッピング。Base64コーデック。Ivy。
0.6 Web Flowを統合。Config DSL。Jetty 6。
15
時代での変化1.0系ORM DSL (マッピングDSL)。REST対応。JNDI対応。コンテントネゴシエーション対応。フィルタ対応。
1.1系GORMスタンドアロン版。joinTable指定。独自プラグインリポジトリ利用可能。テストプラグインを統合。Maven統合。Log4j DSL。BuildConfig。
16
時代での変化 - 1.2系デザイン変更!Spring 3.0 に更新Tomcatに変更ドキュメントエンジンGSPプリコンパイルService: メソッド単位のトランザクションDomainClass: アノテーションエンティティライブラリ依存関係管理用DSLテスト: フェーズとターゲット指定パフォーマンスの向上!
17
パフォーマンスの向上!
18
1.3リリーススケジュール3/10 1.3-M1 - リリース済み3/31 1.3-RC1 - リリース済み
4/24 - 1.3-RC2 リリース!
5/10 1.3 ?
5/26 1.3.1 ?
19
今日のテーマは、
Grails入門!
20
Grails Quick StartGrailsのインストールダウンロードhttp://grails.org/Download
任意の場所に解凍環境変数を設定 GRAILS_HOME、PATHの指定
% export GRAILS_HOME=/opt/grails-1.2.2% export PATH=$GRAILS_HOME/bin:$PATH
% grailsWelcome to Grails 1.2.2 - http://grails.org/Licensed under Apache Standard License 2.0Grails home is set to: /opt/grails-1.2.2
21
直ぐに始められる開発各種開発用コマンドターゲットプロジェクト作成、各種コード生成、アプリケーション起動等をコマンドターゲットで行う。
メモリ上で動くデータベースHSQLDBがバンドルされている。ファイル動作も可能。
サーブレットコンテナ組込Tomcatがバンドルされている。リロードできる。但し一部不安定 (ry
スカッフォルド ベースになるコードを生成 (動的 or 静的)簡単なCRUDのみで良いマスタはこれでも充分。
% grails run-app% grails test-app
22
新規プロジェクト作成
23
プロジェクト構造コマンドを実行してプロジェクト作成grails create-app myapp ; cd myapp|-- application.properties|-- grails-app| |-- conf - 設定関連| |-- controllers - コントローラ | |-- domain - ドメインモデル| |-- i18n| |-- services - サービス・ビジネスロジック| |-- taglib - タグライブラリ| |-- utils| `-- views - ビュー・レイアウト |-- lib|-- scripts - コマンドスクリプト|-- src - その他のソースファイル |-- test - テスト関連`-- web-app - Webリソース
24
ドメインクラス
25
ドメインクラスgrails create-domain-class my.pack.Bookソースが grails-app/domain に生成される。
package com.pack
class Book {
String title String author int rate String comment Date dateCreated Date lastUpdated static constraints = { }}
ここを記述。ORマッピングの設定、DBのテーブル生成は自動で行われる。
26
constraints / 制約DSL制約の定義バリデーションビューのフォーム制約を独自定義可能
グローバル定義
static constraints = { title nullable:false,blank:false author nullable:false,blank:false rate range:0..10 comment maxSize:1000 price shared:'myShared' withTax display:false }
grails.gorm.default.constraints = { '*'(nullable:true, size:1..20) myShared(nullable:true)}
27
mapping / マッピングDSLテーブル名、カラム名カスタムデータベースアイデンティティプライマリキー合成データベースインデックスHibernateユーザ定義型派生プロパティデフォルトソート順class Book implements Serializable{ static mapping = { table 'T_BOOK' id generator:'uuid.hex', params:[type:'string'] columns { comment column:'F_COMMENT',sqlType:'varchar(1000)' } withTax formula: 'price * 1.05' }
28
データ操作
29
GORMデータ操作のメソッドはドメインクラスに自動的に設定される。Book.get(1) 、Book.save()、Book.list()、Book.getAll(2,1,3)、等。※ドキュメントを参照Hibernate HQLHQLを使用できる。Account.executeQuery( "select distinct a.number from Account a where a.branch = :branch", [branch:'London'], [max:10, offset:5])Book.findAll("from Book as b where b.author=?",['森鴎外'])
30
GORM ダイナミックファインダBook.findByフィールド名(引数 , パラメータ)Book.findAllByフィールド名(引数 , パラメータ)Book.countByフィールド名(引数 , パラメータ)
LessThan、LessThanEqualsGreaterThan、GreaterThanEqualsBetween、Like、Ilike、IsNotNull、IsNullNot、NotEqual、And、Or
def results = Book.findAllByTitle("坊っちゃん", [max:10, sort:"title", order:"desc", offset:100] )
def results = Book.findAllByTitleAndAuthor( "我が輩は猫である", "夏目漱石")
31
GORMクライテリアビルダクエリーを生成するDSL※ドキュメントを参照
def c = Account.createCriteria()def results = c.list { like("holderFirstName", "Fred%") and { between("balance", 500, 1000) eq("branch", "London") } maxResults(10) order("holderLastName", "desc") }
32
データソース定義 DSLgrails-app/conf/DataSource.groovy
environments { development { dataSource { dbCreate = "update" url = "jdbc:hsqldb:file:devDB;shutdown=true" } } test { dataSource {....省略....
hibernate { cache.use_second_level_cache=true cache.use_query_cache=true cache.provider_class='net.sf.ehcache.hibernate.EhCacheProvider'}
dataSource { pooled = true driverClassName = "org.hsqldb.jdbcDriver" username = "sa" password = ""}
共通設定
hibernate定義
環境別の定義
33
アノテーションエンティティgrails-app/domains内にあるドメインクラスにGORMシンタックスの代わりにアノテーションでも定義できます
import javax.persistence.* @Entity @Table(name = "animal") class Animal { @Id @GeneratedValue int id String name @ManyToOne @JoinColumn Owner owner static constraints = { name blank:false } }
34
Webレイヤ
35
コントローラgrails create-controller my.pack.Bookソースが grails-app/controllers に生成される。
package com.pack//コントローラclass BookController { //アクション def index = { //ここにコードを書く render text:"Hello" }}
http://localhost:8080/myapp/book/index
36
アクション
def create = { def bookInstance = new Book() bookInstance.properties = params [bookInstance: bookInstance]}
def save = { def bookInstance = new Book(params) if (bookInstance.save(flush: true)) { flash.message = "フラッシュメッセージ" redirect(action: "show", id: bookInstance.id) } else { render(view: "create", model: [bookInstance: bookInstance]) }}
パラメータは全て paramsに収納される。servletContext,session,request,response等変数を参照可能。他にbeforeInterceptor、afterInterceptor等もある。
オブジェクトを返す例
ビューを指定
リダイレクト
37
スカッフォルド対象ドメインクラスのCRUDアプリケーション生成ダイナミックスカッフォルド
スタティックスカッフォルドgrails generate-all my.pack.Book必要なコントローラコートとビュー(GSP)を生成
class BookController {† †† //スカッフォルド // または、ドメイン名を指定 Ex. Book def scaffold = true }
38
生成されたコード単純な登録処理ができるプログラムドメインを元に構成されたビューCRUD操作を行うコントローラ
このコードを基本にして開発
単純なマスタであれば十分な内容
※コード参照!39
ビュー、GSP。Groovy Server PageJSPも使用可能Grailsタグリブ、JSPタグリブ
40
簡単に作れるタグリブgrails create-tag-lib com.pack.SimpleWiki
tld、web.xmlの記述は不要!class SimpleWikiTagLib { static namespace = "wiki" static returnObjectForTags = ['content'] def tagname = {attrs, body -> out<<"Hello" } def content = {attrs, body -> CmsContent.findByCode(attrs.code)?.content }}
41
URLマッピング DSLURLマッピングの指定
class UrlMappings { static mappings = { "/$controller/$action?/$id?"{ constraints { } } "/"(view:"/index") "500"(view:'/error') // 次のURLを変換 /blogname/2007/01/10/my_funky_blog_entry "/$blog/$year?/$month?/$day?/$id?"( controller:"blog", action:"show") //制約を指定 "/$blog/$year?/$month?/$day?/$id?" { controller = "blog" action = "show" constraints { year(matches:/\d{4}/) month(matches:/\d{2}/) day(matches:/\d{2}/) } }
//ワイルドガード "/images/**.jpg"(controller:"image")
42
URLマッピング DSL名前つきURLマッピング
name productDetail:"/showProduct/$productName/$flavor?"{ controller = "product" action = "show"}
<link:productDetail productName="licorice" flavor="strawberry"> Strawberry Licorice </link:productDetail>
43
REST対応HTTPメソッドへマッピング対応送信データも自動でバインドされる。static mappings = { "/product/$id"(controller:"product"){ action = [GET:"show", PUT:"update", DELETE:"delete", POST:"save"] } }
44
コンテントネゴシエーションリスエスと要求された、コンテントタイプに合わせた結果を返す事できる。
withFormat DSLimport grails.converters.*class BookController {
def list = { def books = Book.list() withFormat { html bookList:books json { render books as JSON } xml { render books as XML } } } }
/book/list でアクセス
/book/list.json でアクセス
/book/list.xml でアクセス
45
その他。Webレイヤ他にもWebレイヤには機能豊富Sitemesh レイアウト・コンテンツブロック
Webフローフィルター DSLAJAX Ajaxライブラリ参照を抽象化。Taglibが提供されている
46
ビジネス
ロジック
47
サービスビジネスロジックを記述。Springビーンのオートワイヤで自動解決。
class BookStoreService { boolean transactional = true def allList(params) { return Book.list(params) }}
class BookController {
def bookStoreService def list = { [bookInstanceList:bookStoreService.allList(params), bookInstanceTotal: Book.count()] }
サービスクラス
これを記述するだけでオートワイヤ。
48
テスト!
49
TestingGrailsにはテスト環境も含まれている。Webテスト、BDD等のテストには、プラグインが存在する。
テストの種類と実行方法ユニットテスト Unit Testinggrails test-app unit:
統合テスト Integration Testinggrails test-app integration:
機能テスト Functional Testinggrails test-app functional:
50
ユニットテスト Unit TestingGrailsUnitTestCaseGroovyTestCaseのサブクラスMockが提供されている。mockFor(class, loose = false)
mockDomain(class, testInstances = )
mockForConstraintsTests(class, testInstances = )
mockLogging(class, enableDebug = false)
mockController(class)
mockTagLib(class)
def testInstances=[]mockDomain(Song, testInstances)assertEquals(0, Song.count())new Song(name:"Supper's Ready").save()assertEquals(1, Song.count())
51
統合テスト Integration Testing実行環境にフルアクセスできるテストデータベースも動作。テスト終了後に削除される。リクエスト等のMockも提供されている。MockHttpServletRequest、MockHttpServletResponseMockHttpSession
class FooController { def someRedirect = { redirect(action:"bar") } def text = { render "bar" }}
class FooControllerTests extends GrailsUnitTestCase { void testText(){ def fc = new FooController() fc.text() assertEquals "bar", fc.response.contentAsString } void testSomeRedirect() { def fc = new FooController() fc.someRedirect() assertEquals "/foo/bar", fc.response.redirectedUrl }
52
機能テスト Functional TestingSelenium pluginWebtest Plugin
53
BDDSpock プラグインEasyB プラグイン
54
GrailsはSpring
55
Grails is SpringGrailsは形を変えたSpring-MVC既存のSpring Beanを利用したい場合などでは特に力を発揮する
既存のSpring対応のライブラリが大活躍!
BeanビルダーSpringビーンを定義するDSLGrailsにSpringビーンを注入する!
56
Springビーンビルダー実装クラス:grails.spring.BeanBuilderApplicationContextを構築するためのDSL。直感的でわかりやすくSpringビーンを定義できる。Groovyプログラムを使用して動的にビーンを定義Grailsアプリケーション以外でも使用できるように設計されています。
57
Springビーンビルダーgrails-app/conf/spring/resources.groovy
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="127.0.0.1"/> </bean> <bean id="mailMessageMe" class="org.springframework.mail.SimpleMailMessage"> <property name="from" value="[email protected]"/> </bean><bean id="mailMessageYou" class="org.springframework.mail.SimpleMailMessage"> <property name="from" value="[email protected]"/> </bean>
mailSender(org.springframework.mail.javamail.JavaMailSenderImpl) { host = '127.0.0.1' }def map = ["Me":"[email protected]","You":"[email protected]"]map.each{k,v-> "mailMessage${k}"(org.springframework.mail.SimpleMailMessage) { from = v }}
ダイナミックにしてみたり!58
BeanBuiler:単独での使い方Grailsアプリケーション以外でも使用できるように設計されているので。
import org.springframework.context.ApplicationContext import grails.spring.BeanBuilder // BeanBuilderの生成
def builder = new BeanBuilder() builder.beans { // ここに定義を書く!} // ApplicationContextの生成
ApplicationContext ctx = builder.createApplicationContext() 59
Config 設定
60
設定などgrails-app/conf 階層Config.groovy 各種設定をDSLで定義log4j DSL等
BuildConfig.groovyビルド情報:作業ディレクトリ指定など̃/.grails/settings.groovy
log4j = { appenders { console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n') } error 'org.codehaus.groovy.grails.web.servlet'}
61
プラグイン!
62
プラグイン公式リポジトリプラグイン開発インラインプラグイン モジュラ開発チーム開発プラグインリポジトリSVN、Mavenリポジトリ
63
プラグインって?Grailsその物がプラグイン簡単に作れる!簡単に配布できる!Grailsアプリケーションを開発できれば、誰でもプラグイン開発者違いは、*GrailsPlugin.groovy ファイル(プラグインディスクリプタファイル)
64
セントラルリポジトリGrails 本家プラグインリポジトリ現在、350件ほどのプラグインが存在する。※もちろんすんなり動かないのも含む
Codehaus登録して、GrailsのコミッタにOKもらえば誰でもプラグインを公開できる。
公式に公開しなくてもプラグインは作れます。そして使えます。
grails install-plugin プラグイン名 or ファイル名
65
プラグイン開発grails create-plugin mytagscd mytags.......タグリブとか作る.......grails package-plugin
以上で grails-mytags-0.1.zip ができあがる。
後は他のプロジェクトにインストールgrails install-plugin ../mytags/grails-mytags-0.1.zip
66
プラグイン開発・難易度難易度[低] 通常のGrailsアプリケーション開発ができれば簡単に開発できる内容 JavaScriptファイル、CSSファイルなどを提供する 基本アーティファクトなどを提供する 難易度[中] Springフレームワークの知識、サーブレットなどの知識が必要 Springフレームワークを用いた機能拡張 web.xml操作 難易度[高] ダイナミックメソッド追加→GroovyのExpandoの知識が必要 Gantスクリプトを追加→GantおよびAntの知識が必要 独自アーティファクトの追加
67
インラインプラグインプラグインをインストールしないで使う事ができる。grails-app/conf/BuildConfig.groovyにプラグインの位置を記述。インラインで分ける事により、将来的にプラグインとして再利用。モジュラ開発に最適。
grails.plugin.location."auth-domains"="/path/to/modules/auth-domains"
grails.plugin.location."business-domains"="/path/to/modules/business-domains"
grails.plugin.location."common-tags"="/path/to/commons/common-tags"
grails.plugin.location."shop-cart"="/path/to/functionals/shop-cart"
68
プラグインリポジトリSVNベースのプラグインリポジトリgrails release-plugin -repository=ncリポジトリの指定は、BuildConfig.groovyに設定 (次ページで説明)
Mavenリポジトリ(1.3~)maven-publisherプラグインを使用する
%grails maven-install " ローカルキャッシュにインストール%grails maven-deploy" リモートリポジトリにデプロイ
69
プラグインリポジトリ設定方法USER_HOME/.grails/settings.groovy 又は、grails-app/conf/BuildConfig.groovyに情報定義。例えば、チームのプラグインリポジトリに使用するSVNのUrlが、"http://127.0.0.1/gp"だとしたら
grails.plugin.repos.discovery.local="http://127.0.0.1/gp" grails.plugin.repos.distribution.local="http://127.0.0.1/gp"
grails.plugin.repos.discovery.リポジトリ名称="リポジトリへのHttpベースのURL"
grails.plugin.repos.distribution.リポジトリ名称="リポジトリへのHttpベースのURL"
70
他動的プラグイン自動解決他動的プラグイン自動解決application.properties に記述されているプラグインは自動でインストールされる。公式プラグイン以外を利用する場合は、BuildConfig.groovyにリポジトリを指定
app.version=0.1plugins.acegi=0.5.7app.servlet.version=2.4app.grails.version=1.3.RC2plugins.hibernate=1.3.RC2app.name=relationsample plugins.
プラグイン名=バージョン
71
プラグイン活用例Grails公式プラグイン
チーム用プラグインリポジトリ
メインプロジェクト
使用するプラグインの情報を
定義 プラグインA (プロジェクトの一部の機能)
グラフ機能プラグイン (今後も再利用できそうな機能)
ユーザ認証プラグイン (公式のプラグイン+カスタマイズ)
プラグインB (プロジェクトの一部の機能)
チーム用リポジトリ
独自プラグインリポジトリで管理
チームメンバー
チェックアウト
プラグイン自動解決
プラグイン自動解決
プラグイン
メタ情報で自動管理
プラグイン
72
Ivy DSL
73
ライブラリ依存性管理Ivy DSL
grails install-dependencyコマンドローカルキャッシュにライブラリをインストールするコマンド
% grails install-dependency net.homeip.yusuke:twitter4j:2.0.9
grails.project.dependency.resolution = { ... repositories { //リポジトリ定義 mavenRepo "http://repository.codehaus.org" } dependencies { runtime 'net.homeip.yusuke:twitter4j:2.0.9' } ...} ローカルキャッシュ ls -al ~/.ivy2/cache
74
デプロイ
75
デプロイgrails warwarが生成される。
Tomcatへのデプロイgrails tomcat deploy Config.groovyに以下の定義が必要
tomcat.deploy.username="manager" tomcat.deploy.password="secret" tomcat.deploy.url="http://myserver.com/manager"
76
クラウドへデプロイPaaSサービスStaxMorph AppSpaceCloud Foundry (EC2)
Google App EngineAppEngine プラグインGORM-JPA プラグイン
※別スライド 参照。 77
Google AppEngineおお! 1.3 RC2 & gae plugin 0.8.10
試した。動いた!URLマッピング辺りがあやしい! appenders{null name:'stacktrace'}必須。
78
最新情報!
79
Grails 1.3 最新情報※別スライド参照
80
見出しだけ日本語Grailsドキュメント公開
公式サイトhttp://grails.org/doc/latest
日本語 Japanese doc.http://grails.jp/doc/latest
81
まとめ
82
馬上少年過
世平白髪多
残躯天赦所
伊達政宗公の漢詩 不
楽是如何
【 意味】
大変な思いをして開発したのも遠い昔世の中には便利なフレームワークも増えた残り少ない開発期間Grailsを活用しなくてなんとするかぁ~!!!
83
Thank you.
日本Grails/Groovyユーザーグループ
http://www.jggug.org/84