Building a GraphQL API with Spring Boot: Tutorial and Example

This tutorial explains how to replace traditional REST APIs with GraphQL by building a Spring Boot application, defining Java entities, writing GraphQL schema, implementing query resolvers, configuring the endpoint, and testing queries using tools like Altair.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Building a GraphQL API with Spring Boot: Tutorial and Example

Overview

REST is a popular modern web‑application architectural style that many developers love, but its biggest drawback becomes evident as the number of similar yet slightly different data requirements grows: different clients often need overlapping but not identical fields, leading to a proliferation of endpoints and heavy documentation.

In many cases the client‑side data has similarity across different places but is not exactly the same. For example, a user’s basic information (name, avatar) may be enough for one UI, while another UI needs the full profile. When such variations multiply, developers must create many APIs to satisfy the front‑end. More APIs mean larger documentation and exponentially increasing communication cost between front‑end and back‑end.

To address this scenario we need a solution that lets the front‑end specify which fields it wants while the back‑end automatically adapts and returns only those fields using the same domain model (DO/DTO).

The solution is GraphQL .

Scenario Simulation

Consider the following scenario:

User and Article have a one‑to‑many relationship: a user can publish many articles, and each article can be linked back to its author.

We need to build the following GraphQL queries:

Get user details by user ID and retrieve all articles posted by that user.

Get article details by article ID and retrieve the author’s information.

The project is based on SpringBoot.

Practical Development

Before starting, install the JS GraphQL plugin in IDEA; it helps with schema editing, syntax checking, and highlighting.

Create a SpringBoot Project

Create a SpringBoot project in IDEA and add the required dependencies.

<code style="padding: 16px; color: #383a42; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; letter-spacing: 0px"><span style="line-height: 26px"><dependencies></span><br/> <span style="line-height: 26px"><dependency></span><br/>    <span style="line-height: 26px"><groupId>org.springframework.boot</groupId></span><br/>    <span style="line-height: 26px"><artifactId>spring-boot-starter</artifactId></span><br/> <span style="line-height: 26px"></dependency></span><br/><br/> <span style="line-height: 26px"><dependency></span><br/>    <span style="line-height: 26px"><groupId>org.springframework.boot</groupId></span><br/>    <span style="line-height: 26px"><artifactId>spring-boot-starter-web</artifactId></span><br/> <span style="line-height: 26px"></dependency></span><br/><br/> <span style="color: #a0a1a7; font-style: italic; line-height: 26px"><!--graphql start--></span><br/> <span style="line-height: 26px"><dependency></span><br/>    <span style="line-height: 26px"><groupId>com.graphql-java</groupId></span><br/>    <span style="line-height: 26px"><artifactId>graphql-spring-boot-starter</artifactId></span><br/>    <span style="line-height: 26px"><version>5.0.2</version></span><br/> <span style="line-height: 26px"></dependency></span><br/> <span style="line-height: 26px"><dependency></span><br/>    <span style="line-height: 26px"><groupId>com.graphql-java</groupId></span><br/>    <span style="line-height: 26px"><artifactId>graphql-java-tools</artifactId></span><br/>    <span style="line-height: 26px"><version>5.2.4</version></span><br/> <span style="line-height: 26px"></dependency></span><br/> <span style="color: #a0a1a7; font-style: italic; line-height: 26px"><!--graphql end--></span><br/><br/> <span style="line-height: 26px"><dependency></span><br/>    <span style="line-height: 26px"><groupId>org.projectlombok</groupId></span><br/>    <span style="line-height: 26px"><artifactId>lombok</artifactId></span><br/> <span style="line-height: 26px"></dependency></span><br/><span style="line-height: 26px"></dependencies></span></code>

The key dependencies are graphql-spring-boot-starter and graphql-java-tools.

Define Java Entity Classes

User

<code style="padding: 16px; color: #383a42; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; letter-spacing: 0px"><span style="color: #4078f2; line-height: 26px">@Data</span><br/><span style="color: #a626a4; line-height: 26px">public</span> class <span style="color: #c18401; line-height: 26px">User</span> {<br/>    <span style="color: #a626a4; line-height: 26px">private</span> int userId;<br/>    <span style="color: #a626a4; line-height: 26px">private</span> String userName;<br/>    <span style="color: #a626a4; line-height: 26px">private</span> String realName;<br/>    <span style="color: #a626a4; line-height: 26px">private</span> String email;<br/>    <span style="color: #a626a4; line-height: 26px">private</span> List<Post> posts;<br/><br/>    <span style="color: #a626a4; line-height: 26px">public</span> User() {}<br/><br/>    <span style="color: #a626a4; line-height: 26px">public</span> User(int userId, String userName, String realName, String email) {<br/>        <span style="color: #a626a4; line-height: 26px">this</span>.userId = userId;<br/>        <span style="color: #a626a4; line-height: 26px">this</span>.userName = userName;<br/>        <span style="color: #a626a4; line-height: 26px">this</span>.realName = realName;<br/>        <span style="color: #a626a4; line-height: 26px">this</span>.email = email;<br/>    }<br/>}</code>

Post

