RESTful web services have been providing basic support for simple query structures for years. However, these services don’t provide granular control over data that allow developers to exercise flexibility without creating a huge collection of unnecessary calls.
GraphQL built by Facebook is a query language, for APIs or let’s say it is one of the most modern ways of building and querying APIs. It lets developers choose the types of requests they want to make and receive the information they require in a single request.
In this article, we will build a simple GraphQL server with Spring Boot.
Getting started with Spring Boot
Firstly, let’s create a simple Spring Boot application using https://start.spring.io/ with Maven.
Adding MAVEN dependencies
As a first step, we need to add the following dependencies using Spring Initializr platform or directly into our POM.XML :
- graphql-spring-boot-starter is used for enabling GraphQL servlet and exposing its endpoint at /graphql. It initializes GraphQLSchema bean.
- graphql-java enables you to write schema with GraphQL schema language which is simple to understand.
- graphiql-spring-boot-starter provides a user interface that we gonna use to test our GraphQL queries and view query definition.
1 - Create a JPA Entity and Repository
Let’s create a simple Entity named ‘Client’ and it’s its adequate JPA Repository. We will use LOMBOK to auto-generate getters, setters and the constructors...
Let's start by adding some dependencies(JPA, H2, and lombok) in our POM.XML.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
That's the client entity :
and here is the adequate JPA repository of client model :
2 - GraphQl Schema
GraphQL comes with its own language called Schema Definition Language (SDL). The schema definition is a description of all the objects, queries and mutations that we want to expose to the clients.
To implement our GraphQL schema we need to create the folder graphql in a classpath directory (typically src/main/resources) and create a file clientql.graphqls under that folder. Note that, the name of the file could be any name of your choice. Just make sure to keep the file extension as .graphqls.
Here is the corresponding GraphQL schema :
In our schema, we have an object called Client which is our domain object. The type Query represents the queries available to the clients could send to the GraphQL server to fetch data. A GraphQL client query the server by including in the request all the result attributes that he want to retrieve, so, the structure of the query and the result is the same. This is important in the GraphQL world, because we always get back the result that we expect.
The type Mutation represents the queries that are used to perform write operations on the data.
3 - Root Query
Query or Mutation objects are root GraphQL objects, they don’t have any associated data class. In such cases, the resolver classes would implement GraphQLQueryResolver or GraphQLMutationResolver. These resolvers will be searched for methods that map to fields in their respective root types.
Let’s define root resolvers for the Client. We need to create two folders called Query and Mutation where we will define successively our resolvers.
But before we need to define a service that will contains all methods called by Query and Mutation resolvers.
Now, let’s create query resolver :
In this class, we have methods to get a single Client object and a list of Client objects. Note that, we have defined these methods in our schema above (GraphQL will search for resolvers methods having the same name as those defined in the schema or having the same name prefixed by "get").
Next, our mutation resolver will be defined as below :
In this class, we only have one method to create a Client object and this corresponds to type Mutation in our schema definition.
4 - Testing the application
If everything is implemented correctly, the result of the run will be a magnificent Interface (GraphiQL) that allows us to test our queries and also to get generated documentation of our endpoint. It could be accessed at this URL : http://localhost:8080/graphiql.
PS : Don’t be confused between /graphql which is the url where your GraphQL resources are exposed and /graphiql (with an "i") which is the web client applixation used to test those resources
Now, let’s play with some queries
First, we create a client :
The result of this mutation returns the client’s ID as specified in our query (the return type specified in our schema is the Client Object):
Then, we run some ‘Query’ queries to fetch data from the database :
The query above retrieves a client by its ID.
While this one, retrieves the list of all clients.
GraphQL came with a lot of cool features and it's becoming more and more adopted, it's gonna "maybe" be more used than REST in a relatively near future. That been said, you have to be very careful when designing your queries, because a bad design can quickly cause you big performance issues.