Groovy Grails DevJam Jam Session
Upcoming SlideShare
Loading in...5
×
 

Groovy Grails DevJam Jam Session

on

  • 8,102 views

Groovy is a dynamic programming language that runs on the JVM and seamlessly interacts with Java. Grails melds the concept of "Convention over Configuration" and the dynamic power of Groovy to create ...

Groovy is a dynamic programming language that runs on the JVM and seamlessly interacts with Java. Grails melds the concept of "Convention over Configuration" and the dynamic power of Groovy to create a framework that greatly simplifies the development of web based applications. This slideshow explores the two - dive into some Groovy vs. Java code examples and see some examples of Grails. We'll also discuss when to introduce either into an existing (or greenfield) environment and where they have worked and where they have failed

Statistics

Views

Total Views
8,102
Views on SlideShare
7,927
Embed Views
175

Actions

Likes
24
Downloads
527
Comments
4

5 Embeds 175

http://www.piragua.com 133
http://www.slideshare.net 21
http://www.techgig.com 13
http://www.linkedin.com 7
https://www.linkedin.com 1

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

14 of 4 Post a comment

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Groovy Grails DevJam Jam Session Groovy Grails DevJam Jam Session Presentation Transcript

    • Groovy/Grails DevJam
    • Act I
    • “When you program in Groovy, in many ways you’re writing a special kind of Java.” -Dierk König Groovy in Action
    • .groovy .java
    • hugobook:groovy mjhugo$ groovyc usage: groovyc [options] <source-files> options: --encoding <encoding> Specify the encoding of the user class files. -F <flag> -J <property=value> -d Specify where to place generated class files. -e,--exception Print stack trace on error. -h,--help Print a synopsis of standard options. -j,--jointCompilation Attach javac compiler to compile .java files. -v,--version Print the version.
    • 20% 80%
    • getters and setters
    • 1 package com.piragua.java; 2 3 public class SimpleBook { 4 private String title; 5 private String authorName; 6 7 public String getTitle() { 8 return title; 9 } 10 11 public void setTitle(String title) { 12 this.title = title; 13 } 14 15 public String getAuthorName() { 16 return authorName; 17 } 18 19 public void setAuthorName(String authorName) { 20 this.authorName = authorName; 21 } 22 }
    • 1 package com.piragua.groovy 2 3 class SimpleBook { 4 String title 5 String authorName 6 }
    • javap -private SimpleBook Compiled from quot;SimpleBook.groovyquot; public class com.piragua.groovy.SimpleBook ... { private java.lang.String title; private java.lang.String author; public java.lang.String getTitle(); public void setTitle(java.lang.String); public java.lang.String getAuthor(); public void setAuthor(java.lang.String); ... }
    • javap -private SimpleBook Compiled from quot;SimpleBook.groovyquot; public class com.piragua.groovy.SimpleBook ... { private java.lang.String title; private java.lang.String author; public java.lang.String getTitle(); public void setTitle(java.lang.String); public java.lang.String getAuthor(); public void setAuthor(java.lang.String); ... }
    • 1 package com.piragua.java; 1 package com.piragua.groovy 2 2 3 import java.util.Date; 3 class Book { 4 import java.util.List; 4 String title 5 5 String authorName 6 public class Book { 6 Integer numberOfPages 7 private String title; 7 String subTitle 8 private String authorName; 8 List chapters 9 private Integer numberOfPages; 9 Date publishDate 10 private String subTitle; 10 String publisher 11 private List<Chapter> chapters; 11 12 private Date publishDate; 12 String toString() { 13 private String publisher; 13 title?.toUpperCase() 14 14 } 15 public String getPublisher() { 15 16 return publisher; 16 String displayString() { 17 } 17 quot;<u>${title}</u> by ${authorName}, (${numberOfPages} pages)quot; 18 18 } 19 public void setPublisher(String publisher) { 19 20 this.publisher = publisher; 20 Chapter findChapterByTitle(String title) { 21 } 21 // finding the first item that matches criteria 22 22 chapters?.find({it?.title == title}) 23 public Date getPublishDate() { 23 } 24 return publishDate; 24 } 25 } 26 27 public void setPublishDate(Date publishDate) { 28 this.publishDate = publishDate; 29 } 30 31 public List getChapters() { 32 return chapters; 33 } 34 35 public void setChapters(List chapters) { 36 this.chapters = chapters; 37 } 38 39 public String getTitle() { 40 return title; 41 } 42 43 public void setTitle(String title) { 44 this.title = title; 45 } 46 47 public String getAuthorName() { 48 return authorName; 49 } 50 51 public void setAuthorName(String authorName) { 52 this.authorName = authorName; 53 } 54 55 public Integer getNumberOfPages() { 56 return numberOfPages; 57 } 58 59 public void setNumberOfPages(Integer numberOfPages) { 60 this.numberOfPages = numberOfPages; 61 } 62 63 public String getSubTitle() { 64 return subTitle; 65 } 66 67 public void setSubTitle(String subTitle) { 68 this.subTitle = subTitle; 69 } 70 71 public String toString() { 72 String upperCaseTitle = null; 73 if (title != null) { 74 upperCaseTitle = title.toUpperCase(); 75 } 76 return upperCaseTitle; 77 } 78 79 public String displayString() { 80 return quot;<u>quot; + title + quot;</u> by quot; + authorName + quot;, (quot; + numberOfPages + quot; pages)quot;; 81 } 82 83 public Chapter findChapterByTitle(String chapterTitle) { 84 Chapter foundChapter = null; 85 86 if (chapterTitle != null && chapters != null) { 87 for (int i = 0; i < chapters.size(); i++) { 88 if (chapters.get(i) != null && 89 chapterTitle.equals(chapters.get(i).getTitle())) { 90 foundChapter = chapters.get(i); 91 break; 92 } 93 } 94 } 95 return foundChapter; 96 } 97 }
    • constructor convenience http://flickr.com/photos/9229859@N02/1052409181/
    • 1 package com.piragua.java; 2 3 import junit.framework.TestCase; 4 5 import java.util.ArrayList; 6 import java.util.Date; 7 8 public class BookTest extends TestCase { 9 Book book; 10 Chapter chapter; 11 12 public void setUp() { 13 book = new Book(); 14 book.setNumberOfPages(300); 15 book.setAuthorName(quot;Mike Hugoquot;); 16 book.setTitle(quot;Groovy Jamquot;); 17 book.setSubTitle(quot;Jamminquot;); 18 book.setPublisher(quot;Piragua Pressquot;); 19 book.setPublishDate(new Date()); 20 }
    • 1 package com.piragua.groovy 2 3 public class BookTest extends GroovyTestCase { 4 Book book 5 Chapter grails, groovy, why 6 7 void setUp() { 8 book = new Book(title: quot;Groovy Jamquot;, subTitle:quot;Jamminquot;, 9 authorName: quot;Mike Hugoquot;, numberOfPages: 300, 10 publishDate:new Date(), publisher: quot;Piragua Pressquot;) 11 }
    • null safe dereferencing http://flickr.com/photos/synthesisstudios/352834727/
    • 32 public String toString() { 33 String upperCaseTitle = null; 34 if (title != null){ 35 upperCaseTitle = title.toUpperCase(); 36 } 37 return upperCaseTitle; 38 }
    • String toString(){ title?.toUpperCase() }
    • // more complex String toString(){ book?.publisher?.address?.city?.toUpperCase() }
    • groovy strings http://flickr.com/photos/austinevan/416813459/
    • // Java Example public String displayString() { return quot;<u>quot; + title + quot;</u> by quot; + authorName + quot;, (quot; + numberOfPages + quot; pages)quot;; }
    • // Java Example public String displayString() { return quot;<u>quot; + title + quot;</u> by quot; + authorName + quot;, (quot; + numberOfPages + quot; pages)quot;; }
    • String displayString() { quot;<u>${title}</u> by ${authorName}, (${numberOfPages} pages)quot; }
    • String multiLineDisplayString() { quot;quot;quot;<u>${title}</u> by ${authorName} (${numberOfPages} pages)quot;quot;quot; }
    • collections http://flickr.com/photos/stibbons/375342559/
    • 11 private List<Chapter> chapters; //... 55 public Chapter findChapterByTitle(String chapterTitle) { 56 Chapter foundChapter = null; 57 58 if (chapterTitle != null && chapters != null) { 59 for (int i = 0; i < chapters.size(); i++) { 60 if (chapters.get(i) != null && 61 chapterTitle.equals(chapters.get(i).getTitle())) { 62 foundChapter = chapters.get(i); 63 break; 64 } 65 } 66 } 67 return foundChapter; 68 }
    • 11 private List<Chapter> chapters; //... 55 public Chapter findChapterByTitle(String chapterTitle) { 56 Chapter foundChapter = null; 57 58 if (chapterTitle != null && chapters != null) { 59 for (int i = 0; i < chapters.size(); i++) { 60 if (chapters.get(i) != null && 61 chapterTitle.equals(chapters.get(i).getTitle())) { 62 foundChapter = chapters.get(i); 63 break; 64 } 65 } 66 } 67 return foundChapter; 68 }
    • 8 List chapters //... 17 Chapter findChapterByTitle(String title) { 18 // finding the first item that matches criteria 19 chapters?.find({it?.title == title}) 20 }
    • 8 List chapters //... 22 List findChaptersByTitleStartingWith(String searchKeyword) { 23 // finding all matching items 24 chapters?.findAll({it?.title?.startsWith(searchKeyword)}) 25 }
    • 8 List chapters //... 27 void printChapterTitles() { 28 // iterating over a list 29 chapters.each {chapter -> 30 println chapter?.title 31 } 32 }
    • duck typing http://flickr.com/photos/davidw/380277419/
    • 1 package com.piragua.java; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.*; 5 import java.io.IOException; 6 7 public class MyServlet extends HttpServlet { 8 9 @Override 10 protected void doPost(HttpServletRequest request, 11 HttpServletResponse response) 12 throws ServletException, IOException { 13 14 String username = request.getParameter(quot;usernamequot;); 15 if (username != null) { 16 HttpSession session = request.getSession(true); 17 session.setAttribute(quot;loggedInUserquot;, username); 18 } 19 20 } 21 } 22
    • 1 package com.piragua.groovy 2 3 import javax.servlet.http.* 4 import com.piragua.java.MyServlet 5 6 public class MyServletTest extends GroovyTestCase { 7 8 Map params 9 Map session 10 11 def request 12 13 protected void setUp() { 14 params = [:] 15 session = [:] 16 def mockSession = [setAttribute: {k, v -> session[k] = v }] 17 18 request = [ 19 getParameter: {param -> return params[param]}, 20 getSession: {createNew -> return mockSession as HttpSession}] 21 }
    • 23 void testDoGetFoundUser() { 24 params.username = 'mike' 25 new MyServlet().doPost(request as HttpServletRequest, 26 [:] as HttpServletResponse) 27 assertEquals(params.username, session.loggedInUser) 28 } 29 30 void testDoGetNoUser() { 31 params.username = null 32 new MyServlet().doPost(request as HttpServletRequest, 33 [:] as HttpServletResponse) 34 assertNull(session.loggedInUser) 35 }
    • If we had more time... • file handling • really easy regular expressions • groovy truth • case / switch • closures • meta programming
    • http://groovy.codehaus.org/ http://groovy.mn/
    • Act II
    • Web MVC Framework
    • convention http://flickr.com/photos/markpasc/92779595
    • configuration http://flickr.com/photos/clintjcl/169886338
    • DRY http://flickr.com/photos/joshsommers/935470210/
    • Development
    • Deployment
    • Artifacts http://flickr.com/photos/ragesoss/118620722/
    • Artefacts http://flickr.com/photos/ragesoss/118620722/
    • grails create-app devjam
    • mysql> describe event; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | version | bigint(20) | NO | | NULL | | | event_date | datetime | NO | | NULL | | | title | varchar(255) | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec)
    • mysql> describe event; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | version | bigint(20) | NO | | NULL | | | event_date | datetime | NO | | NULL | | | title | varchar(255) | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec)
    • mysql> describe event; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | version | bigint(20) | NO | | NULL | | | event_date | datetime | NO | | NULL | | | title | varchar(255) | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec)
    • Zero
    • Customer class Customer { ! Address address } Address
    • class Customer { ! static hasMany = [incidents:Incident] } Customer Incident
    • class Customer { ! static hasMany = [products:Product] } class Product { static hasMany = [customers:Customer] static belongsTo = Customer //Customer owns the relationship } Customer Customer Product Product
    • http://server/devjam/event/list name of application
    • http://server/devjam/event/list name of controller
    • http://server/devjam/event/list name of action
    • http://server/devjam/event/list?max=10
    • Data Binding
    • Dependency Injection
    • Demo
    • If we had more time... • testing • tag libraries • services • plugins • content negotiation
    • http://grails.org http://grails.org/doc/1.0.x/
    • Act III
    • http://flickr.com/photos/johnniewalker/359440369
    • http://flickr.com/photos/philliecasablanca/2473728872
    • Learning Curve 100 75 50 25 0 * data for this chart is completely fabricated
    • Learning Curve 100 75 50 25 0 * data for this chart is completely fabricated
    • http://flickr.com/photos/13010608@N02/2441101135/
    • + +
    • http://flickr.com/photos/kevint/85911467
    • 1 package com.piragua.groovy 2 3 import javax.servlet.http.* 4 import com.piragua.java.MyServlet 5 6 class MyServletTest extends GroovyTestCase { 7 8 Map params 9 Map session 10 11 def request 12 13 protected void setUp() { 14 params = [:] 15 session = [:] 16 def mockSession = [setAttribute: {k, v -> session[k] = v }]
    • http://flickr.com/photos/nengard/82039595
    • 200,000 1 Million $250/month users page views/month VPS
    • http://flickr.com/photos/oxygenws/39895404
    • XYZ Thing
    • http://flickr.com/photos/thatblondegirl/467513888
    • Thank You
    • Groovy/Grails DevJam https://duke.dev.java.net/images/guitar/DukeAsKeith-daylight.png http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/cruise/reporting-app/images/DukeGroovyChair.jpg
    • 3 things to talk about tonight: -Brief overview of Groovy -High level Grails (and Live Coding!) -Thumbs up and Thumbs Down: ! -When should you choose to use Groovy/Grails in existing or greenfield project ! -Where it has worked (and why) and where it has failed (and why)
    • Act I What is Groovy? - ask the audience...possible answers: - answers.com: “Very pleasing; wonderful.” - agile language - scripting language for the JVM - dynamically typed language - build tool - runtime tool for the JVM - high level language for the JVM that compiles to byte code - open source java language
    • “When you program in Groovy, in many ways you’re writing a special kind of Java.” -Dierk König Groovy in Action Groovy is all of those things, but most of all I like this definition. What is Groovy? - answer by Dierk König, Groovy committer and author of “Groovy in Action” - dynamic language for the JVM
    • .groovy .java In fact, most of the time you can take .java file and rename it .groovy and it will compile and run
    • Groovy and Java work seamlessly together -your java classes can reference groovy classes and groovy classes can reference java classes
    • hugobook:groovy mjhugo$ groovyc usage: groovyc [options] <source-files> options: --encoding <encoding> Specify the encoding of the user class files. -F <flag> -J <property=value> -d Specify where to place generated class files. -e,--exception Print stack trace on error. -h,--help Print a synopsis of standard options. -j,--jointCompilation Attach javac compiler to compile .java files. -v,--version Print the version. This is because of something unique to groovy - the Groovy Joint Compiler - you can compile .groovy and .java files at the same time allowing that seamless interaction
    • What this means is if you’re already using Java, it works with everything you already have - IDEs - Open Source Frameworks - Application Servers, etc.
    • 20% 80% For me, it comes down to the 80/20 rule. Groovy gives me the ability to write concise code thatquot;s straight to the point of what Iquot;m trying to do. I donquot;t have to include “ceremony” - code that doesnquot;t relate to the task at hand (Stuart Halloway, http://blog.thinkrelevance.com/ 2008/4/1/ending-legacy-code-in-our-lifetime) and can focus directly on the goal my code is trying to achieve. Examples...
    • getters and setters Getters and Setters Example Standard stuff - create some properties and have your IDE of choice generate the getters and setters but WHY generate them? they add so much noise to your code...
    • 1 package com.piragua.java; 2 3 public class SimpleBook { 4 private String title; 5 private String authorName; 6 7 public String getTitle() { 8 return title; 9 } 10 11 public void setTitle(String title) { 12 this.title = title; 13 } 14 15 public String getAuthorName() { 16 return authorName; 17 } 18 19 public void setAuthorName(String authorName) { 20 this.authorName = authorName; 21 } 22 } Java example: two properties, 15 lines of code for getters/ setters Now, letquot;s look at the same class in Groovy...
    • 1 package com.piragua.groovy 2 3 class SimpleBook { 4 String title 5 String authorName 6 } Same class, 0 lines of code for getters/setters Also notice that the attributes and the class are not scoped - thatquot;s because Groovy provides sensible defaults for these - Lets take a look at a snippet of the byte code as shown by javap
    • javap -private SimpleBook Compiled from quot;SimpleBook.groovyquot; public class com.piragua.groovy.SimpleBook ... { private java.lang.String title; private java.lang.String author; public java.lang.String getTitle(); public void setTitle(java.lang.String); public java.lang.String getAuthor(); public void setAuthor(java.lang.String); ... } - getters and setters are provided automatically ! - You can add your own getters and setters to define custom behavior - but how often do you really do this?
    • javap -private SimpleBook Compiled from quot;SimpleBook.groovyquot; public class com.piragua.groovy.SimpleBook ... { private java.lang.String title; private java.lang.String author; public java.lang.String getTitle(); public void setTitle(java.lang.String); public java.lang.String getAuthor(); public void setAuthor(java.lang.String); ... } - no need to define class as public - thatquot;s the default - attributes are private by default - methods are public by default
    • 1 package com.piragua.java; 1 package com.piragua.groovy 2 2 3 import java.util.Date; 3 class Book { 4 import java.util.List; 4 String title 5 5 String authorName 6 public class Book { 6 Integer numberOfPages 7 private String title; 7 String subTitle 8 private String authorName; 8 List chapters 9 private Integer numberOfPages; 9 Date publishDate 10 private String subTitle; 10 String publisher 11 private List<Chapter> chapters; 11 12 private Date publishDate; 12 String toString() { 13 private String publisher; 13 title?.toUpperCase() 14 14 } 15 public String getPublisher() { 15 16 return publisher; 16 String displayString() { 17 } 17 quot;<u>${title}</u> by ${authorName}, (${numberOfPages} pages)quot; 18 18 } 19 public void setPublisher(String publisher) { 19 20 this.publisher = publisher; 20 Chapter findChapterByTitle(String title) { 21 } 21 // finding the first item that matches criteria 22 22 chapters?.find({it?.title == title}) 23 public Date getPublishDate() { 23 } 24 return publishDate; 24 } 25 } 26 27 public void setPublishDate(Date publishDate) { 28 this.publishDate = publishDate; 29 } 30 31 public List getChapters() { 32 return chapters; 33 } 34 35 public void setChapters(List chapters) { 36 this.chapters = chapters; 37 } 38 39 public String getTitle() { 40 return title; 41 } 42 43 public void setTitle(String title) { 44 this.title = title; 45 } 46 47 public String getAuthorName() { 48 return authorName; 49 } 50 51 public void setAuthorName(String authorName) { 52 this.authorName = authorName; 53 } 54 55 public Integer getNumberOfPages() { 56 return numberOfPages; 57 } 58 59 public void setNumberOfPages(Integer numberOfPages) { 60 this.numberOfPages = numberOfPages; 61 } 62 63 public String getSubTitle() { 64 return subTitle; 65 } 66 67 public void setSubTitle(String subTitle) { 68 this.subTitle = subTitle; 69 } 70 71 public String toString() { 72 String upperCaseTitle = null; 73 if (title != null) { 74 upperCaseTitle = title.toUpperCase(); 75 } 76 return upperCaseTitle; 77 } 78 79 public String displayString() { 80 return quot;<u>quot; + title + quot;</u> by quot; + authorName + quot;, (quot; + numberOfPages + quot; pages)quot;; 81 } 82 83 public Chapter findChapterByTitle(String chapterTitle) { 84 Chapter foundChapter = null; 85 86 if (chapterTitle != null && chapters != null) { 87 for (int i = 0; i < chapters.size(); i++) { 88 if (chapters.get(i) != null && 89 chapterTitle.equals(chapters.get(i).getTitle())) { 90 foundChapter = chapters.get(i); 91 break; 92 } 93 } 94 } 95 return foundChapter; 96 } 97 } This is the same class - on the left is Java (97 lines of code), on the right is Groovy (24 lines of code). 6 pt font Each class has 7 attributes and three methods. When you go to maintain the Book class, which file would you rather work with?
    • constructor convenience http://flickr.com/photos/9229859@N02/1052409181/
    • 1 package com.piragua.java; 2 3 import junit.framework.TestCase; 4 5 import java.util.ArrayList; 6 import java.util.Date; 7 8 public class BookTest extends TestCase { 9 Book book; 10 Chapter chapter; 11 12 public void setUp() { 13 book = new Book(); 14 book.setNumberOfPages(300); 15 book.setAuthorName(quot;Mike Hugoquot;); 16 book.setTitle(quot;Groovy Jamquot;); 17 book.setSubTitle(quot;Jamminquot;); 18 book.setPublisher(quot;Piragua Pressquot;); 19 book.setPublishDate(new Date()); 20 } Constructor Shortcut Happens all the time in unit testing, but also sometimes in real code for setting defaults New up an object, then call all the setters to populate some values
    • 1 package com.piragua.groovy 2 3 public class BookTest extends GroovyTestCase { 4 Book book 5 Chapter grails, groovy, why 6 7 void setUp() { 8 book = new Book(title: quot;Groovy Jamquot;, subTitle:quot;Jamminquot;, 9 authorName: quot;Mike Hugoquot;, numberOfPages: 300, 10 publishDate:new Date(), publisher: quot;Piragua Pressquot;) 11 } In groovy, you can use named parameters in the constructor to build objects - can happen in any order - can pass all, some, or none of the attributes to the constructor - itquot;s descriptive - you know whatquot;s being set because it says it right here (e.g. title: “groovy jam”)...if you created a java constructor how would you remember which order to pass the parameters?
    • null safe dereferencing http://flickr.com/photos/synthesisstudios/352834727/
    • 32 public String toString() { 33 String upperCaseTitle = null; 34 if (title != null){ 35 upperCaseTitle = title.toUpperCase(); 36 } 37 return upperCaseTitle; 38 } In Java, you often have times where you check to see if something is null before performing an action on it
    • String toString(){ title?.toUpperCase() } In Groovy, you can use the ? operator to safely traverse the tree of an object graph
    • // more complex String toString(){ book?.publisher?.address?.city?.toUpperCase() } If any of the attributes in this example are null, groovy will stop at that point and return null
    • groovy strings http://flickr.com/photos/austinevan/416813459/
    • // Java Example public String displayString() { return quot;<u>quot; + title + quot;</u> by quot; + authorName + quot;, (quot; + numberOfPages + quot; pages)quot;; } Yeck. String concatenation is evil So is using string buffer
    • // Java Example public String displayString() { return quot;<u>quot; + title + quot;</u> by quot; + authorName + quot;, (quot; + numberOfPages + quot; pages)quot;; } Yeck. String concatenation is evil So is using string buffer
    • String displayString() { quot;<u>${title}</u> by ${authorName}, (${numberOfPages} pages)quot; } Groovy strings allow you to construct strings using ${} notation You can also do multi line strings
    • String multiLineDisplayString() { quot;quot;quot;<u>${title}</u> by ${authorName} (${numberOfPages} pages)quot;quot;quot; } You can also do multi line strings
    • collections http://flickr.com/photos/stibbons/375342559/
    • 11 private List<Chapter> chapters; //... 55 public Chapter findChapterByTitle(String chapterTitle) { 56 Chapter foundChapter = null; 57 58 if (chapterTitle != null && chapters != null) { 59 for (int i = 0; i < chapters.size(); i++) { 60 if (chapters.get(i) != null && 61 chapterTitle.equals(chapters.get(i).getTitle())) { 62 foundChapter = chapters.get(i); 63 break; 64 } 65 } 66 } 67 return foundChapter; 68 } Java example of finding a chapter by title - iterate over the the list until you find the one youquot;re looking for, set it in a temp variable and break
    • 11 private List<Chapter> chapters; //... 55 public Chapter findChapterByTitle(String chapterTitle) { 56 Chapter foundChapter = null; 57 58 if (chapterTitle != null && chapters != null) { 59 for (int i = 0; i < chapters.size(); i++) { 60 if (chapters.get(i) != null && 61 chapterTitle.equals(chapters.get(i).getTitle())) { 62 foundChapter = chapters.get(i); 63 break; 64 } 65 } 66 } 67 return foundChapter; 68 } Java example of finding a chapter by title - by the way, did you notice all the null checking going on that distracts from the essence of the code: finding a chapter by title
    • 8 List chapters //... 17 Chapter findChapterByTitle(String title) { 18 // finding the first item that matches criteria 19 chapters?.find({it?.title == title}) 20 } Groovy example - use .find and pass a closure - closure is executed against every item in the list until a match is found - #itquot; is an implicit parameter passed to a closure, can be named
    • 8 List chapters //... 22 List findChaptersByTitleStartingWith(String searchKeyword) { 23 // finding all matching items 24 chapters?.findAll({it?.title?.startsWith(searchKeyword)}) 25 } - can also use .findAll
    • 8 List chapters //... 27 void printChapterTitles() { 28 // iterating over a list 29 chapters.each {chapter -> 30 println chapter?.title 31 } 32 } or .each to iterate over a collection
    • duck typing http://flickr.com/photos/davidw/380277419/ http://en.wikipedia.org/wiki/Duck_typing If it walks like a duck and quacks like a duck, I would call it a duck. Rather than create an interface to define the contract, use behavior at runtime to determine the functionality So now, a Java example
    • oh wait. you canquot;t do this in java. no example here.
    • 1 package com.piragua.java; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.*; 5 import java.io.IOException; 6 7 public class MyServlet extends HttpServlet { 8 9 @Override 10 protected void doPost(HttpServletRequest request, 11 HttpServletResponse response) 12 throws ServletException, IOException { 13 14 String username = request.getParameter(quot;usernamequot;); 15 if (username != null) { 16 HttpSession session = request.getSession(true); 17 session.setAttribute(quot;loggedInUserquot;, username); 18 } 19 20 } 21 } 22 Herequot;s an example of a Java Servlet. It takes a parameter from the request, and if it is not null, sets it in to the session. If I wanted to test this, I would have to provide a full implementation of HttpServletRequest and HttpServletResponse just in order to call the method. Note: Spring (and other frameworks) provide Mock implementations of HttpServletRequest and HttpServletResponse,
    • 1 package com.piragua.groovy 2 3 import javax.servlet.http.* 4 import com.piragua.java.MyServlet 5 6 public class MyServletTest extends GroovyTestCase { 7 8 Map params 9 Map session 10 11 def request 12 13 protected void setUp() { 14 params = [:] 15 session = [:] 16 def mockSession = [setAttribute: {k, v -> session[k] = v }] 17 18 request = [ 19 getParameter: {param -> return params[param]}, 20 getSession: {createNew -> return mockSession as HttpSession}] 21 } But using Groovy, I can utilize Duck Typing to mock out the implementation. Line 20 has an example: “mockSession as HttpSession” more in the tests
    • 23 void testDoGetFoundUser() { 24 params.username = 'mike' 25 new MyServlet().doPost(request as HttpServletRequest, 26 [:] as HttpServletResponse) 27 assertEquals(params.username, session.loggedInUser) 28 } 29 30 void testDoGetNoUser() { 31 params.username = null 32 new MyServlet().doPost(request as HttpServletRequest, 33 [:] as HttpServletResponse) 34 assertNull(session.loggedInUser) 35 } Line 25: “request as HttpServletRequest” - my map (defined in the setup method) now looks like a HttpServletRequest to the Servlet under test Line 33: “[:] as HttpServletResponse” just acts as a non-null HttpServletResponse. How would you do this in Java? Create a class, implement the HttpServletResponse interface with a bunch of empty methods, then new it up and pass it into the doPost method. That sucks. Now, I know duck typing is controversial. Interfaces can be a good thing, and they enforce the contract at compile time. With duck typing, you donquot;t
    • If we had more time... • file handling • really easy regular expressions • groovy truth • case / switch • closures • meta programming For reference in the handout: - File: Convenience methods for writing and reading files: http://docs.codehaus.org/display/GROOVY/JN2015-Files - Truth: .equals is the same as ==; 1 is true, 0 is false; null is false; empty string is false; etc. : http://docs.codehaus.org/ display/GROOVY/Groovy+Truth - Regular expressions are so easy! http://naleid.com/blog/2008/05/19/dont-fear-the-regexp/ - Case / Switch: can switch on any type: http://groovy.codehaus.org/Logical+Branching - Closures: named block of code. pass it around, reuse it, do all sorts of fun things: http://groovy.codehaus.org/Closures - Meta Programming: http://groovy.dzone.com/articles/metaprogramming-groovy-ii-expa , also http://naleid.com/blog/ 2008/05/07/what-methods-does-my-groovygrails-class-have/ - See more differences from Java: http://groovy.codehaus.org/Differences+from+Java
    • http://groovy.codehaus.org/ http://groovy.mn/ Two resources: Groovy website @ codehaus - api, documentation, and lots of examples Groovy Users Group of MN - meets the second Tuesday of the month in NE minneapolis Also see this presentation by Guillaume LaForge (groovy project manager) on Groovy http://www.slideshare.net/glaforge/groovy-and-grails-in-action-devoxx-2008- university-guillaume-laforge-presentation
    • Three books: -Groovy in Action (Dierk König) -Groovy Recipies (Scott Davis) -Programming Groovy (Venkat Subramaniam) http://www.amazon.com/Groovy-Action-Dierk-Koenig/dp/ 1932394842 http://www.amazon.com/Groovy-Recipes-Greasing-Pragmatic-
    • Act II So now, on to Grails...What is Grails?
    • Web MVC Framework Grails is a Web Model/View/Controller framework
    • that leverages the power of Groovy, Hibernate, Spring and Java
    • convention http://flickr.com/photos/markpasc/92779595 With it you can do rapid application development by using the concepts of Convention...
    • configuration http://flickr.com/photos/clintjcl/169886338 instead of configuration (AKA convention over configuration)
    • DRY http://flickr.com/photos/joshsommers/935470210/ And “Don’t Repeat Yourself” Why add all sorts of ceremony to your code in configuration when it could be implied?
    • Development Grails provides a full *development* environment out of the box including an: - in-memory HSQL DB - Jetty application server - Automatic reloading of most artifacts But you’re not limited to that in Development or even in Production -
    • Deployment Jetty and HSQLDB are just the defaults - You can deploy a grails application on any application server that can handle a WAR file and any database that has a JDBC driver But I’m getting ahead of myself...let’s get started with some Grails basics
    • Artifacts http://flickr.com/photos/ragesoss/118620722/ Artifacts. or, if you’re british
    • Artefacts http://flickr.com/photos/ragesoss/118620722/ A lot of the core contributors to Grails are in the UK, so you sometimes run into this (in the Grails code base)
    • grails create-app devjam Every Grails Application has a common structure Underneath the ‘grails-app’ directory there are sub-directories for “special” grails artifacts. Let’s look at a few
    • The domain subdirectory is for any class that you want to be persistent. These classes are automatically mapped to the DB through Hibernate
    • Grails will automatically create your database tables based on your domain classes using Hibernate’s hbm2ddl There are other ways to manage DB migrations, this is just the default
    • mysql> describe event; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | version | bigint(20) | NO | | NULL | | | event_date | datetime | NO | | NULL | | | title | varchar(255) | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) ! - the domain class name becomes the table name
    • mysql> describe event; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | version | bigint(20) | NO | | NULL | | | event_date | datetime | NO | | NULL | | | title | varchar(255) | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) ! - attribute names are converted into column names
    • mysql> describe event; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | version | bigint(20) | NO | | NULL | | | event_date | datetime | NO | | NULL | | | title | varchar(255) | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) - id (PK) and version (optimistic locking) columns are added to DB, but don’t need to be explicitly specified in code all of these defaults can be overridden through a mapping DSL or through explicit Hibernate configuration
    • The next couple examples are screen shots of the “Grails Console” - an interactive Swing console that is wired up with hibernate and all your spring beans and everything
    • Not only are the domain classes automatically mapped to the DB, Grails adds persistent methods like .save() - inserts or updates an object
    • .get(id) pass in the ID of a persistent object and hibernate will retrieve it
    • .list() select * from table
    • and last but not least, dynamic finders like “findByTitle”
    • and you can even add criteria like ‘EventDateLessThan’
    • how about a query using case insensitive ‘like’?
    • or a query using HQL?
    • or a query using criteria?
    • Zero All of this with: Zero - the amount of configuration and DAO lines of code you have to do to perform crud on a domain class.
    • Customer class Customer { ! Address address } Address Associations are also supported - you can have - one to one
    • class Customer { ! static hasMany = [incidents:Incident] } Customer Incident - one to many
    • class Customer { ! static hasMany = [products:Product] } class Product { static hasMany = [customers:Customer] static belongsTo = Customer //Customer owns the relationship } Customer Customer Product Product - many to many
    • Controllers are servlets in the Grails world. Any groovy class in this directory will have a url mapping by convention - no xml config required:
    • http://server/devjam/event/list name of application The context root of your app is the name of the application, in this case “devjam”
    • http://server/devjam/event/list name of controller The next part of a URL is the name of the controller
    • http://server/devjam/event/list name of action and the final part is the name of the action (which is a closure defined in the controller) These are the defaults - you can change URL mappings to your liking
    • http://server/devjam/event/list?max=10 Grails puts all the parameters coming in to a controller in to a map called ‘params’ - you can access them using ‘dot’ notation (like ‘params dot max’ to get the ‘max’ parameter)
    • Data Binding This is also fantastic for data binding - on a new object you can pass the ‘params’ map straight to a object constructor (thank you Groovy constructor convenience)
    • Dependency Injection Grails artifacts like controllers and services are created as spring beans - and grails autowires beans together by name. In the case, AuthenticateService will automatically be injected into the EventController - no config needed
    • Views are GSP (grails server pages) instead of JSPs
    • you can reference anything that is in the ‘model’ with ${} notation (like eventInstance)
    • there’s a convention for where the views go - by default views for the “EventController” go in the “views/event” subdirectory
    • Grails uses SiteMesh to decorate pages - so your GSPs are simple HTML
    • that have a layout applied to them
    • Demo Demo - build a simple Grails app to -list events (demo scaquot;olding) -create a new event (demo domain constraints) -allow users to RSVP to them (demo reloading of controller and dependency injection) -create RSS feed of events list (install and use feeds plugin)
    • If we had more time... • testing • tag libraries • services • plugins • content negotiation For reference in the handout: Testing: http://www.grails.org/Testing+Plugin Tag Libraries: http://grails.org/doc/1.0.x/guide/6.%20The%20Web%20Layer.html#6.3%20Tag%20Libraries Services: http://grails.org/doc/1.0.x/guide/8.%20The%20Service%20Layer.html Plugins: http://grails.org/Plugins Content Negotiation: http://grails.org/doc/1.0.x/guide/6.%20The%20Web%20Layer.html#6.8%20Content%20Negotiation
    • http://grails.org http://grails.org/doc/1.0.x/ Two resources: Grails.org website - great starting point - and a grails app itself Grails reference guide - excellent documentation of Grails
    • Two excellent books coming out very soon (early editions available from publisher now) GIA (May?): http://www.amazon.com/Grails-Action-Glen-Smith/ dp/1933988932/ DGG (Jan): http://www.amazon.com/Definitive-Guide-Grails- Second/dp/1590599950
    • Act III Act III: - when should you consider using these tools in an existing environment? - greenfield environment? - Where have they worked and where havenquot;t they? When should you consider using these tools in an existing environment?
    • The first question I ask is “Are you already a Java shop?”
    • http://flickr.com/photos/johnniewalker/359440369 If you are - then you already have the infrastructure you need to build and deploy applications with Groovy/Grails...
    • http://flickr.com/photos/philliecasablanca/2473728872 And you also have resources that understand Java
    • If your company/client is open source friendly
    • Then bringing Groovy into your existing environment is a piece of cake.
    • Learning Curve 100 75 50 25 0 * data for this chart is completely fabricated The learning curve for a new language might look like this
    • Learning Curve 100 75 50 25 0 * data for this chart is completely fabricated With Groovy, your Java developers will have a jump start on learning the language -the syntax is basically the same -all the Java APIs are available to you -can immediately be productive with the language and conveniences it provides
    • Integrating Grails into an existing environment may not be quite as easy
    • If you’re already using Hibernate for the ORM layer, then it’s possible. You can take your existing database, existing hibernate mapping files and Java domain classes and take advantage of all the features Grails has to oquot;er. (See “Grails In Action” book for using Grails to map the “Legacy Database from Hell”)
    • http://flickr.com/photos/13010608@N02/2441101135/ But where Grails really excels is in a green field
    • + + -If your team is familiar with Hibernate and Spring -Your process includes iterative development and a fast feedback loop -And testing is important
    • Then you should seriously be considering Grails for your next project
    • http://flickr.com/photos/kevint/85911467 Where has it worked?
    • 1 package com.piragua.groovy 2 3 import javax.servlet.http.* 4 import com.piragua.java.MyServlet 5 6 class MyServletTest extends GroovyTestCase { 7 8 Map params 9 Map session 10 11 def request 12 13 protected void setUp() { 14 params = [:] 15 session = [:] 16 def mockSession = [setAttribute: {k, v -> session[k] = v }] Unit Testing is a great way to start integrating Groovy into your code base - collections / xml / file convenience features reduce the amount of ceremony in your tests - can make mocking is easier (as shown in earlier groovy slides)
    • http://flickr.com/photos/nengard/82039595 “internal” apps are a great place for Grails - it’s very easy to develop a fully functional web app very quickly I built one at my last client in 12 hours (full user login, search, audit history and workflow task management)
    • There are tons of success stories for Grails (http://grails.org/ Success+Stories) Some very large, some smaller.
    • 200,000 1 Million $250/month users page views/month VPS Like this example - this Brazilian Entertainment website has 200k users, 1 million page views per month and runs on a $250/month VPS - no load balancing or major performance tuning Feb 2008 reference: http://www.nabble.com/Grails-1.0.1-is-out- td15548113.html
    • Linked in uses Grails for some of its sites for corporate customers http://blog.linkedin.com/2008/06/11/grails-at-linkedin/
    • Hot oquot; the press - a full case study is coming soon! wired.com/reviews is Grails powered and more of Wired.com is moving to Grails soon
    • http://flickr.com/photos/oxygenws/39895404 Where has it failed?
    • I have seen projects run into trouble when they don’t test enough. The dynamic nature of Groovy/Grails means that the compiler won’t find certain errors - you need good testing to mitigate this
    • XYZ Thing Too far outside the box For instance - one project that didn’t use the conventions that GORM provides and tried to roll their own persistence mechanism didn’t go so well.
    • I hope youquot;ve enjoyed the overview of Groovy/Grails and some thoughts to consider when choosing them
    • http://flickr.com/photos/thatblondegirl/467513888 Obviously, I’m drinking the Koolaid
    • But I’ve also been working with Groovy and Grails for almost 2 years and I’m still a happy camper.
    • I encourage you to go download Groovy or download Grails and walk through the “Getting Started” tutorials - and see how these new tools can help you be more equot;ective
    • Thank You