SlideShare a Scribd company logo
GraphQL with Sangria
Scala Implementation
About Me
Anthony SSI YAN KAI
● Data Engineer at ebiznext
○ Formation BI
○ DataLake (creation, enriching)
○ FullStack (react.js - scala)
Scala - Spark - Hadoop - ElasticSearch - Kafka - Akka - GraphQL
What is GraphQL all about ?
GraphQL is a query language for APIs
Created to answer those problematics :
● Mobile usage:
○ Sloppy networks and low-powered devices
○ Reduce the amount of data transferred over network
● Large variety of clients:
○ Classic API can hardly fit every clients needs in a maintainable way
○ Each client accesses the data it needs with a single endpoint
● Fast development
○ Classic REST APIs regularly needs to update the way data is exposed (multiple endpoints,
etc…)
○ Less communication between frontend and backend
REST vs GraphQL
The major paradigm variation:
REST imposes a fixed data structure to the client
while …
GraphQL allow clients to fetch the data they need
Instead of multiple endpoints that returns fixed data structures, GraphQL provides an unique endpoint that
returns the data asked by the client
Fetching data with GraphQL can be done in a single query while in REST multiples queries are often
needed and more unnecessary data is transferred.
For more GraphQL vs REST: www.howtographql.com
Architecture
GraphQL can be plugged to basically anything ...
● Database
● Legacy systems
● Microservice
● Third-party API
● Anything ...
resources: www.howtographql.com
Use Case
id: String
title: String,
description: Option[String]
genres: Seq[Genre.Value]
actors: Seq[Actor]
rating: Option[Double]
reviews: Seq[Review]
budget: Long
gross: Seq[Long]
id: String,
fullname: String
popularity: Option[Int]
movies: Seq[Movie]
Expose data for a movie application
case class Movie
case class Actor
id: String = UUID.randomUUID().toString,
author: String,
content: String,
rating: Double,
created: Long = Instant.now.toEpochMilli
case class Review
Scenario
We want to fetch this data:
● Movie Title - Genres - Rating - Description
● Top 3 most popular actors in the movie
● Last 5 reviews about the movie
The Avengers Top 3 Actors
Last 5 Reviews
Action,Adventure, Sci-Fi
Rating: 8.1
Description:
When Loki returns and
threatens to steal the ..
Robert D. Scarlett J. Chris E.
Scenario with REST
1
{
"movie": {
"id": "001",
"title": "The Avengers"
"genres": [ACTION","ADVENTURE","SCI_FI"],
"description": "When Loki returns and threatens ...",
"gross": [207438708,103052274,55644102,36686871],
"rating": 8.1,
"budget": 225000000
}
}
HTTP GET
Fetch Movie Details /movie/<id>
Scenario with REST
2
{
"actors": [
{
"id": "001",
"fullname": "Robert Downey Jr.",
"popularity": 85
},
{
"id": "002",
"fullname": "Scarlett Johansson",
"popularity": 78
},
{
"id": "003",
"fullname": "Chris Evans",
"popularity": 78
}
]
}
HTTP GET
Fetch Top 3 Actors /movie/<id>/actors?top=3
Scenario with REST
3
{
"reviews": [
{
"id": "a393dc48-0bc9-4d42-bfa2-c29bb23d0cb3",
"author": "Alex",
"rating": 10,
"content": "Amazing movie ! I love superheroes"
},
{
"id": "010b3dbd-d24d-4349-999b-27db1135a839",
"author": "Hannah",
"rating": 7.5,
"content": "Best Marvel ever."
},
{
"id": "786d22dc-821e-4843-a58d-210ba097158b",
"author": "David",
“rating": 7,
"content": "I didn't have high expectations and wasn't disappointed
},
...
]
}
HTTP GET
Fetch Movie Reviews /movie/<id>/reviews?last=5
Scenario with GraphQL
HTTP POST
/graphql
Scenario with GraphQL
{
"data": {
"movie": {
"title": "The Avengers",
"description": "When Loki returns and threatens
...",
"genres": [
"ACTION",
"ADVENTURE",
"SCI_FI"
],
"lastReviews": [
{
"author": "Alex",
"rating": 10,
"content": "Amazing movie ! I love superheroes"
},
...
],
"topActors": [
{
"fullname": "Robert Downey Jr.",
},
...
]
}
}
}
When Scala met GraphQL: Sangria
Scala uses a type system … and so does GraphQL
Sangria will help us implement GraphQL in Scala
Oleg LLYENKO
GraphQL and Scala Type Systems
Trait - Interface
trait VideoContext {
val id: String
val title: String
val description: Option[String]
val genres: Seq[Genre.Value]
val actors: Seq[Actor]
val rating: Option[Double]
val reviews: Seq[Review]
@GraphQLField
def topActors(top: Int): Seq[Actor] =
actors.sortBy(_.popularity).reverse.take(top)
@GraphQLField
def lastReviews(last: Int): Seq[Review] =
reviews.takeRight(last)
}
Case Class - Type
case class Movie(id: String,
title: String,
description: Option[String],
genres: Seq[Genre.Value],
actors: Seq[Actor],
rating: Option[Double],
reviews: Seq[Review],
budget: Long,
gross: Seq[Long]
) extends VideoContext {
@GraphQLField
def profit(week: Int): Long = gross.take(week - 1).sum - budget
@GraphQLField
def alert: Boolean = gross.sum < 0
}
Enumeration - Enum
object Genre extends Enumeration {
val ACTION, COMEDY, HORROR, ANIMATION, ADVENTURE, SCI_FI = Value
}
sealed trait GenreEnum
object GenreEnum {
case object ACTION extends GenreEnum
case object COMEDY extends GenreEnum
case object HORROR extends GenreEnum
case object ANIMATION extends GenreEnum
case object ADVENTURE extends GenreEnum
case object SCI_FI extends GenreEnum
}
Schema Definition in Sangria
Interface Type - Sangria
val VideoType: InterfaceType[Unit, VideoContext] = InterfaceType(
name = "VideoContext",
description = "Template of any video",
fields = fields[Unit, VideoContext](
Field(name = "id", fieldType = StringType, resolve = _.value.id),
Field(name = "title", fieldType = StringType, resolve = _.value.title),
Field(name = "description", fieldType = OptionType(StringType), resolve = _.value.description),
Field(name = "genres", fieldType = ListType(GenreEnum), resolve = _.value.genres),
Field(name = "actors", fieldType = ListType(ActorType), resolve = _.value.actors),
Field(name = "rating", fieldType = OptionType(FloatType), resolve = _.value.rating),
Field(name = "topActors", ListType(ActorType), arguments = Argument("top", IntType) :: Nil,
resolve = c => c.value.topActors(c.arg(Argument("top", IntType)))),
Field(name = "lastReviews", ListType(ReviewType), arguments = Argument("last", IntType) :: Nil,
resolve = c => c.value.lastReviews(c.arg(Argument("last", IntType))))
))
Object Type - Sangria
val MovieType = ObjectType(
"Movie",
"VideoContext you can watch at the theater",
interfaces[Unit, Movie](VideoType),
fields = fields[Unit, Movie](
Field("id", StringType, Some("the id of the movie."), resolve = _.value.id),
Field("title", StringType, Some("the title of the movie."), resolve = _.value.title),
Field("actors", ListType(ActorType), Some("the actors appearing in the movie"), resolve = _.value.actors),
Field("genres", ListType(GenreEnum), Some("the genres of the movie"), resolve = _.value.genres),
Field("rating", OptionType(FloatType), resolve = _.value.rating),
Field("reviews", ListType(ReviewType), resolve = _.value.reviews),
Field("budget", LongType, resolve = _.value.budget),
Field("gross", ListType(LongType), resolve = _.value.gross),
Field("profit", LongType, arguments = Argument("week", IntType) :: Nil,
resolve = ctx => ctx.value.profit(ctx.arg(Argument("week", IntType)))),
Field("alert", BooleanType, resolve = _.value.alert)
))
Enum Type - Sangria
val GenreEnum = EnumType(
"Genre",
Some("Genre of a video"),
List(
EnumValue("COMEDY", value = Genre.COMEDY, description = Some("Toc Toc Toc ...")),
EnumValue("ACTION", value = Genre.ACTION, description = Some("Action videos")),
EnumValue("HORROR", value = Genre.HORROR, description = Some("Bouuuh !")),
EnumValue("ANIMATION", value = Genre.ANIMATION, description = Some("Perfect to have a good time")),
EnumValue("ADVENTURE", value = Genre.ADVENTURE, description = Some("Adventure videos")),
EnumValue("SCI_FI", value = Genre.SCI_FI, description = Some("Weird stuff happening"))
)
)
If Scala and GraphQL have such similar
type systems
Why do we have to redefine it ?
Derivation Macro
We can use derivation macros with implicits
import sangria.macros.derive._
implicit val ReviewType: ObjectType[Unit, Review] = deriveObjectType[Unit, Review]()
implicit val ActorType: ObjectType[Unit, Actor] = deriveObjectType[Unit, Actor]()
implicit val TvShowType: ObjectType[Unit, TvShow] = deriveObjectType[Unit, TvShow]()
// Fonctionne aussi bien avec les Enumeration Scala que les sealed trait + case object
implicit val GenreEnum: EnumType[Genre.Value] = deriveEnumType[Genre.Value]()
implicit val MovieType: ObjectType[VideoContext, Movie] = deriveObjectType[VideoContext, Movie]()
Advantages : Less Code
Inconvenients: Less Flexibility
Derivation Object Type
implicit val MovieType: ObjectType[VideoContext, Movie] = deriveObjectType[VideoContext, Movie]()
trait VideoContext {
val id: String
val title: String
val description: Option[String]
val genres: Seq[Genre.Value]
val actors: Seq[Actor]
val rating: Option[Double]
val reviews: Seq[Review]
@GraphQLField
def topActors(top: Int): Seq[Actor] =
actors.sortBy(_.popularity).reverse.take(top)
@GraphQLField
def lastReviews(last: Int): Seq[Review] =
reviews.takeRight(last)
}
case class Movie(id: String,
title: String,
description: Option[String],
genres: Seq[Genre.Value],
actors: Seq[Actor],
rating: Option[Double],
reviews: Seq[Review],
budget: Long,
gross: Seq[Long]
) extends VideoContext {
@GraphQLField
def profit(week: Int): Long = gross.take(week - 1).sum - budget
@GraphQLField
def alert: Boolean = gross.sum < 0
}
Derivation Object Type With Context
val QueryType = deriveContextObjectType[ApplicationContext, Query, Unit](_.QueryObject)
trait Query {
@GraphQLField
def movies: Vector[Movie] = MovieController.getAllMovies
@GraphQLField
def movie(id: String): Option[Movie] = MovieController.getMovieById(id)
@GraphQLField
def getMoviesByGenre(genres: Seq[Genre.Value]): Vector[Movie] =
MovieController.getMoviesByGenres(genres)
@GraphQLField
def movieByTitle(title: String): Option[Movie] = MovieController.getMovieByTitle(title)
}
class ApplicationContext {
object QueryObject extends Query
object MutationObject extends Mutation
}
Derivation Enum Type
Scala Enumeration
implicit val GenreEnum = deriveEnumType[Genre.Value]()
object Genre extends Enumeration {
val ACTION = Value
val COMEDY = Value
val HORROR = Value
val ANIMATION = Value
val ADVENTURE = Value
val SCI_FI = Value
}
Sealed trait + case object
implicit val GenreEnumSealed = deriveEnumType[GenreEnum]()
sealed trait GenreEnum
object GenreEnum {
case object ACTION extends GenreEnum
case object COMEDY extends GenreEnum
case object HORROR extends GenreEnum
case object ANIMATION extends GenreEnum
case object ADVENTURE extends GenreEnum
case object SCI_FI extends GenreEnum
}
Annotations
@GraphQLField: Specify a def as a Field
@GraphQLDescription: Describe a Field or a Type
@GraphQLDeprecated: Reason why the Field is deprecated
@GraphQLName: To rename a Field
@GraphQLExclude: Exclude a Field, Enum, Argument
Annotations
trait Query {
@GraphQLField
@GraphQLDescription("Fetch a specific movie by id")
def movie(id: String): Option[Movie] = movies.find(_.id == id)
@GraphQLField
@GraphQLDescription("Fetch a specific by title")
@GraphQLDeprecated("Please use movie field instead when possible")
def movieByTitle(title: String): Option[Movie] = movies.find(_.title.toLowerCase() == title.toLowerCase)
}
How to interact with this schema ?
Interacting with GraphQL
How to interact with GraphQL ?
3 types of interactions:
● Query: Read-only
● Mutation: Create Update Delete
● Subscription: Real-Time update
○ Streams of data are sent to the subscribed client
A single endpoint /graphql
Akka HTTP Server
POST /graphql => JSON
query, variables, operation that we parse with any JSON library
QueryParser.parse(query) match {
case Success(queryAst) ⇒
complete(Executor.execute(
schema = SchemaDefinitionMovie.GraphQLSchema,
queryAst = queryAst,
userContext = new ApplicationContext,
variables = vars,
operationName = operation
).map(OK → _))
case Failure(error) ⇒
complete(BadRequest, JsObject("error" → JsString(error.getMessage)))
}
Application Context
// Root context of our application
class ApplicationContext {
object QueryObject extends Query
object MutationObject extends Mutation
}
GraphQL Schema
val QueryType = deriveContextObjectType[ApplicationContext, Query, Unit](_.QueryObject)
val MutationType = deriveContextObjectType[ApplicationContext, Mutation, Unit](_.MutationObject)
val GraphQLSchema = Schema(QueryType, Some(MutationType))
Type Query
val QueryType = deriveContextObjectType[ApplicationContext, Query, Unit](_.QueryObject)
@GraphQLDescription("This is our query type to fetch data")
trait Query {
@GraphQLField
@GraphQLDescription("Fetch all movies")
def movies: Vector[Movie] = MovieController.getAllMovies
@GraphQLField
@GraphQLDescription("Fetch a specific movie by id")
def movie(id: String): Option[Movie] = MovieController.getMovieById(id)
@GraphQLField
@GraphQLDescription("Fetch movies by genres")
def getMoviesByGenre(genres: Seq[Genre.Value]): Vector[Movie] = MovieController.getMoviesByGenres(genres)
@GraphQLField
@GraphQLDescription("Fetch a specific by title")
@GraphQLDeprecated("Please use movie field instead when possible")
def movieByTitle(title: String): Option[Movie] = MovieController.getMovieByTitle(title)
}
Nested Fields
def movie(id: String): Option[Movie] = MovieController.getMovieById(id)
def topActors(top: Int): Seq[Actor] = actors.sortBy(_.popularity).reverse.take(top)
case class Actor(id: String,
fullname: String,
popularity: Option[Int]
)
query {
movie(id: "001") {
topActors(top: 3) {
id
fullname
popularity
}
}
}
Type Mutation
val MutationType = deriveContextObjectType[ApplicationContext, Mutation, Unit](_.MutationObject)
trait Mutation {
@GraphQLField
def createReview(movieId: String, author: String, rating: Double, content: String): Option[Movie] = {
val review = Review(author = author, rating = rating, content = content)
MovieController.addReview(movieId, review)
}
}
Main difference between Query and Mutation
Because mutation modify a state, it is not possible to run them in parallel.
● Query Fields are run in parallel
● Mutation Fields are run in series
If we send two mutations in our query, they will be run one after the other
Client Side
Introspection API
The Introspection API allows us to fetch graphql Schema in JSON
If we don’t know the schema, we can query it.
What kind of client consume GraphQL API
Most of the clients to a GraphQL server are frontend applications.
The GraphQL ecosystem client-side for frontend applications is extremely rich
For Example, Apollo Client which is really mature or Relay Client
What about Sangria client-side ?
Principal use cases are for tooling, validation and testing
● graphql macro can be used to validate query syntax at compile time
import sangria.macros._
test("query is valid") {
val query =
graphql"""
query {
movie(id: "001") {
title
description
rating
lastReviews(last: 5) {
author
content
}
}
}
"""
assert(QueryValidator.default.validateQuery(SchemaDefinitionMovie.GraphQLSchema, query) == Vector.empty[Violation])
}
What about Sangria client-side ?
● test graphql response for a query
test("query parsed correctly") {
val query =
graphql"""
query {
movie(id: "001") {
title
}
}
"""
assert(executeQuery(query).toString == """{"data":{"movie":{"title":"The Avengers"}}}""")
}
● retrieve graphql schema from sangria schema definition
SchemaRenderer.renderSchema(SchemaDefinitionMovie.GraphQLSchema)
Before We Go
When is GraphQL a good alternative to REST for your API ?
● Your API is used by mobile applications and data needs to be reached by the
client even with a bad connection
● You have lots of different clients using your API and can’t customize your API
for each one
● You have a backend team and a frontend team (they can work independently)
Rest is still deeply rooted in our habits
But if you have the opportunity, why not use GraphQL
Resources
● www.howtographql.com (There is everything to know about GraphQL)
● http://facebook.github.io/graphql/ (Paper about GraphQL)
● http://sangria-graphql.org/learn/ (Sangria Documentation)
● https://github.com/sangria-graphql/sangria-akka-http-example (Boilerplate)

More Related Content

What's hot

Jvm performance tuning
Jvm performance tuningJvm performance tuning
Jvm performance tuning
Igor Igoroshka
 
G1 Garbage Collector: Details and Tuning
G1 Garbage Collector: Details and TuningG1 Garbage Collector: Details and Tuning
G1 Garbage Collector: Details and Tuning
Simone Bordet
 
2012 Chevy Sonic in Baltimore, Maryland
2012 Chevy Sonic in Baltimore, Maryland2012 Chevy Sonic in Baltimore, Maryland
2012 Chevy Sonic in Baltimore, Maryland
Jerry's Chevrolet
 
Instagram Hacker 2014 v3.7.2 - easy way to hack Instagram account !
Instagram Hacker 2014 v3.7.2 - easy way to hack Instagram account !Instagram Hacker 2014 v3.7.2 - easy way to hack Instagram account !
Instagram Hacker 2014 v3.7.2 - easy way to hack Instagram account !
Home
 
Unit testing of spark applications
Unit testing of spark applicationsUnit testing of spark applications
Unit testing of spark applications
Knoldus Inc.
 
Top 10 applications support analyst interview questions and answers
Top 10 applications support analyst interview questions and answersTop 10 applications support analyst interview questions and answers
Top 10 applications support analyst interview questions and answers
marcdanny68
 

What's hot (6)

Jvm performance tuning
Jvm performance tuningJvm performance tuning
Jvm performance tuning
 
G1 Garbage Collector: Details and Tuning
G1 Garbage Collector: Details and TuningG1 Garbage Collector: Details and Tuning
G1 Garbage Collector: Details and Tuning
 
2012 Chevy Sonic in Baltimore, Maryland
2012 Chevy Sonic in Baltimore, Maryland2012 Chevy Sonic in Baltimore, Maryland
2012 Chevy Sonic in Baltimore, Maryland
 
Instagram Hacker 2014 v3.7.2 - easy way to hack Instagram account !
Instagram Hacker 2014 v3.7.2 - easy way to hack Instagram account !Instagram Hacker 2014 v3.7.2 - easy way to hack Instagram account !
Instagram Hacker 2014 v3.7.2 - easy way to hack Instagram account !
 
Unit testing of spark applications
Unit testing of spark applicationsUnit testing of spark applications
Unit testing of spark applications
 
Top 10 applications support analyst interview questions and answers
Top 10 applications support analyst interview questions and answersTop 10 applications support analyst interview questions and answers
Top 10 applications support analyst interview questions and answers
 

Similar to GraphQL with Sangria

JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
Jarrod Overson
 
RIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWTRIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWT
Michael Galpin
 
Mining Interesting Trivia for Entities from Wikipedia PART-II
Mining Interesting Trivia for Entities from Wikipedia PART-IIMining Interesting Trivia for Entities from Wikipedia PART-II
Mining Interesting Trivia for Entities from Wikipedia PART-II
Abhay Prakash
 
Casting for not so strange actors
Casting for not so strange actorsCasting for not so strange actors
Casting for not so strange actors
zucaritask
 
Kotlin for all the Things
Kotlin for all the ThingsKotlin for all the Things
Kotlin for all the Things
Eamonn Boyle
 
SVGo workshop
SVGo workshopSVGo workshop
SVGo workshop
Anthony Starks
 
Making Swift even safer
Making Swift even saferMaking Swift even safer
Making Swift even safer
Denis Fileev
 
Using Stargate APIs for Cassandra-Backed Applications
Using Stargate APIs for Cassandra-Backed ApplicationsUsing Stargate APIs for Cassandra-Backed Applications
Using Stargate APIs for Cassandra-Backed Applications
Nordic APIs
 
Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017
Mike Nakhimovich
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application Architecture
FDConf
 
Reactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDaysReactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDays
Manuel Bernhardt
 
Abc2011 yagi
Abc2011 yagiAbc2011 yagi
Abc2011 yagi
Toshihiro Yagi
 
How to Handle NoSQL with a Relational Database
How to Handle NoSQL with a Relational DatabaseHow to Handle NoSQL with a Relational Database
How to Handle NoSQL with a Relational Database
DATAVERSITY
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
Ben Lesh
 
Idioms in swift 2016 05c
Idioms in swift 2016 05cIdioms in swift 2016 05c
Idioms in swift 2016 05c
Kaz Yoshikawa
 
Moderne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodellModerne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodell
Damir Dobric
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
Ted Husted
 
VelocityGraph Introduction
VelocityGraph IntroductionVelocityGraph Introduction
VelocityGraph Introduction
Mats Persson
 
2012-08-29 - NoSQL Bootcamp (Redis, RavenDB & MongoDB für .NET Entwickler)
2012-08-29 - NoSQL Bootcamp (Redis, RavenDB & MongoDB für .NET Entwickler)2012-08-29 - NoSQL Bootcamp (Redis, RavenDB & MongoDB für .NET Entwickler)
2012-08-29 - NoSQL Bootcamp (Redis, RavenDB & MongoDB für .NET Entwickler)
Johannes Hoppe
 
If you give a mouse a clickhouse, by Alex Hofsteede, Sentry
If you give a mouse a clickhouse, by Alex Hofsteede, SentryIf you give a mouse a clickhouse, by Alex Hofsteede, Sentry
If you give a mouse a clickhouse, by Alex Hofsteede, Sentry
Altinity Ltd
 

Similar to GraphQL with Sangria (20)

JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
 
RIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWTRIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWT
 
Mining Interesting Trivia for Entities from Wikipedia PART-II
Mining Interesting Trivia for Entities from Wikipedia PART-IIMining Interesting Trivia for Entities from Wikipedia PART-II
Mining Interesting Trivia for Entities from Wikipedia PART-II
 
Casting for not so strange actors
Casting for not so strange actorsCasting for not so strange actors
Casting for not so strange actors
 
Kotlin for all the Things
Kotlin for all the ThingsKotlin for all the Things
Kotlin for all the Things
 
SVGo workshop
SVGo workshopSVGo workshop
SVGo workshop
 
Making Swift even safer
Making Swift even saferMaking Swift even safer
Making Swift even safer
 
Using Stargate APIs for Cassandra-Backed Applications
Using Stargate APIs for Cassandra-Backed ApplicationsUsing Stargate APIs for Cassandra-Backed Applications
Using Stargate APIs for Cassandra-Backed Applications
 
Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application Architecture
 
Reactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDaysReactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDays
 
Abc2011 yagi
Abc2011 yagiAbc2011 yagi
Abc2011 yagi
 
How to Handle NoSQL with a Relational Database
How to Handle NoSQL with a Relational DatabaseHow to Handle NoSQL with a Relational Database
How to Handle NoSQL with a Relational Database
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
 
Idioms in swift 2016 05c
Idioms in swift 2016 05cIdioms in swift 2016 05c
Idioms in swift 2016 05c
 
Moderne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodellModerne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodell
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
VelocityGraph Introduction
VelocityGraph IntroductionVelocityGraph Introduction
VelocityGraph Introduction
 
2012-08-29 - NoSQL Bootcamp (Redis, RavenDB & MongoDB für .NET Entwickler)
2012-08-29 - NoSQL Bootcamp (Redis, RavenDB & MongoDB für .NET Entwickler)2012-08-29 - NoSQL Bootcamp (Redis, RavenDB & MongoDB für .NET Entwickler)
2012-08-29 - NoSQL Bootcamp (Redis, RavenDB & MongoDB für .NET Entwickler)
 
If you give a mouse a clickhouse, by Alex Hofsteede, Sentry
If you give a mouse a clickhouse, by Alex Hofsteede, SentryIf you give a mouse a clickhouse, by Alex Hofsteede, Sentry
If you give a mouse a clickhouse, by Alex Hofsteede, Sentry
 

Recently uploaded

RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
thanhdowork
 
132/33KV substation case study Presentation
132/33KV substation case study Presentation132/33KV substation case study Presentation
132/33KV substation case study Presentation
kandramariana6
 
International Conference on NLP, Artificial Intelligence, Machine Learning an...
International Conference on NLP, Artificial Intelligence, Machine Learning an...International Conference on NLP, Artificial Intelligence, Machine Learning an...
International Conference on NLP, Artificial Intelligence, Machine Learning an...
gerogepatton
 
2. Operations Strategy in a Global Environment.ppt
2. Operations Strategy in a Global Environment.ppt2. Operations Strategy in a Global Environment.ppt
2. Operations Strategy in a Global Environment.ppt
PuktoonEngr
 
A SYSTEMATIC RISK ASSESSMENT APPROACH FOR SECURING THE SMART IRRIGATION SYSTEMS
A SYSTEMATIC RISK ASSESSMENT APPROACH FOR SECURING THE SMART IRRIGATION SYSTEMSA SYSTEMATIC RISK ASSESSMENT APPROACH FOR SECURING THE SMART IRRIGATION SYSTEMS
A SYSTEMATIC RISK ASSESSMENT APPROACH FOR SECURING THE SMART IRRIGATION SYSTEMS
IJNSA Journal
 
Heat Resistant Concrete Presentation ppt
Heat Resistant Concrete Presentation pptHeat Resistant Concrete Presentation ppt
Heat Resistant Concrete Presentation ppt
mamunhossenbd75
 
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
ihlasbinance2003
 
Low power architecture of logic gates using adiabatic techniques
Low power architecture of logic gates using adiabatic techniquesLow power architecture of logic gates using adiabatic techniques
Low power architecture of logic gates using adiabatic techniques
nooriasukmaningtyas
 
sieving analysis and results interpretation
sieving analysis and results interpretationsieving analysis and results interpretation
sieving analysis and results interpretation
ssuser36d3051
 
6th International Conference on Machine Learning & Applications (CMLA 2024)
6th International Conference on Machine Learning & Applications (CMLA 2024)6th International Conference on Machine Learning & Applications (CMLA 2024)
6th International Conference on Machine Learning & Applications (CMLA 2024)
ClaraZara1
 
Wearable antenna for antenna applications
Wearable antenna for antenna applicationsWearable antenna for antenna applications
Wearable antenna for antenna applications
Madhumitha Jayaram
 
PPT on GRP pipes manufacturing and testing
PPT on GRP pipes manufacturing and testingPPT on GRP pipes manufacturing and testing
PPT on GRP pipes manufacturing and testing
anoopmanoharan2
 
Swimming pool mechanical components design.pptx
Swimming pool  mechanical components design.pptxSwimming pool  mechanical components design.pptx
Swimming pool mechanical components design.pptx
yokeleetan1
 
Technical Drawings introduction to drawing of prisms
Technical Drawings introduction to drawing of prismsTechnical Drawings introduction to drawing of prisms
Technical Drawings introduction to drawing of prisms
heavyhaig
 
Manufacturing Process of molasses based distillery ppt.pptx
Manufacturing Process of molasses based distillery ppt.pptxManufacturing Process of molasses based distillery ppt.pptx
Manufacturing Process of molasses based distillery ppt.pptx
Madan Karki
 
ML Based Model for NIDS MSc Updated Presentation.v2.pptx
ML Based Model for NIDS MSc Updated Presentation.v2.pptxML Based Model for NIDS MSc Updated Presentation.v2.pptx
ML Based Model for NIDS MSc Updated Presentation.v2.pptx
JamalHussainArman
 
ACEP Magazine edition 4th launched on 05.06.2024
ACEP Magazine edition 4th launched on 05.06.2024ACEP Magazine edition 4th launched on 05.06.2024
ACEP Magazine edition 4th launched on 05.06.2024
Rahul
 
Embedded machine learning-based road conditions and driving behavior monitoring
Embedded machine learning-based road conditions and driving behavior monitoringEmbedded machine learning-based road conditions and driving behavior monitoring
Embedded machine learning-based road conditions and driving behavior monitoring
IJECEIAES
 
DfMAy 2024 - key insights and contributions
DfMAy 2024 - key insights and contributionsDfMAy 2024 - key insights and contributions
DfMAy 2024 - key insights and contributions
gestioneergodomus
 
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdfBPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
MIGUELANGEL966976
 

Recently uploaded (20)

RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
RAT: Retrieval Augmented Thoughts Elicit Context-Aware Reasoning in Long-Hori...
 
132/33KV substation case study Presentation
132/33KV substation case study Presentation132/33KV substation case study Presentation
132/33KV substation case study Presentation
 
International Conference on NLP, Artificial Intelligence, Machine Learning an...
International Conference on NLP, Artificial Intelligence, Machine Learning an...International Conference on NLP, Artificial Intelligence, Machine Learning an...
International Conference on NLP, Artificial Intelligence, Machine Learning an...
 
2. Operations Strategy in a Global Environment.ppt
2. Operations Strategy in a Global Environment.ppt2. Operations Strategy in a Global Environment.ppt
2. Operations Strategy in a Global Environment.ppt
 
A SYSTEMATIC RISK ASSESSMENT APPROACH FOR SECURING THE SMART IRRIGATION SYSTEMS
A SYSTEMATIC RISK ASSESSMENT APPROACH FOR SECURING THE SMART IRRIGATION SYSTEMSA SYSTEMATIC RISK ASSESSMENT APPROACH FOR SECURING THE SMART IRRIGATION SYSTEMS
A SYSTEMATIC RISK ASSESSMENT APPROACH FOR SECURING THE SMART IRRIGATION SYSTEMS
 
Heat Resistant Concrete Presentation ppt
Heat Resistant Concrete Presentation pptHeat Resistant Concrete Presentation ppt
Heat Resistant Concrete Presentation ppt
 
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
 
Low power architecture of logic gates using adiabatic techniques
Low power architecture of logic gates using adiabatic techniquesLow power architecture of logic gates using adiabatic techniques
Low power architecture of logic gates using adiabatic techniques
 
sieving analysis and results interpretation
sieving analysis and results interpretationsieving analysis and results interpretation
sieving analysis and results interpretation
 
6th International Conference on Machine Learning & Applications (CMLA 2024)
6th International Conference on Machine Learning & Applications (CMLA 2024)6th International Conference on Machine Learning & Applications (CMLA 2024)
6th International Conference on Machine Learning & Applications (CMLA 2024)
 
Wearable antenna for antenna applications
Wearable antenna for antenna applicationsWearable antenna for antenna applications
Wearable antenna for antenna applications
 
PPT on GRP pipes manufacturing and testing
PPT on GRP pipes manufacturing and testingPPT on GRP pipes manufacturing and testing
PPT on GRP pipes manufacturing and testing
 
Swimming pool mechanical components design.pptx
Swimming pool  mechanical components design.pptxSwimming pool  mechanical components design.pptx
Swimming pool mechanical components design.pptx
 
Technical Drawings introduction to drawing of prisms
Technical Drawings introduction to drawing of prismsTechnical Drawings introduction to drawing of prisms
Technical Drawings introduction to drawing of prisms
 
Manufacturing Process of molasses based distillery ppt.pptx
Manufacturing Process of molasses based distillery ppt.pptxManufacturing Process of molasses based distillery ppt.pptx
Manufacturing Process of molasses based distillery ppt.pptx
 
ML Based Model for NIDS MSc Updated Presentation.v2.pptx
ML Based Model for NIDS MSc Updated Presentation.v2.pptxML Based Model for NIDS MSc Updated Presentation.v2.pptx
ML Based Model for NIDS MSc Updated Presentation.v2.pptx
 
ACEP Magazine edition 4th launched on 05.06.2024
ACEP Magazine edition 4th launched on 05.06.2024ACEP Magazine edition 4th launched on 05.06.2024
ACEP Magazine edition 4th launched on 05.06.2024
 
Embedded machine learning-based road conditions and driving behavior monitoring
Embedded machine learning-based road conditions and driving behavior monitoringEmbedded machine learning-based road conditions and driving behavior monitoring
Embedded machine learning-based road conditions and driving behavior monitoring
 
DfMAy 2024 - key insights and contributions
DfMAy 2024 - key insights and contributionsDfMAy 2024 - key insights and contributions
DfMAy 2024 - key insights and contributions
 
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdfBPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
 

GraphQL with Sangria

  • 1. GraphQL with Sangria Scala Implementation
  • 2. About Me Anthony SSI YAN KAI ● Data Engineer at ebiznext ○ Formation BI ○ DataLake (creation, enriching) ○ FullStack (react.js - scala) Scala - Spark - Hadoop - ElasticSearch - Kafka - Akka - GraphQL
  • 3. What is GraphQL all about ? GraphQL is a query language for APIs Created to answer those problematics : ● Mobile usage: ○ Sloppy networks and low-powered devices ○ Reduce the amount of data transferred over network ● Large variety of clients: ○ Classic API can hardly fit every clients needs in a maintainable way ○ Each client accesses the data it needs with a single endpoint ● Fast development ○ Classic REST APIs regularly needs to update the way data is exposed (multiple endpoints, etc…) ○ Less communication between frontend and backend
  • 4. REST vs GraphQL The major paradigm variation: REST imposes a fixed data structure to the client while … GraphQL allow clients to fetch the data they need Instead of multiple endpoints that returns fixed data structures, GraphQL provides an unique endpoint that returns the data asked by the client Fetching data with GraphQL can be done in a single query while in REST multiples queries are often needed and more unnecessary data is transferred. For more GraphQL vs REST: www.howtographql.com
  • 5. Architecture GraphQL can be plugged to basically anything ... ● Database ● Legacy systems ● Microservice ● Third-party API ● Anything ... resources: www.howtographql.com
  • 6. Use Case id: String title: String, description: Option[String] genres: Seq[Genre.Value] actors: Seq[Actor] rating: Option[Double] reviews: Seq[Review] budget: Long gross: Seq[Long] id: String, fullname: String popularity: Option[Int] movies: Seq[Movie] Expose data for a movie application case class Movie case class Actor id: String = UUID.randomUUID().toString, author: String, content: String, rating: Double, created: Long = Instant.now.toEpochMilli case class Review
  • 7. Scenario We want to fetch this data: ● Movie Title - Genres - Rating - Description ● Top 3 most popular actors in the movie ● Last 5 reviews about the movie The Avengers Top 3 Actors Last 5 Reviews Action,Adventure, Sci-Fi Rating: 8.1 Description: When Loki returns and threatens to steal the .. Robert D. Scarlett J. Chris E.
  • 8. Scenario with REST 1 { "movie": { "id": "001", "title": "The Avengers" "genres": [ACTION","ADVENTURE","SCI_FI"], "description": "When Loki returns and threatens ...", "gross": [207438708,103052274,55644102,36686871], "rating": 8.1, "budget": 225000000 } } HTTP GET Fetch Movie Details /movie/<id>
  • 9. Scenario with REST 2 { "actors": [ { "id": "001", "fullname": "Robert Downey Jr.", "popularity": 85 }, { "id": "002", "fullname": "Scarlett Johansson", "popularity": 78 }, { "id": "003", "fullname": "Chris Evans", "popularity": 78 } ] } HTTP GET Fetch Top 3 Actors /movie/<id>/actors?top=3
  • 10. Scenario with REST 3 { "reviews": [ { "id": "a393dc48-0bc9-4d42-bfa2-c29bb23d0cb3", "author": "Alex", "rating": 10, "content": "Amazing movie ! I love superheroes" }, { "id": "010b3dbd-d24d-4349-999b-27db1135a839", "author": "Hannah", "rating": 7.5, "content": "Best Marvel ever." }, { "id": "786d22dc-821e-4843-a58d-210ba097158b", "author": "David", “rating": 7, "content": "I didn't have high expectations and wasn't disappointed }, ... ] } HTTP GET Fetch Movie Reviews /movie/<id>/reviews?last=5
  • 11. Scenario with GraphQL HTTP POST /graphql
  • 12. Scenario with GraphQL { "data": { "movie": { "title": "The Avengers", "description": "When Loki returns and threatens ...", "genres": [ "ACTION", "ADVENTURE", "SCI_FI" ], "lastReviews": [ { "author": "Alex", "rating": 10, "content": "Amazing movie ! I love superheroes" }, ... ], "topActors": [ { "fullname": "Robert Downey Jr.", }, ... ] } } }
  • 13. When Scala met GraphQL: Sangria Scala uses a type system … and so does GraphQL Sangria will help us implement GraphQL in Scala Oleg LLYENKO
  • 14. GraphQL and Scala Type Systems
  • 15. Trait - Interface trait VideoContext { val id: String val title: String val description: Option[String] val genres: Seq[Genre.Value] val actors: Seq[Actor] val rating: Option[Double] val reviews: Seq[Review] @GraphQLField def topActors(top: Int): Seq[Actor] = actors.sortBy(_.popularity).reverse.take(top) @GraphQLField def lastReviews(last: Int): Seq[Review] = reviews.takeRight(last) }
  • 16. Case Class - Type case class Movie(id: String, title: String, description: Option[String], genres: Seq[Genre.Value], actors: Seq[Actor], rating: Option[Double], reviews: Seq[Review], budget: Long, gross: Seq[Long] ) extends VideoContext { @GraphQLField def profit(week: Int): Long = gross.take(week - 1).sum - budget @GraphQLField def alert: Boolean = gross.sum < 0 }
  • 17. Enumeration - Enum object Genre extends Enumeration { val ACTION, COMEDY, HORROR, ANIMATION, ADVENTURE, SCI_FI = Value } sealed trait GenreEnum object GenreEnum { case object ACTION extends GenreEnum case object COMEDY extends GenreEnum case object HORROR extends GenreEnum case object ANIMATION extends GenreEnum case object ADVENTURE extends GenreEnum case object SCI_FI extends GenreEnum }
  • 19. Interface Type - Sangria val VideoType: InterfaceType[Unit, VideoContext] = InterfaceType( name = "VideoContext", description = "Template of any video", fields = fields[Unit, VideoContext]( Field(name = "id", fieldType = StringType, resolve = _.value.id), Field(name = "title", fieldType = StringType, resolve = _.value.title), Field(name = "description", fieldType = OptionType(StringType), resolve = _.value.description), Field(name = "genres", fieldType = ListType(GenreEnum), resolve = _.value.genres), Field(name = "actors", fieldType = ListType(ActorType), resolve = _.value.actors), Field(name = "rating", fieldType = OptionType(FloatType), resolve = _.value.rating), Field(name = "topActors", ListType(ActorType), arguments = Argument("top", IntType) :: Nil, resolve = c => c.value.topActors(c.arg(Argument("top", IntType)))), Field(name = "lastReviews", ListType(ReviewType), arguments = Argument("last", IntType) :: Nil, resolve = c => c.value.lastReviews(c.arg(Argument("last", IntType)))) ))
  • 20. Object Type - Sangria val MovieType = ObjectType( "Movie", "VideoContext you can watch at the theater", interfaces[Unit, Movie](VideoType), fields = fields[Unit, Movie]( Field("id", StringType, Some("the id of the movie."), resolve = _.value.id), Field("title", StringType, Some("the title of the movie."), resolve = _.value.title), Field("actors", ListType(ActorType), Some("the actors appearing in the movie"), resolve = _.value.actors), Field("genres", ListType(GenreEnum), Some("the genres of the movie"), resolve = _.value.genres), Field("rating", OptionType(FloatType), resolve = _.value.rating), Field("reviews", ListType(ReviewType), resolve = _.value.reviews), Field("budget", LongType, resolve = _.value.budget), Field("gross", ListType(LongType), resolve = _.value.gross), Field("profit", LongType, arguments = Argument("week", IntType) :: Nil, resolve = ctx => ctx.value.profit(ctx.arg(Argument("week", IntType)))), Field("alert", BooleanType, resolve = _.value.alert) ))
  • 21. Enum Type - Sangria val GenreEnum = EnumType( "Genre", Some("Genre of a video"), List( EnumValue("COMEDY", value = Genre.COMEDY, description = Some("Toc Toc Toc ...")), EnumValue("ACTION", value = Genre.ACTION, description = Some("Action videos")), EnumValue("HORROR", value = Genre.HORROR, description = Some("Bouuuh !")), EnumValue("ANIMATION", value = Genre.ANIMATION, description = Some("Perfect to have a good time")), EnumValue("ADVENTURE", value = Genre.ADVENTURE, description = Some("Adventure videos")), EnumValue("SCI_FI", value = Genre.SCI_FI, description = Some("Weird stuff happening")) ) )
  • 22. If Scala and GraphQL have such similar type systems Why do we have to redefine it ?
  • 23. Derivation Macro We can use derivation macros with implicits import sangria.macros.derive._ implicit val ReviewType: ObjectType[Unit, Review] = deriveObjectType[Unit, Review]() implicit val ActorType: ObjectType[Unit, Actor] = deriveObjectType[Unit, Actor]() implicit val TvShowType: ObjectType[Unit, TvShow] = deriveObjectType[Unit, TvShow]() // Fonctionne aussi bien avec les Enumeration Scala que les sealed trait + case object implicit val GenreEnum: EnumType[Genre.Value] = deriveEnumType[Genre.Value]() implicit val MovieType: ObjectType[VideoContext, Movie] = deriveObjectType[VideoContext, Movie]() Advantages : Less Code Inconvenients: Less Flexibility
  • 24. Derivation Object Type implicit val MovieType: ObjectType[VideoContext, Movie] = deriveObjectType[VideoContext, Movie]() trait VideoContext { val id: String val title: String val description: Option[String] val genres: Seq[Genre.Value] val actors: Seq[Actor] val rating: Option[Double] val reviews: Seq[Review] @GraphQLField def topActors(top: Int): Seq[Actor] = actors.sortBy(_.popularity).reverse.take(top) @GraphQLField def lastReviews(last: Int): Seq[Review] = reviews.takeRight(last) } case class Movie(id: String, title: String, description: Option[String], genres: Seq[Genre.Value], actors: Seq[Actor], rating: Option[Double], reviews: Seq[Review], budget: Long, gross: Seq[Long] ) extends VideoContext { @GraphQLField def profit(week: Int): Long = gross.take(week - 1).sum - budget @GraphQLField def alert: Boolean = gross.sum < 0 }
  • 25. Derivation Object Type With Context val QueryType = deriveContextObjectType[ApplicationContext, Query, Unit](_.QueryObject) trait Query { @GraphQLField def movies: Vector[Movie] = MovieController.getAllMovies @GraphQLField def movie(id: String): Option[Movie] = MovieController.getMovieById(id) @GraphQLField def getMoviesByGenre(genres: Seq[Genre.Value]): Vector[Movie] = MovieController.getMoviesByGenres(genres) @GraphQLField def movieByTitle(title: String): Option[Movie] = MovieController.getMovieByTitle(title) } class ApplicationContext { object QueryObject extends Query object MutationObject extends Mutation }
  • 26. Derivation Enum Type Scala Enumeration implicit val GenreEnum = deriveEnumType[Genre.Value]() object Genre extends Enumeration { val ACTION = Value val COMEDY = Value val HORROR = Value val ANIMATION = Value val ADVENTURE = Value val SCI_FI = Value } Sealed trait + case object implicit val GenreEnumSealed = deriveEnumType[GenreEnum]() sealed trait GenreEnum object GenreEnum { case object ACTION extends GenreEnum case object COMEDY extends GenreEnum case object HORROR extends GenreEnum case object ANIMATION extends GenreEnum case object ADVENTURE extends GenreEnum case object SCI_FI extends GenreEnum }
  • 27. Annotations @GraphQLField: Specify a def as a Field @GraphQLDescription: Describe a Field or a Type @GraphQLDeprecated: Reason why the Field is deprecated @GraphQLName: To rename a Field @GraphQLExclude: Exclude a Field, Enum, Argument
  • 28. Annotations trait Query { @GraphQLField @GraphQLDescription("Fetch a specific movie by id") def movie(id: String): Option[Movie] = movies.find(_.id == id) @GraphQLField @GraphQLDescription("Fetch a specific by title") @GraphQLDeprecated("Please use movie field instead when possible") def movieByTitle(title: String): Option[Movie] = movies.find(_.title.toLowerCase() == title.toLowerCase) }
  • 29. How to interact with this schema ?
  • 30. Interacting with GraphQL How to interact with GraphQL ? 3 types of interactions: ● Query: Read-only ● Mutation: Create Update Delete ● Subscription: Real-Time update ○ Streams of data are sent to the subscribed client A single endpoint /graphql
  • 31. Akka HTTP Server POST /graphql => JSON query, variables, operation that we parse with any JSON library QueryParser.parse(query) match { case Success(queryAst) ⇒ complete(Executor.execute( schema = SchemaDefinitionMovie.GraphQLSchema, queryAst = queryAst, userContext = new ApplicationContext, variables = vars, operationName = operation ).map(OK → _)) case Failure(error) ⇒ complete(BadRequest, JsObject("error" → JsString(error.getMessage))) }
  • 32. Application Context // Root context of our application class ApplicationContext { object QueryObject extends Query object MutationObject extends Mutation } GraphQL Schema val QueryType = deriveContextObjectType[ApplicationContext, Query, Unit](_.QueryObject) val MutationType = deriveContextObjectType[ApplicationContext, Mutation, Unit](_.MutationObject) val GraphQLSchema = Schema(QueryType, Some(MutationType))
  • 33. Type Query val QueryType = deriveContextObjectType[ApplicationContext, Query, Unit](_.QueryObject) @GraphQLDescription("This is our query type to fetch data") trait Query { @GraphQLField @GraphQLDescription("Fetch all movies") def movies: Vector[Movie] = MovieController.getAllMovies @GraphQLField @GraphQLDescription("Fetch a specific movie by id") def movie(id: String): Option[Movie] = MovieController.getMovieById(id) @GraphQLField @GraphQLDescription("Fetch movies by genres") def getMoviesByGenre(genres: Seq[Genre.Value]): Vector[Movie] = MovieController.getMoviesByGenres(genres) @GraphQLField @GraphQLDescription("Fetch a specific by title") @GraphQLDeprecated("Please use movie field instead when possible") def movieByTitle(title: String): Option[Movie] = MovieController.getMovieByTitle(title) }
  • 34. Nested Fields def movie(id: String): Option[Movie] = MovieController.getMovieById(id) def topActors(top: Int): Seq[Actor] = actors.sortBy(_.popularity).reverse.take(top) case class Actor(id: String, fullname: String, popularity: Option[Int] ) query { movie(id: "001") { topActors(top: 3) { id fullname popularity } } }
  • 35. Type Mutation val MutationType = deriveContextObjectType[ApplicationContext, Mutation, Unit](_.MutationObject) trait Mutation { @GraphQLField def createReview(movieId: String, author: String, rating: Double, content: String): Option[Movie] = { val review = Review(author = author, rating = rating, content = content) MovieController.addReview(movieId, review) } }
  • 36. Main difference between Query and Mutation Because mutation modify a state, it is not possible to run them in parallel. ● Query Fields are run in parallel ● Mutation Fields are run in series If we send two mutations in our query, they will be run one after the other
  • 38. Introspection API The Introspection API allows us to fetch graphql Schema in JSON If we don’t know the schema, we can query it.
  • 39. What kind of client consume GraphQL API Most of the clients to a GraphQL server are frontend applications. The GraphQL ecosystem client-side for frontend applications is extremely rich For Example, Apollo Client which is really mature or Relay Client
  • 40. What about Sangria client-side ? Principal use cases are for tooling, validation and testing ● graphql macro can be used to validate query syntax at compile time import sangria.macros._ test("query is valid") { val query = graphql""" query { movie(id: "001") { title description rating lastReviews(last: 5) { author content } } } """ assert(QueryValidator.default.validateQuery(SchemaDefinitionMovie.GraphQLSchema, query) == Vector.empty[Violation]) }
  • 41. What about Sangria client-side ? ● test graphql response for a query test("query parsed correctly") { val query = graphql""" query { movie(id: "001") { title } } """ assert(executeQuery(query).toString == """{"data":{"movie":{"title":"The Avengers"}}}""") } ● retrieve graphql schema from sangria schema definition SchemaRenderer.renderSchema(SchemaDefinitionMovie.GraphQLSchema)
  • 42. Before We Go When is GraphQL a good alternative to REST for your API ? ● Your API is used by mobile applications and data needs to be reached by the client even with a bad connection ● You have lots of different clients using your API and can’t customize your API for each one ● You have a backend team and a frontend team (they can work independently)
  • 43. Rest is still deeply rooted in our habits But if you have the opportunity, why not use GraphQL
  • 44. Resources ● www.howtographql.com (There is everything to know about GraphQL) ● http://facebook.github.io/graphql/ (Paper about GraphQL) ● http://sangria-graphql.org/learn/ (Sangria Documentation) ● https://github.com/sangria-graphql/sangria-akka-http-example (Boilerplate)