(A case for) GRAILSMark DaughertyCITYTECH, Inc.July 7th, 2010
OutlineInspirationGrails overviewComparison of Java/Spring/JPA application to Groovy/Grails
ContextFebruary 2010 : wrote a small Groovy/Grails app to learn the technologiesMarch 1st, 2010 : started on CDGA project (Struts, Spring, JPA)March 1st, 2010 (later that day) : realized that CDGA had an enormous amount of boilerplate code that Grails could eliminate
(Additional) ContextMay 7th, 2010 : wrote CITYTECH blog post about code savings from replacing Spring DAO code with GrailsMay 8th, 2010 – present : blog is read by a total of 4 CITYTECH employeesJuly 7th, 2010 : Grails begins to learn at a geometric rate.  It becomes self-aware at 2:14 AM, Eastern time.
Grails PrimerWeb application framework built with Groovy (Java-based dynamic language) on top of proven Java technologiesSpring MVC, HibernateFull stack for rapid developmentEmbedded Tomcat container, HSQLDB, (G)Ant, scaffolding featuresGet a basic app running within minutes
You may notice…Convention over configurationLittle-to-no initial configurationProject structure is predefined according to best practicesCommand line scripts for common tasksCreate new application, compile, test, runGenerate domain classes, controllers, services, test casesInstall pluginsContrast with your last Maven-built project
In practice…
Simple DomainDelegate 1  ∞ UserDelegate 1  ∞ ApplicationA “delegate agency” has one-to-many users and one-to-many applications.  An application contains various forms, input by users, to collect data about the delegate agency.
JPA (Java Persistence API)@Entity@Table(name = "USER")public class User implements Serializable {    @Id    private Integer id;    @OneToOne(fetch = FetchType.LAZY)    @JoinColumn(name = "DELEGATE", referencedColumnName = "ID")    private Delegate delegate;    // getters and setters, equals(), hashCode(), toString()…}
(More) JPA@Entity@Table(name = "DELEGATE")public class Delegate implements Serializable {    @Id    private Integer id;    @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)    private Set<User> users;    @OneToMany(cascade = { CascadeType.REMOVE }, fetch = FetchType.LAZY)    private Set<Application> applications;	 // getters and setters, equals(), hashCode(), toString()...}
(Still more) JPA@Entity@Table(name = "APPLICATION")public class Application implements Serializable {    @Id    private Integer id;    @ManyToOne(cascade = { CascadeType.REFRESH }, optional = false)    @JoinColumn(name = "DELEGATE”)    private Delegate delegate;	// getters and setters, equals(), hashCode(), toString()...}
Grailsclass User {	static belongsTo = [delegate:Delegate]}class Delegate {	static hasMany = [users:User, applications:Application]	static mapping = {	    users lazy:false		   applications cascade:'delete'	}}class Application {	static belongsTo = [delegate:Delegate]	static mapping = {		   delegate cascade:'refresh'	}}
DAOJPA/Hibernate = verbose, repetitiveEven a small domain model can have 1000’s of lines of code for basic CRUD operationsTedious to maintain
GORM!Hibernate under the hoodGroovy + runtime code synthesis to eliminate boilerplate code
Basic CRUD
Dynamic Finders
Additional GORM FeaturesORM DSL for mapping to legacy DB schemasCustom mappings for non-standard table and column namesEvent handlers (beforeInsert, afterUpdate)Customizable caching and fetching strategies, transactions
WebRender XML or JSON responses using markup buildersAutomatic marshalling of domain classes to XML/JSON
(More) WebGSPSimilar to JSP, but with better tag librariesfindAll, grep (filter) for collectionsMethod callsTemplatesSitemesh (decorator) layoutsCustomizable URL mappings
ValidationOften painful, less so with Grails
More FeaturesSpring Web FlowSupports subflows, conversation scope (similar to Seam)Interceptors / FiltersAJAXDOJO, GWT plugins
Even more to likeGroovy testsIdeal for TDDUnit tests created automatically from command line scriptDynamic language features for easy mockingEasy RESTful web servicesURL mappingsControllers can render XML or JSONConsider attending a CGUG meetingExtremely active community400+ plugins (Spring Security, JQuery, GWT, Google App Engine, Flex)Wide range of tutorialsFrequent releases
SummaryGrails compared to Spring, EJB, JPASubstantially less code without compromisesEasier to maintain and testShorter iterations and release cyclesSame proven underlying technologiesGain competitive edgeWhy not?

A Case for Grails

  • 1.
    (A case for)GRAILSMark DaughertyCITYTECH, Inc.July 7th, 2010
  • 2.
    OutlineInspirationGrails overviewComparison ofJava/Spring/JPA application to Groovy/Grails
  • 3.
    ContextFebruary 2010 :wrote a small Groovy/Grails app to learn the technologiesMarch 1st, 2010 : started on CDGA project (Struts, Spring, JPA)March 1st, 2010 (later that day) : realized that CDGA had an enormous amount of boilerplate code that Grails could eliminate
  • 4.
    (Additional) ContextMay 7th,2010 : wrote CITYTECH blog post about code savings from replacing Spring DAO code with GrailsMay 8th, 2010 – present : blog is read by a total of 4 CITYTECH employeesJuly 7th, 2010 : Grails begins to learn at a geometric rate. It becomes self-aware at 2:14 AM, Eastern time.
  • 5.
    Grails PrimerWeb applicationframework built with Groovy (Java-based dynamic language) on top of proven Java technologiesSpring MVC, HibernateFull stack for rapid developmentEmbedded Tomcat container, HSQLDB, (G)Ant, scaffolding featuresGet a basic app running within minutes
  • 6.
    You may notice…Conventionover configurationLittle-to-no initial configurationProject structure is predefined according to best practicesCommand line scripts for common tasksCreate new application, compile, test, runGenerate domain classes, controllers, services, test casesInstall pluginsContrast with your last Maven-built project
  • 7.
  • 8.
    Simple DomainDelegate 1 ∞ UserDelegate 1  ∞ ApplicationA “delegate agency” has one-to-many users and one-to-many applications. An application contains various forms, input by users, to collect data about the delegate agency.
  • 9.
    JPA (Java PersistenceAPI)@Entity@Table(name = "USER")public class User implements Serializable { @Id private Integer id; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "DELEGATE", referencedColumnName = "ID") private Delegate delegate; // getters and setters, equals(), hashCode(), toString()…}
  • 10.
    (More) JPA@Entity@Table(name ="DELEGATE")public class Delegate implements Serializable { @Id private Integer id; @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER) private Set<User> users; @OneToMany(cascade = { CascadeType.REMOVE }, fetch = FetchType.LAZY) private Set<Application> applications; // getters and setters, equals(), hashCode(), toString()...}
  • 11.
    (Still more) JPA@Entity@Table(name= "APPLICATION")public class Application implements Serializable { @Id private Integer id; @ManyToOne(cascade = { CascadeType.REFRESH }, optional = false) @JoinColumn(name = "DELEGATE”) private Delegate delegate; // getters and setters, equals(), hashCode(), toString()...}
  • 12.
    Grailsclass User { staticbelongsTo = [delegate:Delegate]}class Delegate { static hasMany = [users:User, applications:Application] static mapping = { users lazy:false applications cascade:'delete' }}class Application { static belongsTo = [delegate:Delegate] static mapping = { delegate cascade:'refresh' }}
  • 13.
    DAOJPA/Hibernate = verbose,repetitiveEven a small domain model can have 1000’s of lines of code for basic CRUD operationsTedious to maintain
  • 14.
    GORM!Hibernate under thehoodGroovy + runtime code synthesis to eliminate boilerplate code
  • 15.
  • 16.
  • 17.
    Additional GORM FeaturesORMDSL for mapping to legacy DB schemasCustom mappings for non-standard table and column namesEvent handlers (beforeInsert, afterUpdate)Customizable caching and fetching strategies, transactions
  • 18.
    WebRender XML orJSON responses using markup buildersAutomatic marshalling of domain classes to XML/JSON
  • 19.
    (More) WebGSPSimilar toJSP, but with better tag librariesfindAll, grep (filter) for collectionsMethod callsTemplatesSitemesh (decorator) layoutsCustomizable URL mappings
  • 20.
  • 21.
    More FeaturesSpring WebFlowSupports subflows, conversation scope (similar to Seam)Interceptors / FiltersAJAXDOJO, GWT plugins
  • 22.
    Even more tolikeGroovy testsIdeal for TDDUnit tests created automatically from command line scriptDynamic language features for easy mockingEasy RESTful web servicesURL mappingsControllers can render XML or JSONConsider attending a CGUG meetingExtremely active community400+ plugins (Spring Security, JQuery, GWT, Google App Engine, Flex)Wide range of tutorialsFrequent releases
  • 23.
    SummaryGrails compared toSpring, EJB, JPASubstantially less code without compromisesEasier to maintain and testShorter iterations and release cyclesSame proven underlying technologiesGain competitive edgeWhy not?