Skip to main content

Getting started with Spring for GraphQL

In this tutorial, you will create a GraphQL server in Java using Spring for GraphQL in 3 minutes. It requires a little Spring and Java knowledge. While we give a brief introduction to GraphQL, the focus of this tutorial is developing a GraphQL server in Java.

If you're looking to learn more after this tutorial, we (the maintainers) have written a book! GraphQL with Java and Spring includes everything you need to know to build a production ready GraphQL service with Spring for GraphQL, the official Spring integration built on top of the GraphQL Java engine. It's available on Leanpub and Amazon.

A very short introduction to GraphQL

GraphQL is a query language to retrieve data from a server. It is an alternative to REST, SOAP or gRPC.

Let's suppose we want to query the details for a specific book from an online store backend.

With GraphQL you send the following query to the server to get the details for the book with the id "book-1":

query bookDetails {
bookById(id: "book-1"){
id
name
pageCount
author {
firstName
lastName
}
}
}

This is not JSON (even though it looks deliberately similar), it is a GraphQL query. It basically says:

  • query a book with a specific id
  • get me the id, name, pageCount and author from that book
  • for the author, I want to know the firstName and lastName

The response is normal JSON:

{
"bookById": {
"id":"book-1",
"name":"Harry Potter and the Philosopher's Stone",
"pageCount":223,
"author": {
"firstName":"Joanne",
"lastName":"Rowling"
}
}
}

One very important property of GraphQL is that it is statically typed: the server knows exactly the shape of every object you can query and any client can actually "introspect" the server and ask for the "schema". The schema describes what queries are possible and what fields you can get back. (Note: when we refer to schema here, we always refer to a "GraphQL Schema", which is not related to other schemas like "JSON Schema" or "Database Schema")

The schema for the above query looks like this:

type Query {
bookById(id: ID): Book
}

type Book {
id: ID
name: String
pageCount: Int
author: Author
}

type Author {
id: ID
firstName: String
lastName: String
}

This tutorial will focus on how to implement a GraphQL server with this schema in Java.

We've barely scratched the surface of what's possible with GraphQL. Further information can be found on the official GraphQL page.

GraphQL Java Overview

GraphQL Java is the Java (server) implementation for GraphQL. There are several repositories in the GraphQL Java Github org. The most important one is the GraphQL Java Engine which is the basis for everything else.

The GraphQL Java Engine is only concerned with executing queries. It doesn't deal with any HTTP or JSON related topics. For these aspects, we will use Spring for GraphQL which takes care of exposing our API via Spring Boot over HTTP.

The main steps of creating a GraphQL Java server are:

  1. Defining a GraphQL Schema.
  2. Deciding on how the actual data for a query is fetched.

Our example API: getting book details

Our example app will be a simple API to get details for a specific book. This is in no way a comprehensive API, but it is enough for this tutorial.

Create a Spring Boot app

The easiest way to create a Spring Boot app is to use the Spring Initializr.

Select:

  • Gradle Project
  • Spring Boot 3
  • Java 17 or higher

For the project metadata, use:

  • Group: com.graphqljava.tutorial
  • Artifact: bookDetails

For dependencies, select:

  • Spring Web, and
  • Spring for GraphQL

Then click on Generate for a ready to use Spring Boot app. All subsequently mentioned files and paths will be relative to this generated project.

Spring for GraphQL adds many useful features including loading schema files, initializing GraphQL Java, and simplifying data fetching with controller annotations.

Schema

Add a new file schema.graphqls to src/main/resources/graphql with the following content:

type Query {
bookById(id: ID): Book
}

type Book {
id: ID
name: String
pageCount: Int
author: Author
}

type Author {
id: ID
firstName: String
lastName: String
}

This schema defines one top level field (in the type Query): bookById which returns the details of a specific book.

It also defines the type Book which has the fields: id, name, pageCount and author. author is of type Author, which is defined after Book.

The Domain Specific Language (shown above) used to describe a schema is called the Schema Definition Language or SDL. More details about it can be found here.

Source of the data

To simplify the tutorial, book and author data will come from static lists inside their respective classes. It is very important to understand that GraphQL doesn't dictate in any way where the data comes from. This is the power of GraphQL: it can come from a static in-memory list, from a database or an external service.

Create the Book class

