Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat= Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page.

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – All Access – NPI EA (cat= Spring)
announcement - icon

All Access is finally out, with all of my Spring courses. Learn JUnit is out as well, and Learn Maven is coming fast. And, of course, quite a bit more affordable. Finally.

>> GET THE COURSE
Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

End-to-end testing is a very useful method to make sure that your application works as intended. This highlights issues in the overall functionality of the software, that the unit and integration test stages may miss.

Playwright is an easy-to-use, but powerful tool that automates end-to-end testing, and supports all modern browsers and platforms.

When coupled with LambdaTest (an AI-powered cloud-based test execution platform) it can be further scaled to run the Playwright scripts in parallel across 3000+ browser and device combinations:

>> Automated End-to-End Testing With Playwright

Course – Spring Sale 2025 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our Spring Sale. All Courses are 25% off until 26th May, 2025:

>> EXPLORE ACCESS NOW

Course – Spring Sale 2025 – NPI (cat=Baeldung)
announcement - icon

Yes, we're now running our Spring Sale. All Courses are 25% off until 26th May, 2025:

>> EXPLORE ACCESS NOW

1. Introduction

GraphQL is a relatively new concept from Facebook. GraphQL is a query language to retrieve data from a server, as an alternative to REST, SOAP, or gRPC.

In this tutorial, we’ll learn how to set up a GraphQL server using Spring Boot so that we can add it to existing applications or use it in new ones.

2. What Is GraphQL?

Traditional REST APIs are built around managing server-managed resources, manipulated through standard HTTP verbs. While effective within this framework, they struggle when deviating from it or when clients require data from multiple resources simultaneously, often resulting in larger response sizes due to unnecessary data

GraphQL addresses these challenges by empowering clients to request precisely the data they need in a single query, facilitating navigation of child resources, and enabling multiple queries at once. This approach, resembling RPC (Remote Procedure Call), emphasizes named queries and mutations, allowing both API developers and consumers to control functionality and desired outcomes effectively.

For example, a blog might allow the following query:

query {
    recentPosts(count: 10, offset: 0) {
        id
        title
        category
        author {
            id
            name
            thumbnail
        }
    }
}

This query will:

  • request the ten most recent posts
  • for each post, request the ID, title, and category
  • for each post, request the author, returning the ID, name, and thumbnail

In a traditional REST API, this either needs 11 requests, one for the posts and 10 for the authors, or needs to include the author details in the post details.

2.1. GraphQL Schemas

The GraphQL server exposes a schema describing the API. This schema consists of type definitions. Each type has one or more fields, each taking zero or more arguments and returning a specific type.

The graph is derived from the way these fields are nested with each other. Note that the graph doesn’t need to be acyclic, cycles are perfectly acceptable, but it is directed. The client can get from one field to its children, but it can’t automatically get back to the parent unless the schema defines this explicitly.

An example GraphQL Schema for a blog may contain the following definitions describing a Post, the Author of the post, and a root query to get the most recent posts on the blog:

type Post {
    id: ID!
    title: String!
    text: String!
    category: String
    author: Author!
}

type Author {
    id: ID!
    name: String!
    thumbnail: String
    posts: [Post]!
}

# The Root Query for the application
type Query {
    recentPosts(count: Int, offset: Int): [Post]!
}

# The Root Mutation for the application
type Mutation {
    createPost(title: String!, text: String!, category: String, authorId: String!) : Post!
}

The “!” at the end of some names indicates that it’s a non-nullable type. Any type that doesn’t have this can be null in the response from the server. The GraphQL service handles these correctly, allowing us to safely request child fields of nullable types.

The GraphQL Service also exposes the schema using a standard set of fields, allowing any client to query for the schema definition ahead of time.

This allows the client to automatically detect when the schema changes and allows clients to adapt dynamically to how the schema works. One incredibly useful example is the GraphiQL tool, which allows us to interact with any GraphQL API.

3. Introducing GraphQL Spring Boot Starter

The Spring Boot GraphQL Starter offers a fantastic way to get a GraphQL server running in a very short time. Using autoconfiguration and an annotation-based programming approach, we need only write the code necessary for our service.

3.1. Setting up the Service

All we need for this to work is the correct dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-graphql</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Because GraphQL is transport-agnostic, we’ve included the web starter in our config. This exposes the GraphQL API over HTTP using Spring MVC on the default /graphql endpoint. Other starters can be used for other underlying implementations, such as Spring Webflux.

We can also customize this endpoint in our application.properties file if necessary.

4. Writing the Schema

The GraphQL Boot starter works by processing GraphQL Schema files to build the correct structure and then wires special beans to this structure. The Spring Boot GraphQL starter automatically finds these schema files.

