A Case for Grails

23
(A case for) GRAILS Mark Daugherty CITYTECH, Inc. July 7 th , 2010

Transcript of A Case for Grails

Page 1: A Case for Grails

(A case for) GRAILS

Mark DaughertyCITYTECH, Inc.July 7th, 2010

Page 2: A Case for Grails

Outline

• Inspiration• Grails overview• Comparison of Java/Spring/JPA application to

Groovy/Grails

Page 3: A Case for Grails

Context

• February 2010 : wrote a small Groovy/Grails app to learn the technologies

• March 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

Page 4: A Case for Grails

(Additional) Context

• May 7th, 2010 : wrote CITYTECH blog post about code savings from replacing Spring DAO code with Grails

• May 8th, 2010 – present : blog is read by a total of 4 CITYTECH employees

• July 7th, 2010 : Grails begins to learn at a geometric rate. It becomes self-aware at 2:14 AM, Eastern time.

Page 5: A Case for Grails

Grails Primer

• Web application framework built with Groovy (Java-based dynamic language) on top of proven Java technologies– Spring MVC, Hibernate

• Full stack for rapid development– Embedded Tomcat container, HSQLDB, (G)Ant,

scaffolding features– Get a basic app running within minutes

Page 6: A Case for Grails

You may notice…

• Convention over configuration– Little-to-no initial configuration– Project structure is predefined according to best

practices– Command line scripts for common tasks• Create new application, compile, test, run• Generate domain classes, controllers, services, test

cases• Install plugins

– Contrast with your last Maven-built project

Page 7: A Case for Grails

In practice…

Page 8: A Case for Grails

Simple Domain

Delegate 1 ∞ UserDelegate 1 ∞ Application

A “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.

Page 9: A Case for Grails

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()…}

Page 10: A Case for Grails

(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()...}

Page 11: A Case for Grails

(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()...}

Page 12: A Case for Grails

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'}

}

Page 13: A Case for Grails

DAO

• JPA/Hibernate = verbose, repetitive– Even a small domain model can have 1000’s of

lines of code for basic CRUD operations– Tedious to maintain

Page 14: A Case for Grails

GORM!

• Hibernate under the hood• Groovy + runtime code synthesis to eliminate

boilerplate code

Page 15: A Case for Grails

Basic CRUD

Page 16: A Case for Grails

Dynamic Finders

Page 17: A Case for Grails

Additional GORM Features

• ORM DSL for mapping to legacy DB schemas– Custom mappings for non-standard table and

column names• Event handlers (beforeInsert, afterUpdate)• Customizable caching and fetching strategies,

transactions

Page 18: A Case for Grails

Web

• Render XML or JSON responses using markup builders– Automatic marshalling of domain classes to

XML/JSON

Page 19: A Case for Grails

(More) Web

• GSP– Similar to JSP, but with better tag libraries• findAll, grep (filter) for collections• Method calls

• Templates• Sitemesh (decorator) layouts• Customizable URL mappings

Page 20: A Case for Grails

Validation

• Often painful, less so with Grails

Page 21: A Case for Grails

More Features

• Spring Web Flow– Supports subflows, conversation scope (similar to

Seam)• Interceptors / Filters• AJAX– DOJO, GWT plugins

Page 22: A Case for Grails

Even more to like

• Groovy tests– Ideal for TDD– Unit tests created automatically from command line script– Dynamic language features for easy mocking

• Easy RESTful web services– URL mappings– Controllers can render XML or JSON– Consider attending a CGUG meeting

• Extremely active community– 400+ plugins (Spring Security, JQuery, GWT, Google App Engine, Flex)– Wide range of tutorials– Frequent releases

Page 23: A Case for Grails

Summary

• Grails compared to Spring, EJB, JPA– Substantially less code without compromises– Easier to maintain and test– Shorter iterations and release cycles– Same proven underlying technologies– Gain competitive edge

• Why not?