This article is a walk though a GraphQL application using Spring Boot. We will cover the basics of GraphQL and then we will show how to code and test an example application.
GraphQL is a query language known for having a highly typed schema, and for providing developers with the information they need for creating new applications and transferring data. The GraphQL schema identifies input parameters and possible answers quite clearly, reducing the confusion and rework often required with other API models to ensure consistent results.
Schemas, resolvers and other common GraphQL terms
API developers use GraphQL to create a schema that describes all the possible data that clients might query via the specified service.
A GraphQL schema consists of object types that define the types of objects that can be queried and the types of fields available within it. As queries are received, GraphQL validates them against the schema, then executes them.
The API developer adds the schema fields to a function called resolver. During execution, the resolver generates the value.
From the client’s point of view, GraphQL deals mainly with queries and mutations. Compared with the standard CRUD model (create, read, update and delete), a Query would be equivalent to read. All other elements (create, update and delete) are handled by Mutation.
Set up the Spring Boot Project
Firstly, we will create our Spring Boot project. When using the Spring Boot Initializr, simply add the Web dependency and the GraphQL dependency. Click on Add Dependencies and download the project.

Next, import the project to your IDE.
Defining our Schema
Next step will be defining the GraphQL schema which follows the Model of our Domain. The GraphQL specification defines a human-readable schema definition language (or SDL) that you use to define your schema and store it as a string. Here is our schema:
type Book { id: ID! title: String author: Author } type Author { id: ID! name: String books: [Book] } type Query { allBooks: [Book] findOne(id: ID!): Book allAuthors: [Author] } type Mutation { createBook( title: String author: String): Boolean! }
As you can see, our Schema defines two main types: Book and Author. Besides, the schema includes a set of Query and one Mutation.
The Query allBooks returns the list of Books. The query findOne return a Book by its id. Finally, the query allAuthors returns all Book Authors.
The Mutation createBook adds a new Book using as input parameter the Title and the Author.
For learning purpose, we will use a simple set of objects stored in memory. Therefore, we will add the following Java Records to our project. Here is the Author Record:
public record Author(Integer id, String name) { }
Next, here is the Book Record:
public record Book(Integer id, String title, Author author) { }
Records, available since Java 14, are immutable data classes that require only the type and name of fields. Using records, a public constructor, with an argument for each field, is generated for us. Besides, we also receive public getters methods out of the box.
Coding the Controller
Client accessing our applications require a Controller. Here is the BookController:
@Controller public class BookController { private final BookRepository bookRepository; public BookController(BookRepository bookRepository) { this.bookRepository = bookRepository; } @SchemaMapping(typeName = "Query",value = "allBooks") public List<Book> findAll() { return bookRepository.findAll(); } @QueryMapping public Book findOne(@Argument Integer id) { return bookRepository.findOne(id); } @MutationMapping public boolean createBook(@Argument("title") String title, @Argument("author") String author) { return bookRepository.add(title, author); } }
To start the Spring Boot application, we will also add a basic Application Class:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Finally, here is the application.properties:
spring.graphql.graphiql.enabled=true spring.graphql.cors.allowed-origins=* spring.graphql.schema.printer.enabled=true
With the above properties we will be able to activate the GraphQL UI to test our example. Also we enabled cross-origin resource sharing (CORS) and schema debug.
Testing the application
Having enabled the UI of GraphQL, start the application and connect to http://localhost:8080/graphiql?path=/graphql#
Next, you can Query allBooks using the following Query:
query { allBooks { title author { name } } }
Here is the output of our query in the GraphiQL:

To find a single Book, you can use the findOne Query which requires an integer (id) as parameter:
query { findOne(id: 1) { title author { name } } }
Finally, to add a book using the mutation CreateBook:
mutation CreateBook($title:String, $author:String) { createBook(title: $title, author: $author) } { "title": $title, "author": $author }
As you can see from the above mutation, we are using variables in our mutation expression. To allow the GrapQL server to resolve those variables, we will set them as Query Variables:

Conclusion
This article was a walk through an example GraphQL application in Spring Boot. You can find the source code for this tutorial here: https://github.com/fmarchioni/masterspringboot/tree/master/graphql/graphql-demo