Grails Launchpad - From Ground Zero to Orbit

Information about Grails Launchpad - From Ground Zero to Orbit

Published on December 10, 2017

Author: zak89s

Source: slideshare.net

Content

1. GRAILS LAUNCHPAD from Ground Zero to Orbit

2. ABOUT ME • Zachary Klein • Based in St Louis, MO • GrailsTeam at OCI • Developing with Grails since 2010 • Grails Profile, plugin, documentation author

3. guides.grails.org

4. start.grails.org

5. start.grails.org Create An Application Using The Latest Release curl -O start.grails.org/myProject.zip Create A Plugin Using The Latest Release curl -O start.grails.org/myPlugin.zip -d type=plugin Specify A Grails Version curl -O start.grails.org/myProject.zip -d version=3.2.5 Specify A Grails Profile curl -O start.grails.org/restPproject.zip -d profile=rest-api

6. HISTORY • Created in 2005 • Grails 3, based on Spring Boot, released in 2015 • Sponsored by OCI since 2015 • Grails 3.3 released in 2017

7. WHAT IS GRAILS? • Java web application framework • Based on Spring Boot • Follows Model-View-Controller pattern • Leverages proven technology • Convention-over-configuration • Modular plugin-based architecture • Prioritizes developer productivity

8. Model ControllerView User uses manipulatesupdates sees

9. • Extensive plugin library • Application Profiles • JSON views • Native multi-tenancy • Angular & React support WHAT IS GRAILS? Unique Features • JVM Platform • Spring & Spring Boot • Hibernate • Quartz • Gradle Proven Technology

10. FOUNDATIONS JavaVirtual Machine Java JDK Groovy JEE GORMBoot

11. SPRING BOOT • Rapid development for Spring-based applications • Convention-over-configuration • Embedded container • First-class metrics & monitoring • Custom “starters” for popular libraries & frameworks

12. SPRING BOOT ACTUATOR

13. SPRING BOOT ACTUATOR DEMO http://mrhaki.blogspot.com/2015/04/grails-goodness-adding-health-check.html https://objectpartners.com/2016/08/30/monitoring-grails-applications-the-easy-way/

14. GRAILS & SPRING BOOT Grails 3 for Spring Developers Screencast

15. GROOVY • Java-based, optionally-typed programming language • Can be dynamic or statically-compiled • Emphasizes developer-productivity • First-class DSL (domain-specific language) support • Supports multiple programming styles - OO, functional, runtime & compile-time meta-programming

16. public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World"); } } Java

17. println “Hello, World" Groovy

18. Java POJO public class Person { private String firstName; private String lastName; public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public String setLastName(String value) { this.lastName = value; } public void setFirstName(String value) { this.firstName = value; } }

19. Groovy POGO class Person { String firstName String lastName }

20. Groovy Closures Integer item = 0 String name = "My name" { item++ } { println it } { name -> println name } { String x, int y -> println "hey ${x} the value is ${y}" } { reader -> def line = reader.readLine() line.trim() }

21. Groovy Web Console

22. GORM • Groovy-based data access & persistence framework • Originally an ORM framework based on Hibernate • Supports MongoDB, Neo4J, Cassandra • Supports RxJava for Reactive applications • Supports multiple datasources

23. DATASOURCE CONFIG dataSource: pooled: true jmxExport: true driverClassName: org.h2.Driver username: sa password: environments: development: dataSource: dbCreate: create-drop url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE test: dataSource: dbCreate: update url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE production: dataSource: dbCreate: update url: jdbc:h2:prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE properties: jmxEnabled: true initialSize: 5 grails-app/conf/application.yml

24. DATASOURCE CONFIG dataSource: pooled: true jmxExport: true driverClassName: com.mysql.jdbc.Driver dialect: org.hibernate.dialect.MySQL5InnoDBDialect username: sa password: testing environments: development: dataSource: dbCreate: update url: jdbc:mysql://127.0.0.1:3306/myapp grails-app/conf/application.yml

25. MULTIPLE DATASOURCES dataSource: pooled: true jmxExport: true driverClassName: org.h2.Driver username: sa password: dataSources: lookup: dialect: org.hibernate.dialect.MySQLInnoDBDialect driverClassName: com.mysql.jdbc.Driver username: lookup password: secret url: jdbc:mysql://localhost/lookup dbCreate: update grails-app/conf/application.yml