<code style="padding: 16px; color: #383a42; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; letter-spacing: 0px"><span style="color: #4078f2; line-height: 26px">@Data</span><br/><span style="color: #a626a4; line-height: 26px">public</span> class <span style="color: #c18401; line-height: 26px">Post</span> {<br/>    <span style="color: #a626a4; line-height: 26px">private</span> int postId;<br/>    <span style="color: #a626a4; line-height: 26px">private</span> String title;<br/>    <span style="color: #a626a4; line-height: 26px">private</span> String text;<br/>    <span style="color: #a626a4; line-height: 26px">private</span> String category;<br/>    <span style="color: #a626a4; line-height: 26px">private</span> User user;<br/><br/>    <span style="color: #a626a4; line-height: 26px">public</span> Post() {}<br/><br/>    <span style="color: #a626a4; line-height: 26px">public</span> Post(int postId, String title, String text, String category) {<br/>        <span style="color: #a626a4; line-height: 26px">this</span>.postId = postId;<br/>        <span style="color: #a626a4; line-height: 26px">this</span>.title = title;<br/>        <span style="color: #a626a4; line-height: 26px">this</span>.text = text;<br/>        <span style="color: #a626a4; line-height: 26px">this</span>.category = category;<br/>    }<br/>}</code>

These two Java entities represent the domain objects used by GraphQL.

Write Schema File

Create GraphQL schema files under resources/schema.

<code style="padding: 16px; color: #383a42; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; letter-spacing: 0px">schema {<br/>    query: Query,<br/>}<br/><br/>type Query {<br/>    # Get a specific user<br/>    getUserById(id: Int): User<br/>    # Get a specific post<br/>    getPostById(id: Int): Post<br/>}<br/><br/>type User {<br/>    userId: ID!,<br/>    userName: String,<br/>    realName: String,<br/>    email: String,<br/>    posts: [Post],<br/>}<br/><br/>type Post {<br/>    postId: ID!,<br/>    title: String!,<br/>    text: String,<br/>    category: String,<br/>    user: User,<br/>}</code>

The type keyword defines the two objects, User and Post. The exclamation mark (!) marks a field as non‑null, and [Post] denotes a list of Post objects, similar to a Java List. The Query type defines two entry points: getUserById and getPostById.

Write Business Logic

PostService

<code style="padding: 16px; color: #383a42; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; letter-spacing: 0px"><span style="color: #4078f2; line-height: 26px">@Service</span><br/><span style="color: #a626a4; line-height: 26px">public</span> class <span style="color: #c18401; line-height: 26px">PostService</span> implements GraphQLQueryResolver {<br/>    /**<br/>     * For demonstration, only return the record with id = 1<br/>     */<br/>    public Post getPostById(int id) {<br/>        if (id == 1) {<br/>            User user = new User(1, "javadaily", "JAVA日知录", "[email protected]");<br/>            Post post = new Post(1, "Hello,Graphql", "Graphql初体验", "日记");<br/>            post.setUser(user);<br/>            return post;<br/>        } else {<br/>            return null;<br/>        }<br/>    }<br/>}</code>

UserService

<code style="padding: 16px; color: #383a42; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; letter-spacing: 0px"><span style="color: #4078f2; line-height: 26px">@Service</span><br/><span style="color: #a626a4; line-height: 26px">public</span> class <span style="color: #c18401; line-height: 26px">UserService</span> implements GraphQLQueryResolver {<br/>    List<User> userList = Lists.newArrayList();<br/><br/>    public User getUserById(int id) {<br/>        return userList.stream().filter(item -> item.getUserId() == id).findAny().orElse(null);<br/>    }<br/><br/>    @PostConstruct<br/>    public void initUsers() {<br/>        Post post1 = new Post(1, "Hello,Graphql1", "Graphql初体验1", "日记");<br/>        Post post2 = new Post(2, "Hello,Graphql2", "Graphql初体验2", "日记");<br/>        Post post3 = new Post(3, "Hello,Graphql3", "Graphql初体验3", "日记");<br/>        List<Post> posts = Lists.newArrayList(post1, post2, post3);<br/><br/>        User user1 = new User(1, "zhangsan", "张三", "[email protected]");<br/>        User user2 = new User(2, "lisi", "李四", "[email protected]");<br/><br/>        user1.setPosts(posts);<br/>        user2.setPosts(posts);<br/><br/>        userList.add(user1);<br/>        userList.add(user2);<br/>    }<br/>}</code>

Both services implement GraphQLQueryResolver. For simplicity, no persistent data layer is used.

Configure GraphQL Endpoint

<code style="padding: 16px; color: #383a42; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; letter-spacing: 0px">server.port = 8080<br/>graphql.servlet.corsEnabled = true<br/># Configure endpoint<br/>graphql.servlet.mapping = /graphql<br/>graphql.servlet.enabled = true</code>

After configuring the port and endpoint, the GraphQL API can be tested at http://localhost:8080/graphql.

Testing

The author uses the Chrome extension Altair GraphQL Client , but other tools such as graphql‑playground work as well.

Install Plugin

Open chrome://extensions/, search for “Altair”, and add the extension.

Run Queries

Start the SpringBoot project, open Altair, set the endpoint to http://localhost:8080/graphql, click Docs, hover over a query, click ADD QUERY, then press Send Request to see the result.

You can add or remove fields in the query; the response automatically reflects the selected fields.

Conclusion

GraphQL supports three core operations:

Query : basic data retrieval.

Mutation : create, update, delete operations.

Subscription : real‑time data changes via WebSocket or similar protocols.

This article demonstrated how to implement Query operations with SpringBoot; future articles will cover Mutations and Subscriptions to provide a complete GraphQL solution.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavaAPISpringBootTutorialGraphQL
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.