GrailsでSpringをGroovyにしよう!
-
Upload
tsuyoshi-yamamoto -
Category
Technology
-
view
1.591 -
download
0
description
Transcript of GrailsでSpringをGroovyにしよう!
GrailsでSpringをGroovyにしよう!
JSUG+JGGUG合同勉強会
2009年6月24日
def speaker = new Cast(name:”T.Yamamoto”,version:”JSG2UG-2009-06-24”)
自己紹介名前:山本 剛 (やまもとつよし)所属:株式会社ニューキャスト組版屋、印刷系Webアプリ開発など。案件は90%Grailsを使ってます。
JGGUG(じぇいがぐ) 名古屋支部 担当です。「Grails徹底入門」9-11章を書きました。 Grails Acegi Plugin作った人。
ブログhttp://d.hatena.ne.jp/mottsnite/
おさらい
Grailsとは?よく聞く説明「Groovyで実装されたRuby on Rails」!? Java+Groovyで実装された、CoC、DRYの概念を取り入れた(‘RoR’にインスパイアされた)、Webアプリケーション開発環境。基礎はSpring,Hibernate等を使用している。
そして、それらをシンプルに活用できる環境。
Grails, the Platform (DGG2引用)
合ってるようで間違い
Grailsの構成図GrailsGrailsGrails Groovy
Spring Hibernate SiteMeshGroovy
基礎部分はJava(+Groovy)基礎部分はJava(+Groovy)基礎部分はJava(+Groovy)基礎部分はJava(+Groovy)JVMJVMJVMJVM
Hibernate:ORマッピング Spring: DIコンテナ・多機能なラッパーフレームワーク SiteMesh:レイアウトフレームワーク Jetty: サーブレットコンテナ HSQLDB:ピュアJavaなデータベース
2.5.6
3.3.1 2.4
1.5+
1.6.3
デモgrails create-app democd demograils create-domain-class Bookgrails create-controller Bookgrails run-app
今日はこれやりません
本日のテーマ!
GrailsとSpringの関係~BeanBuilderへたどりつくまで。BeanBuilder(ビーンビルダ)解説!←本日のメイン
GrailsでSpringをGroovyに使う!GrailsにSpringビーンを追加してみる。
SpringでGrailsを使ってGroovyに!applicationContext.groovy !?!? (サンプル解説)GORMをSpringで使う!(サンプル解説)
「GrailsでSpringをGroovyにしよう!」
BeanBuilderって?いろいろ話す前に、まずはザックリこんな感じ。
<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 }}
ダイナミックにしてみたり!
何故,
BeanBuilder
!?
GrailsとSpringの関係今さら言うまでもなく、Grailsの中はSpringがいっぱい!基礎をSpringフレームワークが支えています。Grailsには、Springビーンを簡単に追加する仕組みがあります。 → 「GrailsでSpringをGroovyに使う!」で話します。
先ずは関係を知るために簡単な所から見てみましょう。PROJECT_HOME/src/templates/war/web.xmlPROJECT_HOME/web-app/WEB-INF/applicationContext.xml 手 順
grails create-app democd demograils install-template
src/templates/war/web.xml<web-app version="2.4"... <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param>... <servlet> <servlet-name>grails</servlet-name> <servlet-class>org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet>...
applicationContext!
DispatcherServlet!
web-app/WEB-INF/applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"...> <bean id="grailsApplication" class="org.codehaus.groovy.grails.commons.GrailsApplicationFactoryBean"> <description>Grails application factory bean</description> <property name="grailsDescriptor" value="/WEB-INF/grails.xml" /> <property name="grailsResourceLoader" ref="grailsResourceLoader" /> </bean>...</beans>
applicationContext.xmlの中身grailsApplication - GrailsApplicationFactoryBeanpluginManager - GrailsPluginManagerFactoryBeanpluginMetaManager - DefaultPluginMetaManagergrailsConfigurator - GrailsRuntimeConfiguratorgrailsResourceLoader - GrailsResourceLoaderFactoryBeangrailsResourceHolder - GrailsResourceHoldercharacterEncodingFilter - CharacterEncodingFilter
その中で、最も重要なのは、
grailsApplication
GrailsApplicationFactoryBean
GrailsApplicationFactoryBeanGrailsの最初のバージョンからあります。GroovyファイルからGrailsアプリケーション用オブジェクトを生成するファクトリビーン。リソースが読みこまれ、ここから様々なGrailsオブジェクトが出荷されます。
grailsApplicationgrails-app以下のgroovyファイル達grails-app/domin/Book.groovy Author.groovygrails-app/service/SomeService.groovy HogeService.groovy
リソースロード
ここから様々な情報を読みこんで、Grailsで使うビーンの生成をしています。
grailsApplicationとビーン生成の関係この関係を調べることでBeanBuilderって何か解るかも!いろいろソースを探ってたらBeanBuilder誕生の理由?が解った気がしたから・・・但し、推測
Grailsの裏側解説(簡易版)
groovygroovygroovygroovy
groovygroovygroovygroovy
grails-appの中
grails起動
リソースロード
grailsApplicationに収集
ルールに基づいて情報を読みこむ
コンテキスト完成
ビーンが生成される
歴史をさかのぼると、v0.2時代はGrailsのGroovy(CoC)な部分は複雑だった。
Grailsの裏側解説(簡易版)
GrailsPlugin
grailsApplicationgrails-app以下のgroovyファイル達grails-app/domin/Book.groovy Author.groovygrails-app/service/SomeService.groovy HogeService.groovy
リソースロード
・ロードされたリソースをgrailsApplicationから用途別に収集・クラス名とかプロパティ内容を元に ファクトリビーン(RootBeanDefinition)や、他のビーンとの関連等を生成・生成されたビーン等をapplicationContextに登録する。 ※"applicationContext.registerBeanDefinition()"する
少し歴史など。applicationContext.xmlの内容ヒストリー
grailsApplicationgrailsResourceHoldercharacterEncodingFilter
0.1
pluginMetaManager
0.6 -> 現在
grailsResourceLoader
domainInjector
0.3
injectionOperationpluginManager
0.4 0.4.2-0.5.6
grailsConfigurator
BeanBuilder実装ユーザ拡張可能な、Plugin実装
内部的なPlugin実装
0.2
Grailsでのビーン生成と、BeanBuilder誕生までCoCを実現するために。0.1時代。- SpringConfigクラスで全てを行っていた。0.2-0.3.1時代。プラグインの原型が登場。この時代は、インターフェイスGrailsPluginを実装したクラスのdoWithGenericApplicationContext()の中で、RootBeanDefinitionをGenericApplicationContextにregisterBeanDefinition()してた。(大変そう!)0.4以降。ユーザ拡張可能なプラグインの実装。この時に、ビーンの追加も容易になるようにBeanBuilderってのが実装された。
簡単にまとめるとGrailsに柔軟な拡張性を実装 0.4からのGrailsプラグイン深い所:ビーン生成などは、0.2からの仕組みだと敷居が高くて大変だね!ぢゃあ、ビーンも解りやすくぐるーびぃーに!DSLに!BeanBuilder誕生!
BeanBuilder実装クラス:grails.spring.BeanBuilder
ApplicationContextを構築するためのDSL(Domain Specific Language)です。直感的でわかりやすくSpringビーンを定義できます。Groovyプログラムを使用して、動的にビーンを定義できます。Grailsアプリケーション以外でも使用できるように設計されています。
BeanBuiler:単独での使い方Grailsアプリケーション以外でも使用できるように設計されているので。
import org.springframework.context.ApplicationContext import grails.spring.BeanBuilder // BeanBuilderの生成
def builder = new BeanBuilder() builder.beans { // ここに定義を書く!} // ApplicationContextの生成
ApplicationContext ctx = builder.createApplicationContext()
BeanBuiler基本書式基本!
someBean(MySomeBean,"引数1",2 ,[3]){bean-> bean.singleton = false bean.factoryMethod = "getInstance" fieldOne = "JGGUG" anotherBean = ref("anotherBean",true)}
idクラス名 引数達
ビーン構成用インスタンス AbstractBeanDefinition
<bean . . . factoryMethod="getInstance"/> などのアトリビュートが定義
プロパティ定義
ビーン参照
クロージャの最初の引数は AbstractBeanDefinition
org.springframework.beans.factory.support.
AbstractBeanDefinition → ビーン構成用インスタンス <bean>のdestroy-method等のアトリビュート設定方法“-”をCamelCaseにする。Ex. destroy-method → destroyMethod
■Factoryメソッドの使用例
withFactoryMethod(BeanWithFactoryMethod){bean-> bean.factoryMethod = "getInstance" bean.scope = "prototype" person = "tyama"}
■Bean定義の戻り値はビーン構成用インスタンスなので、戻り値の変数に指定もできます。def somebean = withFactoryMethod(BeanWithFactoryMethod){ person = "tyama"}somebean.factoryMethod = "getInstance"somebean.scope = "prototype"
ビーン構成用インスタンス AbstractBeanDefinition
ビーン構成用インスタンス AbstractBeanDefinition
ファクトリビーン
ビーンスコープビーンスコープ - 基本は全てシングルトンです。prototypeflashflowconversationsessionsingleton
withFactoryMethod(BeanWithFactoryMethod){bean-> bean.factoryMethod = "getInstance" bean.scope = "prototype" person = "tyama"}
スコープ
ビーンの参照ApplicationContextで管理されている他のビーンへの参照xml定義での <ref bean="anotherBean"/>
ref("anotherBean") と書きます。
ref("anotherBean",true) と指定すると
親ApplicationContextのみを参照します。
■ビーンの参照beanA(BeanA){ name="bean a"}
■ref("...")で指定するbeanB(BeanB){ name="bean b" parent=ref("beanA")}
■ref("...")は、省略可能beanBB(BeanB){ name="bean b" parent=beanA}
■ref("...",true)第2引数にtrueを指定して親ApplicationContext内のみを参照beanBParent(BeanB){ name="bean b" parent= ref("beanAParent",true)}
Anonymous Inner Beans匿名インナービーン
exampleInner(ExampleBean2){ bean = {ExampleBean b -> name="My First Inner Bean" num=24 }}
■Factory Beanを使った例exampleInnerBeanFactory(ExapleBeanFactory)exampleInnerUntyped(ExampleBean2){ bean = {bean-> bean.factoryBean = "exampleInnerBeanFactory" bean.factoryMethod = "newInstance" name="example BeanFactory" num=24 }}
Beanの継承、抽象ビーン<bean id="exampleAbstractBeanNoClass" abstract="true"> <property name="name" value="abstract bean"/> <property name="num" value="20"/></bean><bean id="exampleNoCls" parent="exampleAbstractBeanNoClass" class="ExampleBean"> <property name="name" value="My First Bean"/></bean>
<bean id="exampleAbstractBeanWiCn" abstract="true" class="ExampleBean"> <property name="name" value="abstract bean"/> <property name="num" value="23"/></bean><bean id="exampleWiCn" parent="exampleAbstractBeanWiCn"> <property name="name" value="My First Bean"/></bean>
Beanの継承、抽象ビーンexampleAbstractBeanNoClass { name="abstract bean" num = 20}
(SomeClass)クラスの指定を無くす
exampleNoCls(ExampleBean){ bean -> bean.parent = exampleAbstractBeanNoClass name = "My First Bean"} bean.parentに指定する。
exampleAbstractBeanWiCn(ExampleBean){ bean -> bean.'abstract' = true name="abstract bean" num = 23}
bean.‘abstract’=trueを指定
動かしてみるGrails徹底入門10章を参考に!Gantは1.6.1 Binary, standalone installationを使用執筆時と一部仕様が変わっているので修正。build.gantの中の Ant → ant に変更。libの中身を変更commons-logging-1.1.jargrails-bootstrap-1.1.1.jargrails-spring-1.1.1.jargroovy-all-1.6.3.jarspring-2.5.6.jar デモ
BeanBuilderの
利用方法はおさえたので
GrailsでSpringビーンをGroovyに使う!
GrailsでSpringビーンをGroovyに使う!GrailsアプリケーションにSpringビーンを追加。正しい方法は3つresources.xmlに記述。resources.groovyにBeanBuilderで記述。Grailsプラグインにしてしまう。
Grailsのプロジェクト内で定義されたビーンを使うにはdef someBean と宣言するだけでOK.
resources.xmlgrails-app/conf/spring/resources.xmlにxmlでのビーン定義をそのまま書く。
デモ
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans> <bean id="exampleBean" class="bean.ExampleBean"> <constructor-arg value="hello exampleBean"/> <property name="name" value="My First Bean" /> <property name="num" value="19" /> </bean></beans>
package bean
class ExampleBean { def name def num ExampleBean(){} ExampleBean(String arg){println arg} String toString(){ "ExamplBean: $name $num" }}
resources.groovygrails-app/conf/spring/resources.groovyにBeanBuilderで記述。
デモ
package bean
class ExampleBean { def name def num ExampleBean(){} ExampleBean(String arg){println arg} String toString(){ "ExamplBean: $name $num" }}
beans = { exampleBean(ExampleBean,"hello exampleBean"){ name = "My First Bean" num = 19 } }
実装変更に使えるgrails-app/conf/spring/resources.groovy( or xml)で同名称(id)のビーンが追加された場合は、内容が上書きされます。例えば、既に定義されている “dataSource”ビーンの実装クラスを変えて定義し直したい場合。
dataSource(com.mchange.v2.c3p0.ComboPooledDataSource) { bean -> bean.destroyMethod = "close" driverClass = "org.hsqldb.jdbcDriver" jdbcUrl="jdbc:hsqldb:hsql://localhost:9001" user="sa" password=""}
定義したIDが同名のビーン内容が上書きされる
ここを変えてみた
GrailsプラグインでdoWithSpring再利用しちゃいましょう!
class JggugBeanGrailsPlugin { // the plugin version def version = "0.1".... def doWithSpring = { // TODO Implement runtime spring config (optional) exampleBean3(bean.ExamplePluginBean,"hello plugin exampleBean3"){ name = "My 3rd Bean" num = 100 } }....}
プラグインの細かい話はJGGUGの勉強会「G*」で!
SpringでGrailsを
使ってGroovyに!
applicationContext.groovy!?Grailsのソースリポジトリにコッソリ!?置いてある。grails-sample/standalone-beanbuilder 若干古いです。内容<context-param>のcontextConfigLocationに/WEB-INF/applicationContext.groovyを指定<context-param>のcontextClassにGrailsWebApplicationContextを指定あとはビーンビルダで定義するだけ。
ソースの中を見てみましょう
GrailsのGORMを使う!スタンドアロンでGORMが使用可能!Spring MVCでのサンプル、GRAILS_HOME/samples/petclinic-mvcを参照applicationContext.xmlにデータソースと、<gorm:sessionFactory/>の定義。
<gorm:sessionFactory base-package="org.grails.samples" data-source-ref="dataSource" message-source-ref="messageSource"><property name="hibernateProperties"><util:map><entry key="hibernate.hbm2ddl.auto" value="update"/>
</util:map></property>
</gorm:sessionFactory>
import
grail
s.pers
istenc
e.Enti
ty
@Entit
y
class
Person
{
String
name
...
}
Person
.groov
y
まとめAnnotationがあるぢゃないか!? (これは言わない!)BeanBuilderを使うとGrails → Springビーン利用は簡単ですよ。そして柔軟(ダイナミックだし)なので、いろいろSpringビーンの活用幅がひろがりそう。単独で動作するので、単純なビーンのテストとかに使える?
Grailsから派生したGORMSpring → Grailsのコンポーネント利用Springの内部もぐるーびぃーになる。みなさんの実運用でどうなのか解りませんが・・Grailsでドメイン設計して、ほぼ,そのままSpringで利用可能?
将来!?次期バージョンでどうなる?現在のGrailsでは、Spring 2.5.6なので、3.0に更新したらどうなっていくのか!?Grails-1.2から、Spring-3になるそうです。Graemeさんがtwitterで、いろいろつぶやいてました。
Q&Aお手柔らかに、お願いします。(T.T)濃い話しはNGで・・・
参考資料Grails徹底入門The Definitive Guide to Grails 2ndGrails-0.1~1.2のソースコード
Thank You!合同勉強会、またやりたいですね。JSUGの勉強会も参加してみたいです!
みなさまの、
JGGUGへの参加
お待ちしています。