26. DOMAIN CLASSES package org.grails.guides class Vehicle { String name String make String model static constraints = { name maxSize: 255 make inList: ['Ford', 'Chevrolet', 'Nissan'] model nullable: true } } grails-app/domain/demo/Vehicle.groovy

27. CONSTRAINTS Constraint Description Example blank Validates that a String value is not blank login(blank:false) creditCard Validates that a String value is a valid credit card number cardNumber(creditCard: true) email Validates that a String value is a valid email address. homeEmail(email: true) inList Validates that a value is within a range or collection of constrained values. name(inList: ["Joe"]) matches Validates that a String value matches a given regular expression. login(matches: "[a-zA-Z]+") max Validates that a value does not exceed the given maximum value. age(max: new Date()) price(max: 999F) maxSize Validates that a value’s size does not exceed the given maximum value. children(maxSize: 25) min Validates that a value does not fall below the given minimum value. age(min: new Date()) price(min: 0F) minSize Validates that a value’s size does not fall below the given minimum value. children(minSize: 25) notEqual Validates that that a property is not equal to the specified value login(notEqual: "Bob") nullable Allows a property to be set to null - defaults to false. age(nullable: true) range Uses a Groovy range to ensure that a property’s value occurs within a specified range age(range: 18..65) scale Set to the desired scale for floating point numbers (i.e. the number of digits to the right of the salary(scale: 2) http://gorm.grails.org/latest/hibernate/manual/index.html#constraints

28. CUSTOM CONSTRAINTS class Response { Survey survey Answer answer static constraints = { survey blank: false answer blank: false, validator: { val, Response obj -> val in obj.survey.answers } } }

29. ASSOCIATIONS package org.grails.guides class Model { String name static belongsTo = [ make: Make ] static constraints = { } String toString() { name } }

30. ASSOCIATIONS package org.grails.guides class Make { String name static hasMany = [ cars: Car ] static constraints = { } }

31. QUERYING def books = Book.list() def books = Book.list(offset:10, max:20) def books = Book.list(sort:"title", order:"asc") def book = Book.get(23) def book = Book.findByTitle(“Grails In Action") book = Book.findByTitleLike(“Groovy%") book = Book.findByReleaseDateBetween(firstDate, secondDate) book = Book.findByReleaseDateGreaterThan(someDate) book = Book.findByTitleLikeOrReleaseDateLessThan("%Something%", someDate)

32. QUERYING def query = Person.where { firstName == "Bart" } Person bart = query.find() //Note the query is “lazy” - it’s not instantiated until we actually call find(), list(), get() def results = Person.findAll { lastName == "Jeff" } def results = Person.findAll(sort:"firstName") { lastName == "Brown" } Person p = Person.find { firstName == "Bart" } def query = Person.where { (lastName != "Simpson" && firstName != "Fred") || (firstName == "Bart" && age > 9) } def results = query.list(sort:"firstName") http://gorm.grails.org/latest/hibernate/manual/index.html#querying

33. PERSISTENCE & UPDATES //Create def newPerson = new Person(name: “Person name”) newPerson.save() //Update def p = Person.get(1) p.name = “A New Name” p.save() //If you want to persist the change immediately: p.save(flush: true) //Delete p.delete() //or delete(flush:true)

34. DATA SERVICES • Interface-Based approach to persistence and querying logic • Introduced in GORM 6.1 • You define interfaces with methods that follow a naming convention • GORM will implement those methods • You can optionally override the implementation • Statically-compiled, type-checked, transaction-managed

35. DATA SERVICES @Service(Book) interface BookService { Book getBook(Serializable id) } class MyController { @Autowired BookService bookService def index() { render bookService.getBook(1) } } grails-app/services/demo/BookService.groovy src/main/groovy/demo/BookService.groovy src/main/groovy/demo/BookService.groovy http://gorm.grails.org/latest/hibernate/manual/index.html#savingAndUpdating

36. DATA SERVICES @Service(Book) interface BookService { List<Book> findBooks(String title, Map args) //args can supply pagination List<Book> findByTitleAndPublishDateGreaterThan(String title, Date publishDate) @Where({ title ==~ pattern && releaseDate > fromDate }) Book searchBooks(String pattern, Date fromDate) @Query("from $Book as book where book.title like $pattern") Book searchByTitle(String pattern) } grails-app/services/demo/BookService.groovy src/main/groovy/demo/BookService.groovy http://gorm.grails.org/latest/hibernate/manual/index.html#savingAndUpdating

37. DATA SERVICES @Service(Book) interface BookService { Book saveBook(String title) Book saveBook(Book newBook) Book updateBook(Serializable id, String title) @Query(“update ${Book book} set ${book.title} = $newTitle where book.title = $oldTitle") Number updateTitle(String newTitle, String oldTitle) Number deleteAll(String title) void delete(Serializable id) } grails-app/services/demo/BookService.groovy src/main/groovy/demo/BookService.groovy http://gorm.grails.org/latest/hibernate/manual/index.html#savingAndUpdating

38. Model ControllerView User uses manipulatesupdates sees

39. CONTROLLERS package demo class MyController { def index() { render “Hello world” } } grails-app/controllers/demo/MyController.groovy http://localhost:8080/my Hello world

40. CONTROLLERS package demo class MyController { def index() { [message: “Hello world”] } } grails-app/controllers/demo/MyController.groovy

41. VIEWS <html> <html> <head> <title>Home Page</title> </head> <body> <div> ${message} </div> </body> </html> grails-app/views/my/index.gsp

42. Model ControllerView User uses manipulatesupdates sees

43. start.grails.org

44. SDKMAN.IO

45. BUILDYOUR FIRST GRAILS APP http://guides.grails.org/ creating-your-first-grails-app

46. INTERCEPTORS • Interceptors allow you to add logic before/after a targeted request • Allow blocking or redirecting of a request • By default, interceptors will target requests made a controller of the same name • You can implement custom request “matching” in the constructor https://objectcomputing.com/resources/publications/sett/september-2015-grails-3-interceptors/

47. Model ControllerView User sees manipulatesupdates Interceptors Interceptors

48. package com.example class BookInterceptor {   boolean before() { true }   boolean after() { true }   void afterView() { } } grails-app/controller/com/example/BookInterceptor.groovy

49. class CustomInterceptor {   public CustomInterceptor() { // match all requests to the reporting controller... match controller: 'reporting'   //match requests to create action, person controller match controller: 'person', action: 'create'   //match all requests to accounting or payroll controller match controller: ~/(accounting|payroll)/ } boolean before() { true }   boolean after() { true }   void afterView() { /.../ } }

50. class CustomInterceptor {   int order = HIGHEST_PRECEDENCE + 100 //or LOWEST_PRECEDENCE boolean before() { true }   boolean after() { true }   void afterView() { /.../ } }

51. INTERCEPTORS Grails Quickcast #1 - Grails Interceptors

52. JSONVIEWS http://views.grails.org/latest/ • JSON views make it easy to express the desired format of your controller endpoints • Markup views are also available for expressing XML responses • JSON views are statically compiled, type-checked, and reload instantly

53. JSONVIEWS json.message { hello "world" } {"message":{ "hello":"world"}} grails-app/views/hello.gson Response:

54. JSONVIEWS model { Person person } json { name person.name age person.age } {“name": “John Doe”, “age”: 34} grails-app/views/person/_person.gson Response:

55. buildscript { ... dependencies { ... classpath "org.grails.plugins:views-gradle:1.2.6" } } ... apply plugin: "org.grails.grails-web" apply plugin: "org.grails.plugins.views-json" dependencies { ... compile "org.grails.plugins:views-json:1.2.6" In your build.gradle file:

56. model { Person person } json tmpl.person(person) grails-app/views/person/show.gson model { Person person } json { name person.name age person.age } grails-app/views/person/_person.gson

57. model { List<Person> people = [] } json tmpl.person(“person", people) grails-app/views/person/index.gson model { Person person } json { name person.name age person.age } grails-app/views/person/_person.gson

58. HAL+JSON http://www.cnblogs.com/coderland/p/5902997.html

59. model { Book book } json { hal.links(book) hal.embedded { author( book.authors.first() ) { Author author -> name author.name } } title book.title } grails-app/views/book/_book.json HAL+JSON

60. { "_links": { "self": { "href": "http://localhost:8080/book/show/1", "hreflang": "en", "type": "application/hal+json" } }, "_embedded": { "author": { "_links": { "self": { "href": "http://localhost:8080/author/show/1", "hreflang": "en", "type": "application/hal+json" } }, "name": "Stephen King" } }, "title": "The Stand" }

61. HAL+JSON http://guides.grails.org/using- hal-with-json-views/guide

62. JSONVIEWS Grails Quickcast #2 - JSONViews

63. SINGLE PAGE APPS

64. SINGLE PAGE APPS •GORM •Convention/Config •Spring Boot •Profiles •Plugins •Gradle •URL mappings •JSON views •Hypermedia •GORM for GraphQL •WebSockets

65. GRAILS PROFILES • Include default config, plugins, project structure • Custom commands/scripts for code-generation • Optional “features” allow further control of the generated project • Profile inheritance • Packaged/resolved as Maven dependencies

66. SPA GRAILS PROFILES angularjs Angular 1.x https://grails-profiles.github.io/angularjs/latest/ guide/index.html angular Angular 2+ https://grails-profiles.github.io/angular/latest/guide/ index.html react React 16.x https://grails-profiles.github.io/react/latest/guide/ index.html react-webpack React 16.x, using Webpack https://grails-profiles.github.io/react-webpack/ latest/guide/index.html webpack `Webpack 2.x, no JavaScript framework https://grails-profiles.github.io/webpack/latest/ guide/index.html

67. ANGULAR SCAFFOLDING https://grails-plugins.github.io/grails-angular-scaffolding/latest/ • Generate Angular controllers, services and views based on your domain model • Full CRUD functionality • Installed automatically in the Angular Profile

68. buildscript { ... dependencies { ... classpath "org.grails.plugins:angular-scaffolding:2.0.0.RC2" } } dependencies { ... compile "org.grails.plugins:angular-scaffolding:2.0.0.RC2" In your build.gradle file:

69. package demo import grails.rest.Resource @Resource(uri='/book') class Book { String title Integer pages Date publishDate String author static constraints = { } }

70. grails ng-generate-all demo.Book Rendered template service.ts to destination /client/src/app/book/book.service.ts Rendered template domain.ts to destination /client/src/app/book/book.ts Rendered template module.ts to destination /client/src/app/book/book.module.ts Rendered template routing.module.ts to destination /client/src/app/book/book-routing.module.ts Rendered template persist.component.ts to destination /client/src/app/book/book-persist.component.ts Rendered template persist.component.html to destination/client/src/app/book/book-persist.component.html Rendered template list.component.ts to destination /client/src/app/book/book-list.component.ts Rendered template list.component.html to destination /client/src/app/book/book-list.component.html Rendered template show.component.ts to destination /client/src/app/book/book-show.component.ts Rendered template show.component.html to destination /client/src/app/book/book-show.component.html Added Book as a dependency to your bootstrap module

71. ANGULAR SCAFFOLDING https://grails-plugins.github.io/grails-angular-scaffolding/latest/ Grails Quickcast #4 - AngularJS Scaffolding With Grails 3 DEMO

72. ANGULAR SCAFFOLDING Grails Quickcast #4 - AngularJS Scaffolding With Grails 3

73. REACT PROFILE • Create a React app backed by a RESTful Grails API • Uses the create-react-app CLI • Preconfigures CORS support • Provides working React components & test grails create-app myReactApp -profile react

74. REACT PROFILE https://grails-profiles.github.io/react/latest/guide/ DEMO

75. REACT PROFILE Grails Quickcast #8 - Grails React Profile

76. MULTI-TENANCY • GORM provides native support for multi-tenant applications • Multi-tenancy allows an application to service multiple clients (tenants) with isolated datasets • Three modes: • DATABASE - Separate databases for each tenant • SCHEMA - Single database, separate schema for each tenant • DISCRIMINATOR - Single database, with a discriminator column to distinguish between tenants

77. MULTI-TENANCY DATABASE SCHEMA DISCRIMINATOR

78. MULTI-TENANCY grails: gorm: multiTenancy: mode: DATABASE tenantResolverClass: org.grails.datastore.mapping.multitenancy.web.SessionTenantResolver

79. MULTI-TENANCY SessionTenantResolver Resolves the tenant id from the HTTP session using an attribute called gorm.tenantId CookieTenantResolver Resolves the tenant id from the HTTP cookie using an attribute called gorm.tenantId SubDomainTenantResolver Resolves the tenant id from the current sub-domain. For example if the subdomain is foo.mycompany.com, the tenant id would be foo SystemPropertyTenantResolver Resolves the tenant id from a system property called gorm.tenantId. Mainly useful for testing

80. package example import grails.gorm.MultiTenant class Vehicle implements MultiTenant<Vehicle> { String model Integer year static hasMany = [engines: Engine] static constraints = { model blank:false year min:1980 } }

81. package example import grails.gorm.MultiTenant class Vehicle implements MultiTenant<Vehicle> { String model Integer year String manufacturer static hasMany = [engines: Engine] static constraints = { model blank:false year min:1980 } static mapping = { tenantId name:'manufacturer' } }

82. import grails.gorm.multitenancy.* // resolve the current tenant for every method @CurrentTenant class TeamService { // execute the countPlayers method without a tenant id @WithoutTenant int countPlayers() { Player.count() } // use the tenant id "another" for all GORM logic within the method @Tenant({"another"}) List<Team> allTwoTeams() { Team.list() } List<Team> listTeams() { Team.list(max:10) } @Transactional void addTeam(String name) { new Team(name:name).save(flush:true) } }

83. import grails.gorm.multitenancy.* // resolve the current tenant for every method @CurrentTenant class TeamService { // execute the countPlayers method without a tenant id @WithoutTenant int countPlayers() { Player.count() } // use the tenant id "another" for all GORM logic within the method @Tenant({"another"}) List<Team> allTwoTeams() { Team.list() } List<Team> listTeams() { Team.list(max:10) } @Transactional void addTeam(String name) { new Team(name:name).save(flush:true) } }

84. MULTI-TENANCY GRAILS GUIDES Discriminator perTenant Guide Database perTenant Guide Custom JWTTenant Resolver Guide Dynamic Datasources Multi- tenancy Guide

85. GRAPHQL

86. GRAPHQL • Allows JavaScript components to declaratively indicate their data requirements • GraphQL consists of a server-side schema + client operations • Queries: specify the required inputs/outputs of a request • Mutations: specify create/update/delete operations against the GraphQL schema. • GORM GraphQL plugin generates a GraphQL schema for domain classes

87. GRAPHQL https://medium.freecodecamp.org/so-whats-this-graphql-thing-i-keep-hearing-about-baf4d36c20cf?gi=e256cd305c64

88. QUERIES //List speaker ids query { speakerList(max: 10) { id } } //Return total speakers query { speakerCount } //Retrieve speaker details by id query { speaker(id: 1) { firstName lastName bio } } //Return list of talks with speaker details embedded query { talkList(max:10) { title speaker { firstName lastName } } }

89. MUTATIONS //Update speaker by id, return any error messages mutation { speakerUpdate(id: 1, speaker: { bio: "Updated bio!" }) { id bio errors { field message } } } //Delete speaker by id mutation { speakerDelete(id: 2) { error } } //Create speaker mutation { speakerCreate(speaker: { firstName: "James" lastName: "Kleeh" }) { id firstName lastName errors { field message } } }

90. GORM FOR GRAPHQL https://grails.github.io/gorm-graphql/snapshot/guide compile “org.grails.plugins:gorm-graphql:1.0.0.BUILD-SNAPSHOT” package demo class Book { String title Integer pages Date publishDate Author author static graphql = true } In your build.gradle file: In your domain class:

91. GORM, GRAPHQL, REACT & APOLLO GUIDE https://tinyurl.com/GormGraphQLReact Step-by-step guide to building a GraphQL backend using Grails, with a React frontend Soon to be published at: http://guides.grails.org/gorm-graphql-with-react-and-apollo/guide

92. SUMMARY • Grails core framework (MVC, data access/persistence) • Spring Boot interoperability (Actuator) • Advanced request handling (Interceptors) • Expressive JSON rendering (JSON Views) • SPA support for Angular & React (and others) • Native Multi-tenancy support via GORM • Effortless GraphQL support via GORM

93. SUMMARY • Grails is alive and well! • The frameworks offers a suite of unique and compelling features that go above and beyond the competition • Developer-productivity is the #1 benefit of Grails • The Grails community is vibrant, engaged and active • Head to start.grails.org and start your new Grails project!

94. THANKYOU [email protected]

Related presentations


Other presentations created by zak89s

Shields Up! Securing React Apps
10. 12. 2017
0 views

Shields Up! Securing React Apps

Groovy for Java Devs
08. 03. 2019
0 views

Groovy for Java Devs

Grails 4: Upgrade your Game!
01. 10. 2020
0 views

Grails 4: Upgrade your Game!