This article is going to introduce you to Spring Boot with GraphQL. We’ll walk through a simple beer app to show you what it can do.
So you have built this really sweet API with all the gets
, puts
, and deletes
you can think of. Your baby is just beautiful the way it is, right? Well, maybe developer Joe thinks your baby is fat.
WHAT?!
The RESTful calls you have are bringing back way too much information. In other scenarios, the calls don’t do enough, and your baby is left crying because it needs more to play with.
Well, this is where the power of GraphQL comes in.
Graph-What?
The new kid on the block in querying APIs is called GraphQL. Okay, but what is it? Well, the definition pulled directly from the GraphQL site is:
"GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients 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."
Uh-huh. Great. But what is it?
GraphQL is a tool that allows you to get what you want and only what you want from your existing API. You can eliminate the things you don’t need or care about in implementation. It can also offer a one place, one call to join what would otherwise be multiple REST calls to get the same information. GraphQL can significantly speed up performance and simplify coding.
Here is a video introduction to GraphQL, as well as some more information on why it's cool and what you can do with it.
Not In This Article
This article is not going to go into an in-depth explanation about Spring Boot (nor Spring Boot’s complete awesomeness). We will also avoid the arguments about development usage for and against it versus things like NodeJS or .NET.
That said, this article does assume that you are at least familiar with Spring Boot and Java already. It is more about how you can be a part of the “cool” crowd and implement GraphQL in your Java project.
Let’s Doll Up Your GraphQL Baby with Spring Boot
First things first, you must either have an existing API built into Spring Boot, or you can conveniently use the Beer App provided at the end of this article.
Next, you will need to add these into your pom if not already there.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- GraphQL -->
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>7.0.1</version>
</dependency>
<!-- to embed GraphiQL tool -->
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>7.0.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
Next, in your application.properties
file add the following:
graphql.servlet.mapping=/graphql
graphql.servlet.enabled=true
graphql.servlet.exception-handlers-enabled= true
graphql.servlet.contextSetting= PER_REQUEST_WITH_INSTRUMENTATION
# GraphiQL (not GraphQL!)
graphiql.mapping= /graphiql
graphiql.endpoint.graphql= /graphql
graphiql.static.basePath= /
graphiql.enabled= true
graphiql.pageTitle= GraphiQL
graphiql.props.resources.defaultQuery= schema.graphqls
graphiql.props.variables.editorTheme= "solarized light"
These settings tell GraphQL where everything is set up. GraphiQL is a graphical interface that you can use to test out your GraphQL queries.
This is an important feature that will help you get familiar with using GraphiQL (not a typo!). Keep in mind that if you are using an existing API, you will need to add exceptions to your security filtering rules or log in first Here is more information on how to use GraphiQL.
Next, let's look at the mutators and query classes. A mutation
is something that will change data. So this is your creating, updating, or deleting of data. The query classes are just that: methods that query the database or “get” data.
EntityMutationResolver.java:
@Component
public class EntityMutationResolver implements GraphQLMutationResolver {
private final BrewerService brewerService;
private final BeerService beerService;
/**
* Constructor that takes instances of injected service bean for all entities
*
* @param brewerService An instance of Spring managed BrewerService bean
* @param beerService An instance of Spring managed BeerService bean
*/
public EntityMutationResolver( BrewerService brewerService,
BeerService beerService) {
this.brewerService = brewerService;
this.beerService = beerService;
}
/**
* Adds a Brewer entity
*
* @param name Name of the Brewer
* @return An instance of Brewer if created successfully
* @throws Exception If any occurred
*/
public Brewer addBrewer(String name) throws Exception {
Brewer brewer = new Brewer(name);
return brewerService.save(brewer);
}
The key here is that it implements GraphQLMutationResolver
.
Here, we define the methods that are described in the GraphQL schema. We’ll get to that more later.
EntityQueryResolver.java:
@Component
public class EntityQueryResolver implements GraphQLQueryResolver {
private final BrewerService brewerService;
private final BeerService beerService;
/**
* Constructor that takes instances of injected service bean for all entities
*
* @param brewerService An instance of Spring managed BrewerService bean
* @param beerService An instance of Spring managed BeerService bean
*/
public EntityQueryResolver(BrewerService brewerService,
BeerService beerService) {
this.brewerService = brewerService;
this.beerService = beerService;
}
/**
* Returns a Brewer for the given id
*
* @param id Primary key of the Brewer
* @return An instance of Brewer
*/
public Brewer getBrewerById(Long id) {
try {
Optional<Brewer> brewer = brewerService.findOne(id);
if (brewer.isPresent()) {
brewer.get().getbeers();
return brewer.get();
}
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
Here again, this class implements GraphQLQueryResolver
, which allows GraphQL schema to resolve these methods. Remember that these are Get
type methods returning data and not changing it.
GraphQL Schema
Now, it's time to configure GraphQL to know what methods and models are available. We do this by adding a schema.graphqls
file at the project’s root in the resources folder. It’s in the same place as the application.properties
file.
Below is the content we need:
type Brewer {
id: ID!
name: String!
beers: [Beer]!
}
type Beer {
id: ID!
title: String!
brewer: Brewer!
}
# Mutation: to add entities
type Mutation {
addBrewer(name: String!): Brewer!
addBeer(title: String!, brewerId:Int!): Beer!
}
# The Root Query for the application
type Query {
brewerById(id:Int): Brewer
beerById(id:Int): Beer
getAllBeers: [Beer]
}
Let’s break this down briefly:
- The
types
are the “models” for the objects. - The
mutation
is the data changing methods. - The
query
is the definition of methods available to pull data. - The exclamation point means the value cannot be empty.
- Brackets point to arrays. (Most developers will see this as straightforward.)
Go in and Run the Spring Boot Application with GraphQL
If you have problems, it's probably due to mismatching between the resolvers and the schema file. In a browser, go to localhost:8080/graphiql
, and it should show you something like this:
Congratulations! You did it. Now you are on your way to GraphQL greatness!
So this output is simply telling you what is available on your GraphQL. Remove what is there, and write these:
mutation addBrewery {
addBrewer(name:"Leinenkugel") {
id
name
}
}
mutation addBrewsky {
addBeer(title:"Summer Shandy", brewerId:1) {
id
title
}
}
query allBreweries {
getAllBeers {
id
title
brewer {
id
name
}
}
}
The mutation
word tells you what your GraphQL is going to do. Then, the addBrewery
is whatever you want it to be.
mutation addBrewery {
addBrewer(name:"Leinenkugel") {
id
name
}
}
The addBrewer
is the actual method that you are going to be calling. You pass fields inside the brackets.
Hint: the GraphiQL tool tells you what is available, what it is expecting, and the available fields for return. You must fill in what you want to be returned, or it will complain.
mutation addBrewery {
addBrewer(name:"Leinenkugel") {
id
name
}
}
The results are JSON:
{
"data": {
"addBrewer": {
"id": "1552",
"name": "Leinenkugel"
}
}
}
A Few Advantages of Spring Boot with GraphQL
Just think of it in this way: your API has a table return that typically returns 100 fields. Not efficient!
With GraphQL, you can specify that you only want a handful of fields. It will adjust the query to only request and return the fields you are looking for.
This also allows you to make simpler CRUD functions that only return everything but let GraphQL and the request define what you want from that implementation.
Combining REST calls; although no example is given here, you can combine multiple requests into a simplified request limiting the number of requests that a requester has to make to your API.
Conclusion
Although this article is not a complete discussion of what you can accomplish with GraphQL, it gives you a rough look at it in respect to Spring Boot. It will ultimately be a game-changer for many developers who want to stay at the top of their game. If you've found yourself intrigued with Spring Boot with GraphQL and would like to learn more, here is a course on the fundamentals of GraphQL that provides a more in-depth introduction to this query language.
Please feel free to post any questions or examples where you have used this. I’m looking forward to using this in the near future!
Top comments (2)
Thanks for sharing, very useful information!
"Cool Kids" don't use Spring Boot :)