Groovy and Grails: Changing the Landscape of Java™ Platform, Enterprise Edition (Java EE Platform) Patterns Graeme Rocher, CTO – G2One Inc Guillaume LaForge, VP of Engineering – G2One Inc TS-5793
Learn how Groovy through its powerful meta-programming techniques is enabling frameworks like Grails to change the way we think about patterns on the Java™ platform
Your Speakers Graeme Rocher Project Lead of Grails CTO of G2One Inc – The Groovy/Grails Company Member of JSR-241 (Java Specification Request) Expert Group Author of “The Definitive Guide to Grails”
Your Speakers Guillaume LaForge Project Lead of Groovy VP of Technology at G2One Inc – The Groovy/Grails Company Lead of JSR-241 Expert Group Co-Author of “Groovy in Action”
Agenda Introduction and Why Groovy? What makes a dynamic language? Groovy’s Meta Object Protocol Domain Specific Languages Meta Programming Patterns Applying Meta Programming techniques to Java EE platform patterns The DAO The Service Locator
What is Groovy? Groovy is a dynamic language for the Java Virtual Machine (JVM) Takes inspiration from Smalltalk, Python and Ruby Integrates with the Java platform language and platform at every level
What is Grails? A Web platform that implements the full stack from build system down to ORM layer Leverages existing technologies like Spring, Hibernate, Quartz etc. avoiding re-inventing the wheel Features and extensible plug-in system and an environment for runtime configuration built on Spring
Getting Started Download from http://grails.org/Download Extract zip to disk Set GRAILS_HOME variable to location on disk Add $GRAILS_HOME/bin to your environment variables Download from http://groovy. codehaus .org Extract zip to disk Set GROOVY_HOME variable to location on disk Add $GROOVY_HOME/bin to your environment variables
Why is Groovy dynamic? A lot of confusion exists on what a factors make a language dynamic Dynamic vs Static Typing Strong vs. Weak Typing Meta programming Let’s clarify these!
Dynamic/Static/Weak/Strong
The Meta Object Protocol (MOP) There are many dynamic languages VB, Python, Ruby, Groovy, JavaScript™ technology But, only a few have a MOP Groovy Ruby LISP Smalltalk A MOP makes the semantics of a program extensible
Groovy’s MOP Every class has a MetaClass, which can be obtained with: The MetaClass defines the behaviour of the object and can be inspected: def obj = "Hello World!" def metaClass = obj.metaClass obj. metaClass.methods .each { println it.name } Access the metaClass property The methods collection returns a list of MetaMethod instances
Using respondsTo and hasProperty Need to find out whether an object implements a method? Use respondsTo : Need to find out if an object has a property? Use hasProperty : def foo = "Hello World!" if(foo. respondsTo(foo, "toUpperCase")) println foo.toUpperCase() if(foo.metaClass. hasProperty( "bytes") ) println foo.bytes.encodeAsBase64()
Useful API References MetaObjectProtocol http://groovy. codehaus . org/api/groovy/lang/MetaObjectProtocol .html MetaMethod http://groovy. codehaus . org/api/groovy/lang/MetaMethod .html MetaProperty http://groovy. codehaus . org/api/groovy/lang/MetaProperty .html
Adding Methods at Runtime Instance methods can be added using the MetaClass: As can properties using JavaBeans™ architecture conventions: class Dog {} Dog. metaClass.bark = { "woof!" } println new Dog().bark() class Dog {} Dog. metaClass.getBreed = { "Bulldog" } println new Dog().breed Assigning a block of code to a property of the MetaClass creates a method! Properties need to follow JavaBeans naming coventions
Static Methods and Constructors Static methods can be added using the static qualifier: Constructors can be added using a special constructor property: Dog.metaClass .static.bark = {new Dog() } println Dog.create().bark() Dog. metaClass .constructor = {String s -> new Dog(name:s) } println new Dog( "Fred" ).name Prefix the method name with the static qualifier to make a static method Careful of Stack overflows when overriding constructors!
Meta-Programming Hooks invokeMethod , methodMissing , get/setProperty , propertyMissing : Dog.metaClass . methodMissing = { String name, args-> println "Dogs don’t $name!" } def d = new Dog() d.quack() d.fly() "Dogs don’t quack!" "Dogs don’t fly!" No exception is thrown, the call is intercepted and the messages printed to system out Method missing allows you to intercept failed method dispatch
Meta-Programming Patterns Intercept , Cache , Invoke Enables code synthesis Basic Usage: Intercept method Dynamically create new method Cache new method Invoke new method First call takes performance hit, next call faster Dog.metaClass . methodMissing = {String name, args-> def cached = {Object[] a -> println ”Dogs don’t $name!" } Dog.metaClass . "$name" = cached cached. call(args) } Intercept – implement methodMissing Cache – Dynamically register new method Invoke – call new behaviour
Re-inventing Patterns with the MOP The Data Access Object The Service Locator
The Data Access Object (DAO) Basic Steps Define an interface Define one or many implementations Inject dependencies into implementations Dependency Injection (IoC) Factories http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
Implications of DAO Class explosion Promotes anemic domain model Configuration, configuration, configuration Violates DRY
Creating Dynamic SQL Finders Meta Magic with Groovy
Dynamic SQL Finders Example Book.metaClass. static . methodMissing = { String name, args -> if (name.startsWith(&quot;findBy&quot;) && args) { def prop = name[6..-1] prop= prop[0].toLowerCase() + prop[1..-1] def callable = { Object[] varArgs -> def results = [] def sql = Sql.newInstance( url, user, pass, driver) sql.eachRow( &quot;&quot;&quot;select * from ${Book.name} where $prop=?&quot;&quot;&quot; , [varArgs[0]]) { results << new Book(title:it.title, author:it.author) } return results } Book.metaClass. &quot;$name&quot; = callable return callable. call(args) } } Intercept Cache Invoke
Real Life Example: GORM in Grails class Album { String title String artist Date releaseDate static hasMany = [songs:Song] } class Song { String title Double duration } table - album table - song GORM classes, also known as domain classes, go in the domain directory id title artist release_date id title duration album_id
GORM in Action Querying and Persistence with GORM
Dynamic Finders & Criteria def albums = Album. list () def recentAlbums = Album. findAllByReleaseDateGreaterThan (new Date()-7) def albumsStartingWithA = Album. findAllByTitleLike ( &quot;A%&quot;) def albumsWithSongsAboutSummer = Album. withCriteria { songs { like(&quot;title&quot;, &quot;%Summmer%&quot;) } } List all records Form method expressions Use “like” queries Construct criteria on the fly to query associations
GORM Features Dynamic finder and persistence methods Criteria with a Groovy builder Object-relational Mapping DSL Caching Legacy mapping Locking strategy (optimistic/pessimistic) Built on Hibernate +
MOP == Goodbye to the DAO Repetitive, boilerplate DAO logic gone (DRY) Logic exists where it belongs - in the domain (DDD) No direct references to third part dependencies!
The Service Locator / IoC Pattern of many names Dependency Injection Service Locator Inversion of Control Abstracts dependency look-up code http://java.sun.com/blueprints/corej2eepatterns/Patterns/ServiceLocator.html
Implications of Service Locator Requires factory classes Class explosion Promotes anemic domain model Configuration, configuration, configuration
Automatic Dependency Injection Automatic Dependency Injection with Spring & Grails via Meta-programming
Real Life Example: Spring & Grails class Book { PurchasingService purchasingService Transaction buyBook(User u) { purchasingService.buyBook(this, u) } } Book. metaClass.constructor = {-> def obj = BeanUtils.instantiateClass(Book) applicationContext .getAutowireCapableBeanFactory() . autowireBeanProperties( obj, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false) return obj } Book domain class requires reference to PurchasingService Overriding default constructor for class Autowire dependencies into object from Spring at construction time
Real Life Example: Spring & Grails Advantages of Meta way Promotes Domain Driven Design (DDD) No configuration DRY def user = User.get(1) def book = new Book() book.buyBook(user) All dependencies in place even when the new operator is used!
Summary Meta-programming represents a new way to think about problems Common patterns like the DAO and Service Locator are present because of limitations in Java platform Groovy and Grails open doors to declarative programmings, DSLs and Domain Driven Design (DDD)
For More Information Grails TS-6457 - Choosing Your Java Technology-Based Web Framework: A Comparison http://grails.org Groovy Sessions, Panel Discussions, BOFs: PAN-5435, TS-5815, TS-6050, TS-5274, BOF-5102, BOF-5110, TS-5693, BOF-5101 http://groovy. codehaus .org
Groovy and Grails: Changing the Landscape of Java™ Platform, Enterprise Edition (Java EE Platform) Patterns Graeme Rocher Guillaume LaForge TS-5793

JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE patterns

  • 1.
    Groovy and Grails:Changing the Landscape of Java™ Platform, Enterprise Edition (Java EE Platform) Patterns Graeme Rocher, CTO – G2One Inc Guillaume LaForge, VP of Engineering – G2One Inc TS-5793
  • 2.
    Learn how Groovythrough its powerful meta-programming techniques is enabling frameworks like Grails to change the way we think about patterns on the Java™ platform
  • 3.
    Your Speakers GraemeRocher Project Lead of Grails CTO of G2One Inc – The Groovy/Grails Company Member of JSR-241 (Java Specification Request) Expert Group Author of “The Definitive Guide to Grails”
  • 4.
    Your Speakers GuillaumeLaForge Project Lead of Groovy VP of Technology at G2One Inc – The Groovy/Grails Company Lead of JSR-241 Expert Group Co-Author of “Groovy in Action”
  • 5.
    Agenda Introduction andWhy Groovy? What makes a dynamic language? Groovy’s Meta Object Protocol Domain Specific Languages Meta Programming Patterns Applying Meta Programming techniques to Java EE platform patterns The DAO The Service Locator
  • 6.
    What is Groovy?Groovy is a dynamic language for the Java Virtual Machine (JVM) Takes inspiration from Smalltalk, Python and Ruby Integrates with the Java platform language and platform at every level
  • 7.
    What is Grails?A Web platform that implements the full stack from build system down to ORM layer Leverages existing technologies like Spring, Hibernate, Quartz etc. avoiding re-inventing the wheel Features and extensible plug-in system and an environment for runtime configuration built on Spring
  • 8.
    Getting Started Downloadfrom http://grails.org/Download Extract zip to disk Set GRAILS_HOME variable to location on disk Add $GRAILS_HOME/bin to your environment variables Download from http://groovy. codehaus .org Extract zip to disk Set GROOVY_HOME variable to location on disk Add $GROOVY_HOME/bin to your environment variables
  • 9.
    Why is Groovydynamic? A lot of confusion exists on what a factors make a language dynamic Dynamic vs Static Typing Strong vs. Weak Typing Meta programming Let’s clarify these!
  • 10.
  • 11.
    The Meta ObjectProtocol (MOP) There are many dynamic languages VB, Python, Ruby, Groovy, JavaScript™ technology But, only a few have a MOP Groovy Ruby LISP Smalltalk A MOP makes the semantics of a program extensible
  • 12.
    Groovy’s MOP Everyclass has a MetaClass, which can be obtained with: The MetaClass defines the behaviour of the object and can be inspected: def obj = &quot;Hello World!&quot; def metaClass = obj.metaClass obj. metaClass.methods .each { println it.name } Access the metaClass property The methods collection returns a list of MetaMethod instances
  • 13.
    Using respondsTo and hasProperty Need to find out whether an object implements a method? Use respondsTo : Need to find out if an object has a property? Use hasProperty : def foo = &quot;Hello World!&quot; if(foo. respondsTo(foo, &quot;toUpperCase&quot;)) println foo.toUpperCase() if(foo.metaClass. hasProperty( &quot;bytes&quot;) ) println foo.bytes.encodeAsBase64()
  • 14.
    Useful API ReferencesMetaObjectProtocol http://groovy. codehaus . org/api/groovy/lang/MetaObjectProtocol .html MetaMethod http://groovy. codehaus . org/api/groovy/lang/MetaMethod .html MetaProperty http://groovy. codehaus . org/api/groovy/lang/MetaProperty .html
  • 15.
    Adding Methods atRuntime Instance methods can be added using the MetaClass: As can properties using JavaBeans™ architecture conventions: class Dog {} Dog. metaClass.bark = { &quot;woof!&quot; } println new Dog().bark() class Dog {} Dog. metaClass.getBreed = { &quot;Bulldog&quot; } println new Dog().breed Assigning a block of code to a property of the MetaClass creates a method! Properties need to follow JavaBeans naming coventions
  • 16.
    Static Methods andConstructors Static methods can be added using the static qualifier: Constructors can be added using a special constructor property: Dog.metaClass .static.bark = {new Dog() } println Dog.create().bark() Dog. metaClass .constructor = {String s -> new Dog(name:s) } println new Dog( &quot;Fred&quot; ).name Prefix the method name with the static qualifier to make a static method Careful of Stack overflows when overriding constructors!
  • 17.
    Meta-Programming Hooks invokeMethod, methodMissing , get/setProperty , propertyMissing : Dog.metaClass . methodMissing = { String name, args-> println &quot;Dogs don’t $name!&quot; } def d = new Dog() d.quack() d.fly() &quot;Dogs don’t quack!&quot; &quot;Dogs don’t fly!&quot; No exception is thrown, the call is intercepted and the messages printed to system out Method missing allows you to intercept failed method dispatch
  • 18.
    Meta-Programming Patterns Intercept, Cache , Invoke Enables code synthesis Basic Usage: Intercept method Dynamically create new method Cache new method Invoke new method First call takes performance hit, next call faster Dog.metaClass . methodMissing = {String name, args-> def cached = {Object[] a -> println ”Dogs don’t $name!&quot; } Dog.metaClass . &quot;$name&quot; = cached cached. call(args) } Intercept – implement methodMissing Cache – Dynamically register new method Invoke – call new behaviour
  • 19.
    Re-inventing Patterns withthe MOP The Data Access Object The Service Locator
  • 20.
    The Data AccessObject (DAO) Basic Steps Define an interface Define one or many implementations Inject dependencies into implementations Dependency Injection (IoC) Factories http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
  • 21.
    Implications of DAOClass explosion Promotes anemic domain model Configuration, configuration, configuration Violates DRY
  • 22.
    Creating Dynamic SQLFinders Meta Magic with Groovy
  • 23.
    Dynamic SQL FindersExample Book.metaClass. static . methodMissing = { String name, args -> if (name.startsWith(&quot;findBy&quot;) && args) { def prop = name[6..-1] prop= prop[0].toLowerCase() + prop[1..-1] def callable = { Object[] varArgs -> def results = [] def sql = Sql.newInstance( url, user, pass, driver) sql.eachRow( &quot;&quot;&quot;select * from ${Book.name} where $prop=?&quot;&quot;&quot; , [varArgs[0]]) { results << new Book(title:it.title, author:it.author) } return results } Book.metaClass. &quot;$name&quot; = callable return callable. call(args) } } Intercept Cache Invoke
  • 24.
    Real Life Example:GORM in Grails class Album { String title String artist Date releaseDate static hasMany = [songs:Song] } class Song { String title Double duration } table - album table - song GORM classes, also known as domain classes, go in the domain directory id title artist release_date id title duration album_id
  • 25.
    GORM in ActionQuerying and Persistence with GORM
  • 26.
    Dynamic Finders &Criteria def albums = Album. list () def recentAlbums = Album. findAllByReleaseDateGreaterThan (new Date()-7) def albumsStartingWithA = Album. findAllByTitleLike ( &quot;A%&quot;) def albumsWithSongsAboutSummer = Album. withCriteria { songs { like(&quot;title&quot;, &quot;%Summmer%&quot;) } } List all records Form method expressions Use “like” queries Construct criteria on the fly to query associations
  • 27.
    GORM Features Dynamicfinder and persistence methods Criteria with a Groovy builder Object-relational Mapping DSL Caching Legacy mapping Locking strategy (optimistic/pessimistic) Built on Hibernate +
  • 28.
    MOP == Goodbyeto the DAO Repetitive, boilerplate DAO logic gone (DRY) Logic exists where it belongs - in the domain (DDD) No direct references to third part dependencies!
  • 29.
    The Service Locator/ IoC Pattern of many names Dependency Injection Service Locator Inversion of Control Abstracts dependency look-up code http://java.sun.com/blueprints/corej2eepatterns/Patterns/ServiceLocator.html
  • 30.
    Implications of ServiceLocator Requires factory classes Class explosion Promotes anemic domain model Configuration, configuration, configuration
  • 31.
    Automatic Dependency InjectionAutomatic Dependency Injection with Spring & Grails via Meta-programming
  • 32.
    Real Life Example:Spring & Grails class Book { PurchasingService purchasingService Transaction buyBook(User u) { purchasingService.buyBook(this, u) } } Book. metaClass.constructor = {-> def obj = BeanUtils.instantiateClass(Book) applicationContext .getAutowireCapableBeanFactory() . autowireBeanProperties( obj, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false) return obj } Book domain class requires reference to PurchasingService Overriding default constructor for class Autowire dependencies into object from Spring at construction time
  • 33.
    Real Life Example:Spring & Grails Advantages of Meta way Promotes Domain Driven Design (DDD) No configuration DRY def user = User.get(1) def book = new Book() book.buyBook(user) All dependencies in place even when the new operator is used!
  • 34.
    Summary Meta-programming representsa new way to think about problems Common patterns like the DAO and Service Locator are present because of limitations in Java platform Groovy and Grails open doors to declarative programmings, DSLs and Domain Driven Design (DDD)
  • 35.
    For More InformationGrails TS-6457 - Choosing Your Java Technology-Based Web Framework: A Comparison http://grails.org Groovy Sessions, Panel Discussions, BOFs: PAN-5435, TS-5815, TS-6050, TS-5274, BOF-5102, BOF-5110, TS-5693, BOF-5101 http://groovy. codehaus .org
  • 36.
    Groovy and Grails:Changing the Landscape of Java™ Platform, Enterprise Edition (Java EE Platform) Patterns Graeme Rocher Guillaume LaForge TS-5793