Steps to Create Modern APIs with Java and GraphQL

Below are the steps to create Modern APIs with Java and GraphQL.

Step 1. Create a Java Spring Boot Project

Go to start.spring.io and make the following configuration to create a Spring boot application. Spring boot is a Java framework for creating stand-alone Java applications.

  • Project: Maven
  • Language: Java
  • Spring Boot: 3.2.3
  • Packaging: Jar
  • Java: 17

Dependencies:

  • Spring Web ( For creating web APIs)
  • Spring Data JPA (To use Java persistence API for database operations)
  • H2 Database (Provides in memory database with JDBC support)
  • Spring for GraphQL ( Dependency to use GraphQL features in Java application)
  • Lombok ( Provides the Java annotation library)

Now Click on generate and a zip file will be downloaded, unzip the project file and open it with any IDE.

Step 2: Explore the Project

When we open the project, we have to wait for some time for the project to be configured and indexed properly by the IDE. Then we can explore the project.

To check the dependencies we have added, go to the pom.xml file and give it a look.

pom.xml:

XML




<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.w3wiki</groupId>
    <artifactId>JavaGraphQL</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>JavaGraphQL</name>
    <description>Demo project for Java and GraphQL</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <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>
  
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webflux</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.graphql</groupId>
            <artifactId>spring-graphql-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
  
</project>


Step 3: Configure Application properties

Let’s configure the application.properties for our application to use database configurations. Here we are using H2 database which is a light weight relational database management system built in Java.

Inside the Resource folder, we have the application.properties file and we have to configure all necessary details here.

applications.properties file:

server.port=9000
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=admin
spring.datasource.password=admin
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

Here, we have defined the port no as 9000 for the APIs to expose. For database we are using H2 database that is declared here and the username and password for the database is set as admin for both.

Step 4: Configure Entity and Repository

Let’s create 3 packages in our application package, which are Entity, Repository, and Services. Entity is what get stored in the database. We will where we will declare the entity and its attributes. Repository is where we perform operations on database and Service is where we write the business logics behind database operations.

Entity:

Inside entities, we are creating a Book entity with attributes as id, title, author, desc, author, price and pages. For Id we want it to be auto generated and defining the class as an @Entity class. We have also the constructor, getters, and setters in the class. For all this we will be using Lombok annotations.

Book.java:

Java




package com.w3wiki.JavaGraphQL.entities;
import jakarta.persistence.*;
import lombok.*;
  
@Entity
@Table(name = "project_books")
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Book {
  
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String title;
    private String desc;
    private String author;
    private double price;
    private int pages;
}


Repository:

For repository, we will be creating an interface and extend JPA repository. Spring JPA repository is a generic interface provided by Spring Data JPA that provides CRUD functionality for a specific entity type. Here we will declare, Book as entity type and Integer as the type of primary key, which is Id.

BookRep.java:

Java




import com.w3wiki.JavaGraphQL.entities.Book;
import org.springframework.data.jpa.repository.JpaRepository;
  
// Repository interface for managing Book entities
public interface BookRep extends JpaRepository<Book, Integer> {
}


Services:

For database services we are going to create a Interface first and then we will implement it. Let’s say we have three functionalities as, add new book, get all books and get a single book by it’s Id. Let’s write the interface first.

BookService.java:

Java




package com.w3wiki.JavaGraphQL.services;
import com.w3wiki.JavaGraphQL.entities.Book;
import java.util.List;
  
// Interface defining the contract for Book service
public interface BookService {
  
    // Method to create a new book
    Book create(Book book);
      
    // Method to retrieve all books
    List<Book> getAll();
      
    // Method to retrieve a specific book by ID
    Book get(int bookId);
}


Let’s implement the same in a implementation class, where we will be save any new book record, return a list of books for all books and return a single book if requested with Id. Let’s add another line to show the error if Id is not found.

BookServiceImpl.java:

Java




import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.w3wiki.JavaGraphQL.entities.Book;
import com.w3wiki.JavaGraphQL.repositories.BookRep;
import java.util.List;
  
// Service implementation for BookService interface
@Service
public class BookServiceImpl implements BookService {
  
    // Dependency injection for BookRep repository
    private BookRep bookRep;
  
    @Autowired
    public BookServiceImpl(BookRep bookRep) {
        this.bookRep = bookRep;
    }
  
    // Method to create a new book
    @Override
    public Book create(Book book) {
        return this.bookRep.save(book);
    }
  
    // Method to retrieve all books
    @Override
    public List<Book> getAll() {
        return this.bookRep.findAll();
    }
  
    // Method to retrieve a specific book by ID
    @Override
    public Book get(int bookId) {
        return this.bookRep.findById(bookId).orElseThrow(() -> new RuntimeException("Book Not Available!!"));
    }
}


Let’s check the folder structure now.

Step 5: Create Controller

We need a controller to expose the API endpoints. Inside the controller we will be mapping the endpoints. Here instead of using RequestMapping we will be using QueryMappping for GraphQL. We will specify the mapping names as we have declare the same names when we will configure GraphQL configurations. For Query we are using @QueryMapping and for mutation we will us @MutationMapping.

