Contenu connexe
Similaire à GraphQL y Groovy (11)
Plus de Mario García (15)
GraphQL y Groovy
- 2. #madridGUG @marioggar © Mario Garcia 2018
Me presento
Nombre
Mario Garcia
Redes Sociales:
https://twitter.com/marioggar
https://github.com/mariogarcia
2 . 1
- 4. #madridGUG @marioggar © Mario Garcia 2018
Os interesa GraphQL porque…
He oido que GraphQL es lo que esta de moda
Estoy harto de hacer REST
Me aburria y he venido a pasar el rato
Sea lo que sea…
3 . 1
- 7. #madridGUG @marioggar © Mario Garcia 2018
Indice
GraphQL en general
GraphQL como lenguaje de consultas
GraphQL + Ratpack/Grails
Conclusiones
4 . 2
- 9. #madridGUG @marioggar © Mario Garcia 2018
Que es GraphQL ?
Es un lenguaje de consultas
Usa un sistema de tipos para de nir esas consultas
5 . 2
- 10. #madridGUG @marioggar © Mario Garcia 2018
Que NO es GraphQL
No es un web framework
No tiene que ver necesariamente con HTTP
Y desde luego…
GraphQL no es REST
5 . 3
- 13. #madridGUG @marioggar © Mario Garcia 2018
Lo primero
Mientras que REST es buenas practicas + HTTP
GraphQL es SOLO un lenguaje de consulta
5 . 6
- 15. #madridGUG @marioggar © Mario Garcia 2018
Recursos vs Consultas
Rest: 1 URI ⇒ 1 recurso
GraphQL: 1 URI ⇒ N consultas
5 . 8
- 18. #madridGUG @marioggar © Mario Garcia 2018
Manejo de errores
Rest ⇒ HTTP codes
GraphQL error messages in responses
5 . 11
- 19. #madridGUG @marioggar © Mario Garcia 2018
Tipo de Aplicaciones
Rest == HTTP
GraphQL puede usarse con: HTTP, JDBC, AMQP…etc
5 . 12
- 20. #madridGUG @marioggar © Mario Garcia 2018
Documentacion
Rest ⇒ varias implementaciones, no hay especi cacion
(destaca Swagger)
GraphQL ⇒ Todos los motores GraphQL exponen el
esquema de la misma manera
5 . 13
- 21. #madridGUG @marioggar © Mario Garcia 2018
Front-End friendly
Rest ⇒ Back a veces no puede ir a la velocidad que
demanda el front
GraphQL ⇒ Mucha mas exibilidad del back para dar
respuesta al front
5 . 14
- 23. #madridGUG @marioggar © Mario Garcia 2018
Resumiendo
1 solo endpoint
Deja que nos concentremos solo en la consulta
Granularidad en la carga de datos
Documentacion out-of-the-box
5 . 16
- 24. #madridGUG @marioggar © Mario Garcia 2018
El ejemplo
Peliculas de James Bond
Aunque ahora el client SOLO sera el navegador…
Los conceptos nos serviran para cualquier tipo de cliente
5 . 17
- 26. #madridGUG @marioggar © Mario Garcia 2018
Pasos para ejecutar una
consulta
De nir TIPOS
De nir CONSULTAS
Ejecutar consultas contra el esquema
6 . 2
- 28. #madridGUG @marioggar © Mario Garcia 2018
Primer ejemplo: SCHEMA
type Film {
title: !String
year: Int
}
type Queries {
lastFilm: Film
filmByYear(year: Int): Film
}
schema {
query: Queries
}
http://facebook.github.io/graphql/
6 . 4
- 29. #madridGUG @marioggar © Mario Garcia 2018
Primer ejemplo: TIPOS
El cliente PUEDE agregar/omitir tantos campos opcionales
como quiera
El cliente DEBE agregar los campos obligatorios en la
consulta
type Film {
title: String!
year: Int
}
6 . 5
- 30. #madridGUG @marioggar © Mario Garcia 2018
Primer ejemplo : CONSULTAS
Las consultas siempre usan tipos y escalares
Las consultas puede requerir argumentos
type Queries {
lastFilm: Film
filmByYear(year: Int): Film
}
6 . 6
- 31. #madridGUG @marioggar © Mario Garcia 2018
Primer ejemplo : EJECUCION
query: "give me the last James Bond lm with its title
result: "SPECTRE"
{
lastFilm {
title
}
}
{
"data": {
"lastFilm": {
"title": "SPECTRE"
}
}
}
6 . 7
- 32. #madridGUG @marioggar © Mario Garcia 2018
Mirando un poco mas de cerca
query
1. lastFilm: Es la consulta en la que estoy interesado
2. title: Es un campo especi co del tipo que se devuelve
(Film)
{
lastFilm { (1)
title (2)
}
}
6 . 8
- 33. #madridGUG @marioggar © Mario Garcia 2018
Validacion
title es obligatorio
Consulta invalida
type Film {
title: String!
year: Int
}
{
lastFilm
}
6 . 9
- 36. #madridGUG @marioggar © Mario Garcia 2018
GraphQL DSL (GQL)
DSL sobre GraphQL-Java
Todavia alpha
Se agradece Feeback :)
https://github.com/grooviter/gql
6 . 12
- 37. #madridGUG @marioggar © Mario Garcia 2018
Groovy time: TIPOS
GraphQL
Groovy
type Film {
title: String!
year: Int
}
static GraphQLObjectType Film = DSL.type('Film') {
field 'title', nonNull(GraphQLString)
field 'year', GraphQLInt
}
6 . 13
- 38. #madridGUG @marioggar © Mario Garcia 2018
Groovy time: CONSULTAS
type Queries {
lastFilm: Film
filmByYear(year: Int): Film
}
schema {
query: Queries
}
return DSL.schema {
queries('Queries') {
field('lastFilm') {
type Types.Film
fetcher(Queries.&findLastFilm) // from db
}
field('filmByYear') {
type Types.Film
fetcher(Queries.&findByYear) // from db
argument 'year', GraphQLString
}
}
}
6 . 14
- 39. #madridGUG @marioggar © Mario Garcia 2018
Groovy time: TEST
query
ejecucion
queryString = '''
{
lastFilm {
year
title
}
}
'''
def result = DSL
.execute(schema, queryString)
.data as Map<String,Object>
6 . 15
- 40. #madridGUG @marioggar © Mario Garcia 2018
Groovy time: EJECUCION (II)
ejecucion
when: 'executing the query'
def result = DSL
.execute(schema, queryString)
.data as Map<String,Object>
then: 'we should get the expected movie'
result == [lastFilm: [year: 2015, title: 'SPECTRE']]
where: 'the queryString literal is'
queryString = '''
{
lastFilm {
year
title
}
}
'''
6 . 16
- 42. #madridGUG @marioggar © Mario Garcia 2018
Pelicula de 1962 ?
consultas
ejecucion de consultas
queryString = '''
query FindBondFilmByYear($year: String){
filmByYear(year: $year) {
year
title
}
}
'''
def result = DSL
.execute(schema, queryString, [year: year])
6 . 18
- 44. #madridGUG @marioggar © Mario Garcia 2018
Sobre consultas & mutaciones
Consultas suelen poder ejecutarse en batch
Consultas suelen poder ejecutarse en paralelo
Mutaciones se ejecutan de manera secuencial
6 . 20
- 45. #madridGUG @marioggar © Mario Garcia 2018
Agregacion de consultas
varias consultas a la vez
queryString = '''
query Home($year: String){
filmByYear(year: $year) {
year
title
}
lastFilm {
title
year
}
}
'''
6 . 21
- 50. #madridGUG @marioggar © Mario Garcia 2018
Tipo Film
static GraphQLObjectType Film = DSL.type('Film') {
field 'title', nonNull(GraphQLString)
field 'year', GraphQLInt
}
7 . 4
- 51. #madridGUG @marioggar © Mario Garcia 2018
Consultas
return DSL.schema {
queries('Queries') {
field('lastFilm') {
type Types.Film
fetcher(Queries.&findLastFilm) // from db
}
field('filmByYear') {
type Types.Film
fetcher(Queries.&findByYear) // from db
argument 'year', GraphQLString
}
}
}
7 . 5
- 52. #madridGUG @marioggar © Mario Garcia 2018
Ratpack Handler
@Override
void handle(Context ctx) throws Exception {
def payload = ctx.get(Map)
def query = payload.query
def params = payload.variables as Map<String,Object>
Blocking.get {
execute(schema, "$query", params)
}.then { ExecutionResult result ->
ctx.render(json(errors: result.errors, data: result.data))
}
}
7 . 6
- 53. #madridGUG @marioggar © Mario Garcia 2018
Uri mapping
1. GraphQL endpoint
2. GraphiQL
prefix('graphql') {
post(Handler) // GraphQL
}
files {
dir('static').indexFiles('index.html') // GraphiQL
}
7 . 7
- 56. #madridGUG @marioggar © Mario Garcia 2018
GORM GraphQL
https://grails.github.io/gorm-graphql/latest/guide/index.html
7 . 10
- 58. #madridGUG @marioggar © Mario Garcia 2018
Por que Grails/GORM ?
GORM ❤ SQL/NoSQL Databases
Entidades Gorm = Tipos/Queries/Mutations GraphQL
GraphiQL out-of-the-box
Plugin Grails 3 / Standalone
7 . 12
- 59. #madridGUG @marioggar © Mario Garcia 2018
Mapear tipos
class Film {
static graphql = true // exposed via GraphQL
String title
Integer year
static constraints = {
year nullable: false // GraphQL validation
}
}
7 . 13
- 61. #madridGUG @marioggar © Mario Garcia 2018
Type Operation
Query lm(id: ..)
Query lmList(max: .., sort: .., etc)
Query lmCount
Mutation lmCreate( lm: {})
Mutation lmUpdate(id: .., lm: {})
Mutation lmDelete(id: ..)
7 . 15
- 62. #madridGUG @marioggar © Mario Garcia 2018
Custom Queries
import org.grails.gorm.graphql.entity.dsl.GraphQLMapping
class Film {
static graphql = GraphQLMapping.build {
query('lastFilm', Film) {
dataFetcher { env ->
Film.last(sort: "year")
}
}
}
String title
Integer year
static constraints = {
year nullable: false
}
7 . 16
- 63. #madridGUG @marioggar © Mario Garcia 2018
Grail & Spring
Puedes acceder a cualquier bean en un fetcher
Por ejemplo springSecurityService
fetcher { env ->
env.context.springSecurityService
}
7 . 17
- 64. #madridGUG @marioggar © Mario Garcia 2018
Ademas
Se puede optimizar la forma en la que se realizan las
consultas
Se pueden elegir como serializar los datos escalares
(Fechas, monedas…)
7 . 18
- 66. #madridGUG @marioggar © Mario Garcia 2018
Optimizaciones en las consultas
Recuerda que cada propiedad del modelo puede tener su
propio fetcher
Eso deberia hacer que se pudieran optimizar las consultas
8 . 2
- 67. #madridGUG @marioggar © Mario Garcia 2018
Instrumentacion/Interceptor
Interceptan la ejecucion por diferentes motivos
Autorizar
Logear
Lanzar cosas en background
8 . 3
- 68. #madridGUG @marioggar © Mario Garcia 2018
Seguridad
Depende de lo que estes utilizando
HTTP ⇒ JWT esta de moda
8 . 4
- 69. #madridGUG @marioggar © Mario Garcia 2018
Relay
Buenas practicas con GraphQL
Implementadas como especi cacion en una biblioteca JS
https://facebook.github.io/relay/
8 . 5
- 70. #madridGUG @marioggar © Mario Garcia 2018
Relay
Paginacion (restrictiva)
Identi cadores (hashing)
Uso de HTTP (cache por ejemplo)
…
http://graphql.org/learn/best-practices/
8 . 6
- 72. #madridGUG @marioggar © Mario Garcia 2018
Conclusiones
GraphQL no tiene que ser un sustituto 1 - 1 de REST pero…
Es una mejora en la comunicacion con el front-end
Front ❤ Back
8 . 8