- JDK 1.8+
- Maven
The main README contains information about the layers in this feature pack. You can use the wildfly-maven-plugin
to build and run the server with the feature pack, and deploy the quickstart war.
mvn wildfly:provision wildfly:dev
To view the schema, execute this command:
curl localhost:8080/quickstart/graphql/schema.graphql
GraphiQL is a UI tool that can be used to execute GraphQL queries. Open GraphiQL by navigating to
http://localhost:8080/quickstart/graphql-ui
in your browser. Queries that you should try out are listed below.
You will probably also notice that GraphiQL, based on the knowledge of the GraphQL schema, offers autocompletion!
Enter the following query to GraphiQL and press the play button:
query allFilms {
allFilms {
title
director
releaseDate
episodeID
}
}
Note: The equivalent query can be executed via curl by
curl -X POST localhost:8080/quickstart/graphql -d'{"query": "{allFilms{title director releaseDate episodeID}}"}'
Since our query contains all the fields in the Film class we will retrieve all the fields in our response. Since GraphQL API responses are client determined, the client can choose which fields it will require.
Let’s assume that our client only requires title
and releaseDate
making the previous call to the API
Over-fetching of unnecessary data.
Enter the following query into GraphiQL and hit the play button:
query allFilms {
allFilms {
title
releaseDate
}
}
Notice in the response we have only retrieved the required fields. Therefore, we have prevented Over-fetching.
Let's now try out a way how to retrieve one film my its id. It's implemented by this query:
@Query
@Description("Get a Films from a galaxy far far away")
public Film getFilm(@Name("filmId") int id) {
return service.getFilm(id);
}
Enter the following into GraphiQL and make a request.
query getFilm {
film(filmId: 1) {
title
director
releaseDate
episodeID
}
}
The film query method requested fields can be determined as such in our previous example. This way we can retrieve individual film information.
However, say our client requires both films with filmId 0 and 1. In a REST API the client would have to make two calls to the API. Therefore, the client would be Under-fetching.
In GraphQL it is possible to make multiple queries at once.
Enter the following into GraphiQL to retrieve two films:
query getFilms {
film0: film(filmId: 0) {
title
director
releaseDate
episodeID
}
film1: film(filmId: 1) {
title
director
releaseDate
episodeID
}
}
This enabled the client to fetch the required data in a single request.
Until now, we have created a GraphQL API to retrieve film data. We now want to enable the clients to retrieve the Hero data of the Film.
Review the following source-query in our FilmResource
class:
public List<Hero> heroes(@Source Film film) {
return service.getHeroesByFilm(film);
}
Enter the following into GraphiQL to retrieve the film and hero data.
query getFilmHeroes {
film(filmId: 1) {
title
director
releaseDate
episodeID
heroes {
name
height
mass
darkSide
lightSaber
}
}
}
The response now includes the heroes of the film.
Mutations are used when data is created, updated or deleted.
Review the following mutations in our FilmResource
class:
@Mutation
public Hero createHero(Hero hero) {
service.addHero(hero);
return hero;
}
@Mutation
public Hero deleteHero(int id) {
return service.deleteHero(id);
}
Enter the following into GraphiQL to insert a Hero:
mutation addHero {
createHero(hero: {
name: "Han",
surname: "Solo"
height: 1.85
mass: 80
darkSide: false
episodeIds: [4, 5, 6]
}
)
{
name
surname
}
}
By using this mutation we have created a Hero entity in our service.
Notice how in the response we have retrieved the name and surname of the created Hero.
This is because we selected to retrieve these fields in the response within the { }
in the mutation query. This can easily be a server side generated field that the client may require.
Let’s now try deleting an entry:
mutation DeleteHero {
deleteHero(id :3){
name
surname
}
}
Similar to the createHero
mutation method we also retrieve the name and surname of the hero
we have deleted which is defined in { }.
Queries can also be done on individual fields. For example, let’s create a method to query heroes by their last name.
Review the following snippet from the FilmResource class:
@Query
public List<Hero> getHeroesWithSurname(@DefaultValue("Skywalker") String surname) {
return service.getHeroesBySurname(surname);
}
By using the @DefaultValue
annotation we have determined that the surname value
will be Skywalker when the parameter is not provided.
Test the following queries with GraphiQL:
query heroWithDefaultSurname {
heroesWithSurname{
name
surname
lightSaber
}
}
query heroWithSurnames {
heroesWithSurname(surname: "Vader") {
name
surname
lightSaber
}
}
MicroProfile GraphQL enables clients to retrieve the exact data that is required preventing Over-fetching and Under-fetching.
The GraphQL API can be expanded without breaking previous queries enabling easy API evolution.