BookController.java:

Java




import com.w3wiki.JavaGraphQL.entities.Book;
import com.w3wiki.JavaGraphQL.services.BookService;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
  
import java.util.List;
  
// Controller for handling book-related operations
@Controller
public class BookController {
  
    // Dependency injection for BookService
    @Autowired
    private BookService bookService;
  
    // Method to save new books
    @MutationMapping("createBook")
    public Book create(@Argument BookInput book) {
        Book b=new Book();
        b.setTitle(book.getTitle());
        b.setDesc(book.getDesc());
        b.setPrice(book.getPrice());
        b.setAuthor(book.getAuthor());
        b.setPages(book.getPages());
        return this.bookService.create(b);
    }
  
    // Method to retrieve all books
    @QueryMapping("allBooks")
    public List<Book> getAll() {
        return this.bookService.getAll();
    }
  
    // Method to retrieve a book by its ID
    @QueryMapping("getBook")
    public Book get(@Argument int bookId) {
        return this.bookService.get(bookId);
    }
  
}


If we look at the create() function, we are using a BookInput type of input for mutation. So, we have to declare the BookInput class to use the attributes. We can write the class inside this BookController.java file or create a new class file for the same. Use Lombok annotations to declare getters and setters.

@Getter
@Setter
class BookInput{
private String title;
private String desc;
private String author;
private double price;
private int pages;
}

Step 6: Configure GraphQL

To use GraphQL, we have to declare the data first. We will declare the data in the server side. To do this, inside the resource folder we have create a folder and name it graphql, then inside this we will create a file named schema.graphqls.

Here we will first define the type for Book and BookInput.

Now let’s create query type for queries where we will define, getallbooks to return collection of books and a getbook query to return book using Id.

Now, create one mutation to add new books. This will accept as bookInput type input and store the data into the database.

Note: Make sure the names you are using should match the same with ones you have defined in the Controller.

schema.graphqls:

type Mutation{
createBook(book:BookInput):Book
}
type Query{
allBooks:[Book]
getBook(bookId:Int):Book
}
type Book{
    id:ID!
    title:String
    desc:String
    author:String
    price:Float
    pages:Int
}
input BookInput{
    title:String
    desc:String
    author:String
    price:Float
    pages:Int
}

Step 7. Run the application

Once we are done with the configurations, let’s move forward run our application and see if everything is working fine. Go to the JavaGraphQlApplication.java to run the application. This name may differ in your case if you have set different name to the project.

Inside the class, click on the run button and see the console for details.

As we can see, the application is successfully started and its running on port no 9000 as we have defined in the applications.properties.

Step 8: Test the APIs

Once our Java application is running successfully, now it’s time to check and test the APIs if they are functioning properly. For Testing we are using Postman. The APIs are available under “/graphql” by default, however we can change it if we want, for the time being let it be this. To test, we have loaded few books inside our database. Now let’s query using Graphql. We will also use mutation to insert new books.

Open the postman app and in the URL write,

localhost:9000/graphql

Use the method as POST and in the Body select GraphQL.

8.1. Query

Query are the GraphQL read operations used to fetch data. Now we will write Query in the Query box given, we have setup two queries which are to getallbook and getbook using Id. As mentioned, we have inserted few records to let’s check them.

Let’s check all the books with all fields.

query{
    allBooks{
        id
        title
        desc
        author
        price
        pages
    }
}

Output:

Now let’s use the GraphQL feature to get data which is necessary. For example, we want all the book’s name with its author and price. Let’s query this and check what we get.

query{
    allBooks{
        title
        author
        price
    }
}

Output:

Let’s Query to get a book using it’s Id, here for example we are using Id no 2.

query{
  getBook(bookId:2){
    id
    title
    author
  }
}

Output:

8.2 Mutation

Mutation in GraphQL is used for write operations, let’s use mutation to insert a new book record into the database using API.

mutation{
    createBook(book:{
        title: "w3wiki"
        desc: "Manual for Geeks"
        author: "Geek"
        price: 999
        pages: 123
    }){
        id
    }
}

Output:

As we can see a new book has been inserted with Id no 4 which is auto generated as we have defined in the Code.
Let’s query again for book Id 4 and see what we are getting.

query{
    getBook(bookId:4){
        id
        title
        desc
        author
        price
        pages
    }
}

Output:

Java and GraphQL: Building Modern APIs

Java has been there for a very long time for developing APIs with its famous Spring framework and the whole Spring ecosystem. GraphQL is a new technology for modern APIs. GraphQL is a query language for APIs and a runtime to execute those queries. GraphQL allows clients to query only the necessary data making it more efficient and convenient compared to traditional REST APIs. In this article, we will learn how we can combine GraphQL with Java programming to create Modern APIs.

Similar Reads

Steps to Create Modern APIs with Java and GraphQL

Below are the steps to create Modern APIs with Java and GraphQL....

Conclusion:

...

Contact Us