We need to save these “.graphqls” or “.gqls” schema files under src/main/resources/graphql/** location, and Spring Boot will pick them up automatically. As usual, we can customize the locations with spring.graphql.schema.locations and the file extensions with spring.graphql.schema.file-extensions config properties.

The one requirement is that there must be exactly one root query and up to one root mutation. Unlike the rest of the schema, we can’t split this across files. This is a limitation of the GraphQL Schema definition, not the Java implementation.

5. Implementing Our Schema

Once we’ve written our schema, we need to be able to implement it in code. This consists of three different types of code that we can implement:

  • Root Query Resolver – These are used to resolve values of top-level queries from our schema.
  • Field Resolver – These are used to resolve values nested within our response.
  • Mutations – These are used to implement mutations from our schema.

All of these are implemented by writing beans within our application and annotating them as appropriate.

5.1. Root Query Resolver

The root query needs to have specially annotated methods to handle the various fields in this root query. Unlike the schema definition, there’s no restriction that there only be a single Spring bean for the root query fields.

We need to annotate the handler methods with @QueryMapping annotation and place these inside standard @Controller components in our application. This registers the annotated classes as data-fetching components in our GraphQL application:

@Controller
public class PostController {

    private PostDao postDao;

    @QueryMapping
    public List<Post> recentPosts(@Argument int count, @Argument int offset) {
        return postDao.getRecentPosts(count, offset);
    }
}

The above defines the method recentPosts, which we’ll use to handle any GraphQL queries for the recentPosts field in the schema defined earlier. Additionally, the method must have parameters annotated with @Argument that correspond to the corresponding parameters in the schema.

It can also optionally take other GraphQL-related parameters, such as GraphQLContext, DataFetchingEnvironment, etc., for access to the underlying context and environment.

The method must also return the correct return type for the type in the GraphQL scheme, as we’re about to see. We can use any simple types, String, Int, List, etc., with the equivalent Java types, and the system just maps them automatically.

5.2. Using Beans to Represent Types

Every complex type in the GraphQL server is represented by a Java bean, whether loaded from the root query or from anywhere else in the structure. The same Java class must always represent the same GraphQL type, but the name of the class isn’t necessary.

Fields inside the Java bean will directly map onto fields in the GraphQL response based on the name of the field:

public class Post {
    private String id;
    private String title;
    private String category;
    private String authorId;
}

Any fields or methods on the Java bean that don’t map onto the GraphQL schema will be ignored but won’t cause problems. This is important for field resolvers to work.

For example, here, the field authorId doesn’t correspond to anything in the schema we defined earlier, but it will be available to use for the next step.

5.3. Field Resolvers for Complex Values

Sometimes, the value of a field is non-trivial to load. This might involve database lookups, complex calculations, or anything else. The @SchemaMapping annotation maps the handler method to a field with the same name in the schema and uses it as the DataFetcher for that field.

@SchemaMapping
public Author author(Post post) {
    return authorDao.getAuthor(post.getAuthorId());
}

Importantly, if the client doesn’t request a field, then the GraphQL Server won’t do the work to retrieve it. This means that if a client retrieves a Post and doesn’t ask for the author field, the author() method above won’t be executed, and the DAO call won’t be made.

Alternatively, we can also specify the parent type name, and the field name in the annotation:

@SchemaMapping(typeName="Post", field="author")
public Author getAuthor(Post post) {
    return authorDao.getAuthor(post.getAuthorId());
}

Here, the annotation attributes are used to declare this as the handler for the author field in the schema.

5.4. Nullable Values

The GraphQL Schema has the concept that some types are nullable and others aren’t.

We handle this in the Java code by directly using null values. Conversely, we can use the new Optional type from Java 8 directly for nullable types, and the system will do the correct thing with the values.

This is very useful, as it means that our Java code is more obviously the same as the GraphQL schema from the method definitions.

5.5. Mutations

So far, everything we’ve done has been about retrieving data from the server. GraphQL also has the ability to update the data stored on the server through mutations.

From the code’s point of view, there’s no reason that a Query can’t change data on the server. We could easily write query resolvers that accept arguments, save new data, and return those changes. Doing this will cause surprising side effects for the API clients and is considered bad practice.

Instead, Mutations should be used to inform the client that this will cause a change to the data being stored.

Similar to Query, mutations are defined in the controller by annotating the handler method with @MutationMapping. The return value from a Mutation field is then treated exactly the same as from a Query field, allowing nested values to be retrieved as well:

@MutationMapping
public Post createPost(@Argument String title, @Argument String text,
  @Argument String category, @Argument String authorId) {

    Post post = new Post();
    post.setId(UUID.randomUUID().toString());
    post.setTitle(title);
    post.setText(text);
    post.setCategory(category);
    post.setAuthorId(authorId);

    postDao.savePost(post);

    return post;
}

6. GraphiQL

GraphQL also has a companion tool called GraphiQL. This UI tool can communicate with any GraphQL Server and helps to consume and develop against a GraphQL API. A downloadable version of it exists as an Electron app and can be retrieved from here.

Spring GraphQL comes with GraphiQL built-in. This is turned off by default, but we can turn it on by adding the following to application.yml:

spring:
  graphql:
    graphiql:
      enabled: true

Once we do this, we can navigate to the /graphiql endpoint on our application and get the full GraphiQL user interface for interacting with our API. This provides a very useful in-browser tool to write and test queries, particularly during development and testing:

GraphiQL, an in-browser tool to write and test queries.

7. Summary

GraphQL is an exciting new technology that can potentially revolutionize how we develop Web APIs.

Spring Boot GraphQL Starter makes it easy to add this technology to any new or existing Spring Boot application.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Microsoft – NPI EA (cat = Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Course – Spring Sale 2025 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our Spring Sale. All Courses are 25% off until 26th May, 2025:

>> EXPLORE ACCESS NOW

Course – Spring Sale 2025 – NPI (All)
announcement - icon

Yes, we're now running our Spring Sale. All Courses are 25% off until 26th May, 2025:

>> EXPLORE ACCESS NOW

Partner – Microsoft – NPI (cat=Spring)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

eBook Jackson – NPI EA – 3 (cat = Jackson)