Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
GRAILS
N00B TO NINJA IN 3 HOURS
[INTRODUCTION WORKSHOP]
/BrianJohnsen @brianjohnsendk
WHOAMI
(whocares)
Brian Johnsen, GennemtænktITA/S
12+ years Java
Groovy&Grails since 2008
Your FriendlyNeighborhood GR8Con...
READY?
1. Copygrails installto disk and unzip
2. Add to path
3. Voilá
$grails-version
Grailsversion:2.3.8
FULL STACK FRAMEWORK
ORM (GORM)
Powerfulview technology(GSP) and easyTagLib creation
DependencyInjection and on-the-flyrel...
ARCHITECTURE
PHILOSOPHY
LETS GET STARTED!
DEMO TIME!
CLI and create app demo
YOUR TURN!
Itjustgoes on...
CLI
Tryitout
$grailshelp
CREATE THE APP
$grailscreate-appgrailsdemo
$cdgrailsdemo
$grailsrun-app
|Serverrunning.Browsetohttp://localhost:8080/grail...
RUNNING APPLICATION!
ANATOMY
ANATOMY
grails-app-TopleveldirectoryforGroovysources
conf-Configurationsources.
controllers-Webcontrollers-TheCinMVC.
doma...
DON'T LET FRIENDS FORK
Open:
/grails-app/conf/BuildConfig.groovy
Change:
grails.project.fork=[
//configuresettingsforcompi...
DOMAIN
/grails-app/domain/
The M in MVC
Gets mapped to the database
Dynamic finders FTW -> ForgetSQL
constraintsenforce da...
DOMAIN DEMO!
MY FIRST DOMAIN CLASS
$grailscreate-domain-classPerson
//grails-app/domain/Person.groovy
classPerson{
Stringname
Integerag...
SAVE AND VALIDATE
constraintsare enforced on save()and validate()
defperson=newPerson(age:42,name:'DouglasAdams')
person.v...
WHOLE LOTTA DYNAMIC GOIN’ ON
Finders are dynamicallycreated for allproperties
defeverybody=Person.list()
deftheOne=Person....
TESTING
/test/unit/
Spock Specifications
Deeplyintegrated in Grails
When creatinganyartifactacorrespondingtestis created
C...
TEST DEMO!
SPOCK TEST DEFAULT
//test/unit/grailsdemo/PersonSpec.groovy
@TestFor(Person)
classPersonSpecextendsSpecification{
defsetup...
WRITE A TEST!
"age should be more than 0"
COULD LOOK LIKE THIS
//test/unit/grailsdemo/PersonSpec.groovy
@TestFor(Person)
classPersonSpecextendsSpecification{
void"a...
TESTING
- THE EASIEST WAY TO EXECUTE CODE!
Playwith dynamic finders
TAKING CONTROL
/grails-app/controllers/
The C in MVC
Databinding
Redirectingrequests
Delegatingto business logic
HIM AGAIN!
Scaffolded UI Demo
SCAFFOLDED CONTROLLER
//grails-app/controllers/grailsdemo/PersonController.groovy
classPersonController{
staticscaffold=tr...
STOP THE PRESSES
IT'S BACKED BY A REAL DATABASE!
Browse to http://localhost:8080/demo/dbconsole
WANT SOME REST?
AUTOMATIC CONTENT NEGOTIATION
http://localhost:8080/demo/person/show/1.json
{
class:"grailsdemo.Person",
id:1,
age:41,
nam...
BACK ON TRACK
GENERATE CONTROLLER
$grailsgenerate-controllergrailsdemo.Person
ALL THAT CODE
Open:
grails-app/controllers/grailsdemo/PersonController.groovy
SOMETHING LIKE THIS?
//grails-app/controllers/grailsdemo/PersonController.groovy
@Transactional(readOnly=true)
classPerson...
TESTING CONTROLLERS
Run:
$grailstest-appunit:PersonController
Whathappens?
Open:
/test/unit/grailsdemo/PersonControllerSpe...
TESTING CONTROLLERS
Change:
defpopulateValidParams(params){
assertparams!=null
//TODO:Populatevalidpropertieslike...
//par...
MORE TESTING
Do we have the time?
VIEWS
/grails-app/views/
The Vin MVC
GSP
GENERATE VIEWS
$grailsgenerate-allgrailsdemo.Person
THE INDEX VIEW
Open:
grails-app/views/person/index.gsp
THE SHOW VIEW
Open:
grails-app/views/person/show.gsp
CREATE AND EDIT VIEWS - TEMPLATES
Open:
grails-app/views/person/create.gsp
grails-app/views/person/edit.gsp
grails-app/vie...
SERVICES
/grails-app/services/
Should contain allbusiness logic
Transactional
Injected into anyartefact
CREATE THE SERVICE
$grailscreate-servicePerson
Open:
grails-app/services/demo/PersonService.groovy
UPDATE THE SERVICE
@Transactional
classPersonService{
defgetAll(){
Person.list()
}
}
UPDATE THE CONTROLLER
classPersonController{
PersonServicepersonService//injectedbygrails
defindex(Integermax){
respondper...
LETS ADD A NEW FEATURE
Person should have country
//grails-app/domain/Person.groovy
classPerson{
Stringname
Integerage
Str...
UPDATE THE TESTS
Open:
test/unit/grailsdemo/PersonSpec.groovy
UPDATE THE VIEW
Open:
grails-app/views/person/index.gsp
and:
grails-app/views/person/_form.gsp
ANOTHER NEW FEATURE
Creatinganew person should send you to the listview (index)
Open:
grails-app/controllers/grailsdemo/Pe...
PLUGINS
https://grails.org/plugins/
Build TestData
Searchable
Quartz
SpringSecurity
MongoDB
and itgoes on and on...
The Grails introduction workshop
The Grails introduction workshop
Upcoming SlideShare
Loading in …5
×

The Grails introduction workshop

603 views

Published on

Grails is a complete web application framework that runs on the Java JVM. It is a full-stack framework, and handles all layers from the user interface to the persistence layer. Grails is based on known and proven technologies, such as the Spring Framework and Hibernate. It has been around since 2006, and has made considerable progress around the globe in the past few years.

This workshop aims to show how to get from 0 to running application with Grails in three hours - so hold on to your hats! We will touch the following points:

Grails application structure
Domain model and persistence
Controllers
Services
Testing
User Interface

Published in: Technology
  • Be the first to comment

The Grails introduction workshop

  1. 1. GRAILS N00B TO NINJA IN 3 HOURS [INTRODUCTION WORKSHOP] /BrianJohnsen @brianjohnsendk
  2. 2. WHOAMI (whocares) Brian Johnsen, GennemtænktITA/S 12+ years Java Groovy&Grails since 2008 Your FriendlyNeighborhood GR8Conf Organizer
  3. 3. READY? 1. Copygrails installto disk and unzip 2. Add to path 3. Voilá $grails-version Grailsversion:2.3.8
  4. 4. FULL STACK FRAMEWORK ORM (GORM) Powerfulview technology(GSP) and easyTagLib creation DependencyInjection and on-the-flyreloading(Spring) Internationalization support(i18n) Runtime Container (Tomcat) TestingFramework (Spock) Plugin System Command line tools Build Tool(Gant/Gradle) and abunch of other stuff…
  5. 5. ARCHITECTURE
  6. 6. PHILOSOPHY
  7. 7. LETS GET STARTED!
  8. 8. DEMO TIME! CLI and create app demo
  9. 9. YOUR TURN!
  10. 10. Itjustgoes on... CLI Tryitout $grailshelp
  11. 11. CREATE THE APP $grailscreate-appgrailsdemo $cdgrailsdemo $grailsrun-app |Serverrunning.Browsetohttp://localhost:8080/grailsdemo Openyourfavoritebrowserandcheckitout!
  12. 12. RUNNING APPLICATION!
  13. 13. ANATOMY
  14. 14. ANATOMY grails-app-TopleveldirectoryforGroovysources conf-Configurationsources. controllers-Webcontrollers-TheCinMVC. domain-Theapplicationdomain-TheMinMVC. i18n-Supportforinternationalization(i18n). migrations-Databasemigration. services-Theservicelayer. taglib-Taglibraries. utils-Grailsspecificutilities. views-GroovyServerPages-TheVinMVC. scripts-Gantscripts. src-Supportingsources groovy-OtherGroovysources java-OtherJavasources test-Unitandintegrationtests. web-app-JavaScriptandCSS. wrapper-Wrapper.
  15. 15. DON'T LET FRIENDS FORK Open: /grails-app/conf/BuildConfig.groovy Change: grails.project.fork=[ //configuresettingsforcompilationJVM,notethatifyoualtertheGroovyversion ... ... //configuresettingsfortheConsoleUIJVM console:[maxMemory:768,minMemory:64,debug:false,maxPerm:256] ] To: grails.project.fork=false
  16. 16. DOMAIN /grails-app/domain/ The M in MVC Gets mapped to the database Dynamic finders FTW -> ForgetSQL constraintsenforce database consistency Defines scaffolded views
  17. 17. DOMAIN DEMO!
  18. 18. MY FIRST DOMAIN CLASS $grailscreate-domain-classPerson //grails-app/domain/Person.groovy classPerson{ Stringname Integerage staticconstraints={ nameblank:false agemin: 0 } }
  19. 19. SAVE AND VALIDATE constraintsare enforced on save()and validate() defperson=newPerson(age:42,name:'DouglasAdams') person.validate()//onlychecksconstraints person.save()//savestheinstancetothedatabase
  20. 20. WHOLE LOTTA DYNAMIC GOIN’ ON Finders are dynamicallycreated for allproperties defeverybody=Person.list() deftheOne=Person.findByNameAndAge('Brian',41) defcaseInsensitive=Person.findAllByNameIlike('graeme') defunderAge=Person.findAllByAgeLessThan(18) defseniors=Person.findAllByAgeGreaterThanEquals(65) deforderedByName=Person.listOrderByName()
  21. 21. TESTING /test/unit/ Spock Specifications Deeplyintegrated in Grails When creatinganyartifactacorrespondingtestis created CreatingPersonalso creates aPersonSpec
  22. 22. TEST DEMO!
  23. 23. SPOCK TEST DEFAULT //test/unit/grailsdemo/PersonSpec.groovy @TestFor(Person) classPersonSpecextendsSpecification{ defsetup(){ } defcleanup(){ } void"testsomething"(){ } }
  24. 24. WRITE A TEST! "age should be more than 0"
  25. 25. COULD LOOK LIKE THIS //test/unit/grailsdemo/PersonSpec.groovy @TestFor(Person) classPersonSpecextendsSpecification{ void"ageshouldbemorethan0"(){ when: defperson= newPerson(age:age,name:'joe') then: person.validate()==valid where: age |valid 0 | true 41 | true -1 | false } }
  26. 26. TESTING - THE EASIEST WAY TO EXECUTE CODE! Playwith dynamic finders
  27. 27. TAKING CONTROL /grails-app/controllers/ The C in MVC Databinding Redirectingrequests Delegatingto business logic
  28. 28. HIM AGAIN! Scaffolded UI Demo
  29. 29. SCAFFOLDED CONTROLLER //grails-app/controllers/grailsdemo/PersonController.groovy classPersonController{ staticscaffold=true } Fire itup and give itaspin $grailsrun-app
  30. 30. STOP THE PRESSES IT'S BACKED BY A REAL DATABASE! Browse to http://localhost:8080/demo/dbconsole
  31. 31. WANT SOME REST?
  32. 32. AUTOMATIC CONTENT NEGOTIATION http://localhost:8080/demo/person/show/1.json { class:"grailsdemo.Person", id:1, age:41, name:"Brian" } http://localhost:8080/demo/person/show/1.xml <personid="1"> <age>41</age> <name>Brian</name> </person>
  33. 33. BACK ON TRACK
  34. 34. GENERATE CONTROLLER $grailsgenerate-controllergrailsdemo.Person
  35. 35. ALL THAT CODE Open: grails-app/controllers/grailsdemo/PersonController.groovy
  36. 36. SOMETHING LIKE THIS? //grails-app/controllers/grailsdemo/PersonController.groovy @Transactional(readOnly=true) classPersonController{ staticallowedMethods=[save:"POST",update:"PUT",delete:"DELETE"] defindex(Integermax){ params.max=Math.min(max?:10,100) respondPerson.list(params),model:[personInstanceCount:Person.count()] } defshow(PersonpersonInstance){ respondpersonInstance } ... ... }
  37. 37. TESTING CONTROLLERS Run: $grailstest-appunit:PersonController Whathappens? Open: /test/unit/grailsdemo/PersonControllerSpec.groovy
  38. 38. TESTING CONTROLLERS Change: defpopulateValidParams(params){ assertparams!=null //TODO:Populatevalidpropertieslike... //params["name"]='someValidName' } To: defpopulateValidParams(params){ assertparams!=null params["name"]='joe'//orwhatever params["age"]=42//orwhatever }
  39. 39. MORE TESTING Do we have the time?
  40. 40. VIEWS /grails-app/views/ The Vin MVC GSP
  41. 41. GENERATE VIEWS $grailsgenerate-allgrailsdemo.Person
  42. 42. THE INDEX VIEW Open: grails-app/views/person/index.gsp
  43. 43. THE SHOW VIEW Open: grails-app/views/person/show.gsp
  44. 44. CREATE AND EDIT VIEWS - TEMPLATES Open: grails-app/views/person/create.gsp grails-app/views/person/edit.gsp grails-app/views/person/_form.gsp
  45. 45. SERVICES /grails-app/services/ Should contain allbusiness logic Transactional Injected into anyartefact
  46. 46. CREATE THE SERVICE $grailscreate-servicePerson Open: grails-app/services/demo/PersonService.groovy
  47. 47. UPDATE THE SERVICE @Transactional classPersonService{ defgetAll(){ Person.list() } }
  48. 48. UPDATE THE CONTROLLER classPersonController{ PersonServicepersonService//injectedbygrails defindex(Integermax){ respondpersonService.getAll() } ... }
  49. 49. LETS ADD A NEW FEATURE Person should have country //grails-app/domain/Person.groovy classPerson{ Stringname Integerage Stringcountry staticconstraints={ nameblank:false age min:0 countrynullable:true } }
  50. 50. UPDATE THE TESTS Open: test/unit/grailsdemo/PersonSpec.groovy
  51. 51. UPDATE THE VIEW Open: grails-app/views/person/index.gsp and: grails-app/views/person/_form.gsp
  52. 52. ANOTHER NEW FEATURE Creatinganew person should send you to the listview (index) Open: grails-app/controllers/grailsdemo/PersonController.groovy
  53. 53. PLUGINS https://grails.org/plugins/ Build TestData Searchable Quartz SpringSecurity MongoDB and itgoes on and on...

×