PLAN
1 - Introduction
2 - Advantages
3 - GraphQL VS REST API’s
4 - Performance and Utility
● Using all GraphQL / GaphQL with REST API
5 - Security
6 - Implementation
7- GraphQL + Angular = Apollo
Introduction
Traditional REST APIs work with the concept of Resources that the server manages.This
suffers when the client needs data from multiple resources at the same time.
GraphQL as a query language for APIs and a runtime for fulfilling those queries with your
existing data, provides a complete and understandable description of the data in your API,
gives you the power to ask for exactly what they need and nothing more, makes it easier to
evolve APIs over time, and enables powerful developer tools.
3
Advantages
● Apps using GraphQL are fast and stable because they control the data they get.
Send a GraphQL query to your API and get exactly what you need, nothing more and nothing less.
● The data types are strictly defined, which limits communication problems between the client and
the server.
● GraphQL is introspective. A client can request a list of available data types.
● GraphQL allows you to evolve the API of an application without degrading existing requests.
● There are many open source GraphQL extensions that provide functions not available in the REST APIs.
...
4
Real Example
Assume that a mobile or web app wants to access data from a server that displays the blog
author information. The app is supposed to display the author’s name, the blog posts written by
the author, and the three most recent blog topics written by him/her.
Let’s give an abstract level review on how to fetch this data in REST vs GraphQL.
7
REST Request
In REST, an API endpoint is called to request the data that the client app needs and the server returns the
response based on the requested query. When someone uses REST API, they would first have an endpoint
which could be https://mobilelive.ca/blog/author/<author-id>, this endpoint would fetch the author’s
information. Now another REST endpoint is needed to access the blog posts
https://mobilelive.ca/blog/author/<author-id>/posts, and finally, you would need yet another endpoint to get
the blog topics https://mobilelive.ca/blog/author/<some-id>/topics. Now here, you will notice two issues:
9
Problems
Problem 1: Multiple round-trips with REST
As you would have noticed, there are multiple round-trips that one should make while utilizing REST to get the information that a client
application needs. One has to add additional endpoints if the information is extended.
Problem 2: Over-fetching and Under-fetching Problems with REST
Frequently with REST, one will wind up with unnecessary information at a specific stage. For instance, when calling the blog/author/<author-id>
endpoint, the client application will get all the information related to the author’s profile. It could even get back other information like date
created, date updated, age, and gender. But what the client application required was the only author name. It’s a case of over-fetching in REST. On
account of under-getting, one can see here that the call to blog/author/<author-id> was not adequate to recover what the client app was searching
10
for. The client app needed to make a separate call to another endpoint blog/author/<author-id>/posts to get the last three posts composed by the
GraphQL Query Request
Now let’s think about what happens in GraphQL. You think of a query to request what you need, and you get back precisely the data you
asked for. There are no full circle trips to remote servers to bring information to GraphQL.We only go for the fields that we need from the
server to the client app.
Look again at the above example, where we were searching for the author’s information through a specific ID, the blog posts written by the
author, and the three most recent blog topics. The requested query in GraphQL is organized to get the information precisely.
The server will provide a JSON response that has been specifically requested. It has returned the author’s name, the posts composed by
them, and the previous three topics created by the author – that’s it. There were no multiple round trips to the server, no over-fetching, and
no under-fetching of data. Let’s have a quick look at the graphical representation of the differences between the two.
11
NOTE :
The question isn’t necessarily which one is better to use, but which one is better
to use for specific circumstances
The best way to evaluate GraphQL, REST, or any other technology is to figure
out your constraints based on the problem you are going to solve.
13
Performance
● Strongly typed, so it is possible to have better error messages.
● Enables client-specified queries, which allows the server to have better understand of clients' needs.
● Data model is hierarchical, then can retrieve data from multiple sources with only one request.
● The consumers can inspect the types and fields at runtime (introspection).
● Reduce the number of versioning, since fields can be deprecated and adding new ones do not lead to a
relevant change in the API.
14
Utility
Why Use GraphQL?
Strongly-typed Schema
All the types (such as Boolean, String, Int, Float, ID, Scalar) supported by the API are specified in the schema in GraphQL
Schema Definition Language (SDL), which helps determine the data that is available and the form it exists in. This,
consequently, makes GraphQL less error-prone, and more validated, and provides auto-completion for supported IDE/editors.
No Over-Fetching or Under-Fetching
With GraphQL, developers can fetch only what is required. Nothing less, nothing more. This solves the
issues that arise due to over-fetching and under-fetching.
Saves Time and Bandwidth
GraphQL allows making multiple resources request in a single query call, which saves a lot of time and bandwidth
by reducing the number of network round trips to the server. It also helps to save waterfall network requests, where
you need to resolve dependent resources on previous requests.
15
Schema Stitching for Combining Schemas
Schema stitching allows combining multiple, different schemas into a single schema. In a microservices architecture,
where each microservice handles the business logic and data for a specific domain, this is very useful. Each
microservice can define its own GraphQL schema, after which you’d use schema stitching to weave them into one that is
accessed by the client.
Versioning Is Not Required
With GraphQL, there is no need to maintain versions. The resource URL or address remains the same. You can add new
fields and deprecate older field
16
When to Use GraphQL
GraphQL works best for the following scenarios:
● Apps for devices such as mobile phones, smartwatches, and IoT devices, where bandwidth usage matters.
● Applications where nested data needs to be fetched in a single call.
○ For example, a blog or social networking platform where posts need to be fetched along with nested
comments and commenters details.
● Composite pattern, where application retrieves data from multiple, different storage APIs
○ For example, a dashboard that fetches data from multiple sources such as logging services,
backends for consumption stats, third-party analytics tools to capture end-user interactions.
17
Security
There is 9 ways to secure your GraphQL API :
1. Authentication
2. Authorization
3. Mitigate malicious queries
4. Limit API discoverability
5. Batch requests
6. Observability
7. Monitoring
8. Performance alerts
9. Managing graph access
For more details :
https://www.apollographql.com/blog/graphql/security/9-ways-to-secure-your-graphql-api-security-checklist/18
Implementation
Setting up the Service
“ Add this two dependencies in pom.xml”
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version> 19
</dependency>
Writing the Schema (expl) :
1- Create a text file in resources folder : “filename.graphqls”
schema{
2- The file must be in thisquery
form: :Query
}
type Query {
queyName : result type
exp :
getAllUsers : [User]
}
type “entity”{
fields of entity (expl) :
id : String
FirstName: String
.
.
.
.
}
20
Code in controller :
1- Define the path of the file graphQL and instance of GraphQL:
@Value("classpath:users.graphqls")
private Resource schemaResource; - In the @PostConstruct method the bean is fully initialized and
you can use the dependencies.
private GraphQL graphQL; - Because this is the contract that guarantees that this
method will be invoked only once in the bean lifecycle. It may
2- Method loadSchema() : happen (though unlikely) that a bean is instantiated multiple
times by the container in its internal working, but it guarantees
that @PostConstruct will be invoked only once.
@PostConstruct
public void loadSchema() throws IOException {
File schemaFile = schemaResource.getFile();
TypeDefinitionRegistry registry = new SchemaParser().parse(schemaFile);
RuntimeWiring wiring = buildWiring();
GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(registry, wiring);
graphQL = GraphQL.newGraphQL(schema).build(); 21
}
3- Method buildWiring() :
private RuntimeWiring buildWiring() {
DataFetcher<List<User>> fetcher1= data->{
return (List<User>) userRepository.findAll();
};
return RuntimeWiring.newRuntimeWiring().type("Query",typeWriting->
typeWriting.dataFetcher("getAllUsers", fetcher1)).build();
4- And finally we write the API :
@PostMapping("/getAll")
public ResponseEntity<Object> getAll(@RequestBody String query){
ExecutionResult result = graphQL.execute(query);
return new ResponseEntity<Object>(result, HttpStatus.OK);
}
22
Note
You define and use a Query only when you will get Data from Server
(read only)
22
Mutation
Writing your mutation type
Just like last time, when we created our own Query type, it’s now time to create a type called Mutation:
type Mutation {
createArticle(input: CreateArticleInput!): Article!
updateArticle(input: UpdateArticleInput!): Article!
deleteArticle(id: Int!): Int!
createProfile(input: CreateProfileInput!): Profile!
updateProfile(input: UpdateProfileInput!): Profile!
deleteProfile(id: Int!): Int!
createComment(input: CreateCommentInput!): Comment!
deleteComment(id: Int!): Int! 22
Defining custom inputs
!!! The most important difference is that we start by writing input rather than type
input CreateArticleInput {
input UpdateArticleInput {
id: Int!
title: String!
title: String!
text: String!
text: String!
}
authorId: Int!
22
Class Input implements GraphQLInputType
@Data
@Data
@NoArgsConstructor
@AllArgsConstructor
@NoArgsConstructor
public class CreateArticleInput implements
GraphQLInputType
@AllArgsConstructor
{
public class UpdateArticleInput implements
@Override GraphQLInputType
public String getName() {
return firstName; {
}
@Override
public String getName() {
return firstName;
private String title; }
private String text; private Long id;
private Long authorId; private String title;
} private String text;
22
}
Implement The Resolver :
Class Resolver implements GraphQLQueryResolver, GraphQLMutationResolver
@Component
@AllArgsConstructor
public class MutationResolver implements
GraphQLMutationResolver { @Transactional
private ArticleRepository public Article updateArticle(UpdateArticleInput
articleRepository; input) {
private CommentRepository Article article =
commentRepository; articleRepository.findById(input.getId()).orEls
private ProfileRepository eThrow(ArticleNotFoundException::new);
profileRepository; article.setText(input.getText());
article.setTitle(input.getTitle());
@Transactional return article;
public Article }
createArticle(CreateArticleInput input) {
return
articleRepository.saveAndFlush(new
Article(null, input.getTitle(),
input.getText(), input.getAuthorId()));
}
22
}
● Method deleteArticle() can have a type deleteArticleInput that contains just n
fields but here it’s passed us parameter :
@Transactional
public int deleteArticle(Long id) {
return articleRepository.deleteById(id);
22
GraphQL + Angular ? Apollo
Introduction
Apollo Angular is the ultra-flexible, community driven GraphQL client for Angular,
JavaScript, and native platforms. It is designed from the ground up to make it easy to
build UI components that fetch data with GraphQL. To get the most value out of Apollo
Client, you should use it with one of its view layer integrations.
22
Advantages
1. Incrementally adoptable, so that you can drop it into an existing JavaScript app and start using
GraphQL for just part of your UI.
2. Universally compatible, so that Apollo works with any build setup, any GraphQL server, and
any GraphQL schema.
3. Simple to get started with, so you can start loading data right away and learn about advanced
features later.
4. Inspectable and understandable, so that you can have great developer tools to understand exactly
what is happening in your app.
5. Built for interactive apps, so your users can make changes and see them reflected in the UI
immediately.
6. Small and flexible, so you don't get stuff you don't need. The core is under 12kb compressed.
7. Community driven, because Apollo is driven by the community and serves a variety of use
cases. Everything is planned and developed in the open. 22
Apollo + Angular
Apollo is lovingly designed to work nicely with all of the tools used by today's Angular developers. Here are some in particular:
● Angular Schematics: Apollo Angular supports ng-add and ng-update
● NativeScript: Apollo works out of the box in NativeScript.
● Angular Router: Apollo Client is completely router-independent, which means you can use it with any version of Angular Router
or any other routing library for Angular. It's even easy to set up server-side rendering.
● Ionic: Apollo works great with Ionic Framework apps written in Angular
22
GraphQL server + Apollo
Apollo works with every GraphQL server implementation, for every language. It
doesn't impose any requirements on your schema either! If you can send a query to a
standard GraphQL server, Apollo can handle it.
22
Let’s Start
Installation with Angular Schematics :
ng add apollo-angular
One thing you need to set is the URL of your GraphQL Server, so open src/app/graphql.module.ts and set uri variables:
example : const uri = 'http://localhost: 8080/graphql; // our GraphQL API
Done! You can now create your first query
22
Installation without Angular Schematics
If you want to setup Apollo without the help of Angular Schematics, first, let's install some packages:
Run :
npm install apollo-angular @apollo/client graphql
● @apollo/client: Where the magic happens
● apollo-angular: Bridge between Angular and Apollo Client
● graphql: Second most important package
22
The @apollo/client package requires AsyncIterable so make sure your tsconfig.json includes esnext.asynciterable:
{
"compilerOptions": {
// ...
"lib": [
"es2017",
"dom",
:
"esnext.asynciterable"
]
}
}
22
Great, now that you have all the dependencies you need, let's create your first Apollo Client.
In our app.module.ts file use APOLLO_OPTIONS token to configure Apollo
import {HttpClientModule} from '@angular/common/http';
import {APOLLO_OPTIONS} from 'apollo-angular';
import {HttpLink} from 'apollo-angular/http';
import {InMemoryCache} from '@apollo/client/core';
@NgModule({
imports: [BrowserModule, HttpClientModule],
providers: [
{
provide: APOLLO_OPTIONS,
useFactory: (httpLink: HttpLink) => {
return {
cache: new InMemoryCache(),
link: httpLink.create({
uri: graphQL API',
}),
};
},
deps: [HttpLink],
},
})
], 22
export class AppModule {}
Implementation of Query and Mutation in angluar service
Query :
const allUsers = gql`query{
listUser() {
getAllUsers {
return this.apollo.watchQuery<any>({
id
query: allUsers
login
}).valueChanges
firstName
}
lastName
email
}}`;
22
Mutation
Update User:
const update = gql` mutation updateUser(id, firstName, lastName) {
updateUserDetails($user: UpdateProfileInput!){ let user = { id, firstName, lastName }
updateUserDetails(user : $user){ return this.apollo.mutate({
id mutation: update,
firstName variables: {
lastName user
} }
}`; });
}
const delUser = gql`mutation removeUser ($user:
Delete User : (Next Page) DeleteUserInput!) {
removeUser(user: $user) {id}}` 22
deleteUser(id) {
let user = { id }
return this.apollo.mutate({
mutation: delUser,
variables: {
user
},
optimisticResponse: {},
update: (cache) => {
const existingUsers: any = cache.readQuery({ query: allUsers });
const listUsers = existingUsers.filter(u => (u.id !== user.id));
cache.writeQuery({
query: allUsers,
data: { listUser: listUsers }
});
},
}).subscribe(({ data }) => {
console.log('got data', data);
}, (error) => {
console.log('there was an error sending the query', error);});}}
22