Add the following to bookDetails/Book.java

package com.graphqljava.tutorial.bookDetails;

import java.util.Arrays;
import java.util.List;

record Book(String id, String name, int pageCount, String authorId) {

private static List<Book> books = Arrays.asList(
new Book("book-1", "Harry Potter and the Philosopher's Stone", 223, "author-1"),
new Book("book-2", "Moby Dick", 635, "author-2"),
new Book("book-3", "Interview with the vampire", 371, "author-3")
);

public static Book getById(String id) {
return books.stream().filter(book -> book.id().equals(id)).findFirst().orElse(null);
}

}

Create the Author class

Add the following to bookDetails/Author.java

package com.graphqljava.tutorial.bookDetails;

import java.util.Arrays;
import java.util.List;

record Author(String id, String firstName, String lastName) {

private static List<Author> authors = Arrays.asList(
new Author("author-1", "Joanne", "Rowling"),
new Author("author-2", "Herman", "Melville"),
new Author("author-3", "Anne", "Rice")
);

public static Author getById(String id) {
return authors.stream().filter(author -> author.id().equals(id)).findFirst().orElse(null);
}

}

Adding code to fetch data

Spring for GraphQL provides an annotation-based programming model to declare handler methods to fetch the data for specific GraphQL fields.

Add the following to bookDetails/BookController.java

package com.graphqljava.tutorial.bookDetails;

import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;

@Controller
class BookController {

@QueryMapping
public Book bookById(@Argument String id) {
return Book.getById(id);
}

@SchemaMapping
public Author author(Book book) {
return Author.getById(book.authorId());
}

}

The @QueryMapping annotation binds this method to a query, a field under the Query type. The query field is then determined from the method name, bookById. It could also be declared on the annotation. Spring for GraphQL uses RuntimeWiring.Builder to register the handler method as a graphql.schema.DataFetcher for the query field bookById.

In GraphQL Java, DataFetchingEnvironment provides access to a map of field-specific argument values. Use the @Argument annotation to have an argument bound to a target object and injected into the handler method. By default, the method parameter name is used to look up the argument. The argument name can be specified in the annotation.

The @SchemaMapping annotation maps a handler method to a field in the GraphQL schema and declares it to be the DataFetcher for that field. The field name defaults to the method name, and the type name defaults to the simple class name of the source/parent object injected into the method. In this example, the field defaults to author and the type defaults to Book. The type and field can be specified in the annotation.

For more, see the documentation for the Spring for GraphQL annotated controller feature.

That's all the code we need! Let's run our first query.

Running our first query

Enable the GraphiQL Playground

GraphiQL is a useful visual interface for writing and executing queries, and much more. Enable GraphiQL by adding this config to the application.properties file.

spring.graphql.graphiql.enabled=true

This will enable GraphiQL at the path /graphiql by default. You can change this path by configuring spring.graphql.graphiql.path.

Boot the application

Start your Spring application.

Navigate to http://localhost:8080/graphiql or your custom URL.

Run the query

Type in the query and hit the play button at the top of the window.

query bookDetails {
bookById(id: "book-1") {
id
name
pageCount
author {
id
firstName
lastName
}
}
}

You should see a response like this. GraphQL response

We have built a GraphQL server and run our first query! With the help of Spring for GraphQL features, we were able to achieve this with only a few lines of code.

Further reading

Book

If you want to learn more, we (the maintainers) have written a book! GraphQL with Java and Spring includes everything you need to know to build a production ready GraphQL service with Spring for GraphQL and GraphQL Java.

Learn first-hand from the founder of GraphQL Java and co-author of Spring for GraphQL. The book is suitable for beginners and also includes advanced topics for intermediate readers. The book is available on Leanpub and Amazon.

Sample source code

The source code for this tutorial can be found on GitHub.

Documentation

Read the GraphQL Java documentation.

More Spring for GraphQL examples

See the Spring for GraphQL documentation for more samples.

Tutorials written by the community

If you'd like to see a longer tutorial with pure GraphQL Java and without any framework such as Spring, Benjamin Habegger has written a detailed tutorial.

We welcome tutorials written by the community. If you'd like to see a tutorial here, please post on GitHub Discussions.

GitHub Discussions

We also use GitHub Discussions for any questions or problems.