Develop a GraphQL API with Spring Boot: A step-by-step guide

Develop a GraphQL API with Spring Boot: A step-by-step guide

GraphQL is a query language for APIs that allows you to specify exactly what data you need and get only that, no more and no less. Spring Boot, on the other hand, is a popular framework for building enterprise-grade applications in Java. In this blog post, we'll walk through a step-by-step guide on how to build a GraphQL API with Spring Boot.

System Requirements

Before we get started, make sure you have the following installed on your machine:

  • Java 8 or higher

  • Maven 3.6 or higher

Step 1: Create a new Spring Boot project

The first step is to create a new Spring Boot project using the Spring Initializr. You can do this by visiting https://start.spring.io/ and selecting the following options:

  • Project: Maven

  • Language: Java

  • Spring Boot: 2.5.x or higher

  • Group: online.techstories.demo

  • Artifact: graphql-api

  • Packaging: jar

  • Java Version: 8

  • Dependencies: Web, Spring Data JPA, Lombok

Click "Generate" to download the project.

Step 2: Add the GraphQL Dependencies

Once the project is created, the selected dependencies will automatically get added. We need to add the below dependencies in the `pom.xml` file to use the GraphQL features: -

<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-spring-boot-starter</artifactId>
    <version>5.0.2</version>
</dependency>

<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java-tools</artifactId>
    <version>5.2.4</version>
</dependency>

<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphiql-spring-boot-starter</artifactId>
    <version>5.0.2</version>
</dependency>

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

Step 3: Create the Entity class

Next, we will define the Book entity in our project. We can use the @Entity annotation to indicate that this class is an entity that will be managed by JPA. We will also define the necessary attributes for the Book entity.

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "title")
    private String title;

    @Column(name = "author")
    private String author;
}

Here, we have used the Lombok annotations to auto-generate constructors, getters and setters.

Step 4: Define the GraphQL schema

Now that we have our project set up and we have created the model class, it's time to define the GraphQL schema. This is where we define the queries, mutations, and types for our API. You can do this by creating a new file called schema.graphqls in the src/main/resources directory and adding the following code:

type Book {
  id: ID!
  title: String!
  author: String!
}

type Query {
  books: [Book!]!
}

type Mutation {
  addBook(title: String!, author: String!): Book!
}

This schema defines a Book type with an id, title, and author, a Query type with a single resolver that returns a list of books, and a Mutation type with a resolver for adding a new book.

Step 5: Define the GraphQL Resolvers

With the schema defined, we need to define the resolvers that will handle the queries and mutations. You can do this by creating a new class called BookResolver in the default package and adding the following code:

@Component
public class BookResolver implements GraphQLQueryResolver, GraphQLMutationResolver {

  private final BookRepository bookRepository;

  public BookResolver(BookRepository bookRepository) {
    this.bookRepository = bookRepository;
  }

  public List<Book> books() {
    return bookRepository.findAll();
  }

  public Book addBook(String title, String author) {
    Book book = new Book();
    book.setTitle(title);
    book.setAuthor(author);
    bookRepository.save(book);
    return book;
  }

}

This resolver implements the GraphQLQueryResolver and GraphQLMutationResolver interfaces and defines methods for resolving the queries and mutations defined in the schema. Note that the BookResolver depends on a BookRepository, which we'll define in the next step.

Step 6: Define the JPA repository

To store and retrieve books from a database, we'll use Spring Data JPA. You can define a new interface called BookRepository in the default package and add the following code:

@Repository
public interface BookRepository extends JpaRepository<Book, Long> {

}

This interface extends the JpaRepository interface and defines methods for performing CRUD operations on the Book entity.

Step 7: Run the application

That's it! We've defined our schema, resolvers, and repository. Now, let's run the application and test our API. You can do this by running the following command in your terminal:

mvn spring-boot:run

Once the application is up and running, you can visit http://localhost:8080/graphiql to access the GraphQL IDE. Here, you can test your queries and mutations by running them in the left pane and seeing the results in the right pane.

For example, you can run the following query to get a list of all books:

{
  books {
    id
    title
    author
  }
}

Or, you can run the following mutation to add a new book:

mutation {
  addBook(title: "Harry Potter and the Philosopher's Stone", author: "J.K. Rowling") {
    id
    title
    author
  }
}

Conclusion

In this blog post, we walked through a step-by-step guide on how to build a GraphQL API with Spring Boot. We started by creating a new Spring Boot project and adding the GraphQL dependencies. Then, we defined the GraphQL schema and resolvers, and the JPA repository. Finally, we ran the application and tested our API using the GraphQL IDE. I hope this post was helpful to you, and happy coding!

GitHub Code

You can refer to the below GitHub location for the completed project.

https://github.com/BeingSujeetK/techstories-demo-spring-boot/tree/main/springboot-graphql-api-with-java-starter

Did you find this article valuable?

Support Sujeet Kumar by becoming a sponsor. Any amount is appreciated!