In this article we will discuss about how to build a basic backend API with Spring Boot and GraphQL and how it is different from the traditional REST API that we are used to building.
GraphQL as we know has been hyped up as the next big thing and a revolutionary alternative to REST but it has its own advantages as well as limitations. So its not all doom and gloom for REST.
REST(Representational State Transfer) is an architectural style or a protocol which has been used to develop RESTful Web Services. We have endpoints which give access to some resources and then with that data (hyperlinks) we make more requests to more endpoints to get the necessary data.
In the below example we have a sample relation data between customers and transactions. We have 3 endpoints which expose these data to the client.
Limitations of REST
- OverFetching : When using a REST API you get a complete data set as a response including unnecessary data. It means you might need only the name and the email of a customer whereas you get the entire customer object in response thus increasing the size of the payload.
- Multiple Requests and Multiple Endpoints : Some times in case of relational data we need to have multiple endpoints in the API. The client which requires such data will need to make multiple requests to get all the necessary data. This is also under fetching data.
- Maintenance and Versioning : When we make changes to the API we will version it in different paths and the client also has to accommodate the structural changes in response. This leads to supporting legacy API as well as the new API.
GraphQL is a Query Language which was developed by Facebook in 2012 and later Open Sourced in 2015. Facebook needed a robust and performant system to address the huge number of requests coming in especially in mobile devices as well as regions where internet connectivity was a bit too slow.
- Declarative Data Fetching : The Client will only request for data it needs . No more over fetching or under fetching.
- Single endpoint : The client will always hit a single endpoint with the requested data.
- Flexibility and Maintenance : Even if there are many structural changes over the years there is no need for versioning as the client will only request what it needs and the server will respond with the requested data.
As we see in the above example there is only one endpoint and in the request body we send a GraphQL query . The GraphQL query language looks similar to JSON although it is not. The query varies for each request and only the requested fields get sent back in the payload.
The fields that the client can request should be shared in advance by the Server as a contract somewhat similar to a WSDL file in SOAP requests. This file here in the context of GraphQL is the SDL (Schema Definition Language).
From now onwards we will explore the concepts of GraphQL along with building a simple backend API with Spring Boot.
The most important part of developing the API is the schema. We will have to decide what fields and what methods the client should have access to.
We will build a Movie API , get a list of movies with its reviews and also add reviews to a movie. Below is the schema for that.
Queries and Mutations :
There are 4 types in the above schema : Query , Mutation , Movie and Review.
Query as the name suggests is what all methods the client can use to retrieve data from the server.
Mutation is basically if you want to create,update or delete anything from the server.
In the REST world these are handled by GET, POST, PUT, DELETE in the request itself. But in GraphQL it will always be a POST request from the client with the request body having the details of the query or mutation.
In the type Query we expose the movies method which gives a list of movies as indicated by the array symbol for the return type. The second method is movieById(id) which is used to query a movie by giving an id and it returns that Movie . The exclamation (!) mark indicates that the field is a mandatory field.
In the type Mutation we expose two mutation methods create movie where the client passes in the name of the movie and a review of it and we return a list of all the movies with the newly created one added to the list. The add Review method allows to add review to an existing Movie by giving the movie id and a review comment.
The remaining two types type Movie and type Review in the schema file are the two objects associated and the list of fields that the client can get from the request. These two should have POJO classes in the project.
We will create a simple Spring Boot starter project and add the following maven dependencies for GraphQL
Now we will place the above created schema file in src/main/resources/graphql folder. The file should be saved with the extension .graphqls in order to be recognized by spring boot. We also create two pojo classes for Movie and Review respectively.
Spring Boot will now look for resolver classes to call the methods from query and mutation in the schema file .
Query Resolver :
This resolver has to implement the GraphQLQueryResolver in order to be recognized as query resolvers. It has to have all methods from schema file type Query with same name and same return type. The get prefix gets ignored while matching method names from schema file to this file.
Similarly the mutation resolver should have all the exposed methods in schema file which create/update/delete data. This class implements a Mutation Resolver.
In this class we are simulating a database fetch to keep it simple and nothing more. The methods are called from resolver classes.
Note that the two POJO classes has to have all the fields mentioned in the schema file with same name and type. Below are the Movie and Review POJO.
We are all set . Launch the application and head over to localhost:8080/graphiql . We will have our own playground here where we can test our endpoint by making query and mutation requests.
The left side we have the request and the right side we have the response. The query has to follow a particular syntax as shown above. We are getting the id ,name of movies and the review id and review Comment. There are some rules here that if our sub type has further fields we have to mention atleast one field in it. For example we have to mention either review Id or review Comment otherwise we should remove reviews from our query.
Here is an example where we only get the movie name and review comment without the id’s. Note that how simple it is to request for only the data that we want and not clutter the payload with all data.
Here is an example of a mutation where we add review to movie with id :3. To fetch the data we give the movie id , name and review Comment. In response we get the movie with our newly added review comment.
We created a schema file with Queries, Mutations and the Movie and Review Types.
We created query and mutation resolvers to fetch data for the queries and mutations defined above.
In the graphiql playground we were able to fetch data dynamically.
GraphQL is still in the growing stage . It is not as widely used as REST or tried and tested as much but is definitely one for the future. There are growing analytics and visualization tools being built by the community to improve graphQL. It has a decent learning curve and nested queries might be confusing for some at the beginning. But all in all if a high performant API has to be built for a large user base in the future graphQL should get the nod.
Thanks for reading and please leave your queries and views in the comments.
The entire project is available at the below github link