The Grails introduction workshop

474 views
359 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
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
474
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
15
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

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

×