x Java Java 8 JUnit JSON
  • XML
  • JDBC Spring Boot Microservices React Contact Us

    Spring Boot GraphQL tutorial

    When a request is made to a REST service, it sends data for only that service with all the fields. But what if only a subset of data is required in the response or response should contain multiple resource data ? For example if request is made to get User and we want only subset of data along with User Address, then we can make a GraphQL query.

    A GraphQL query will select only the fields required in the response and also save multiple REST calls to a service. This tutorial shows how to query an API using Spring Boot & GraphQL.

    Step 1) Add below dependencies in pom.xml

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <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>       

    Step 2) Create User POJO, UserRepository and UserService classes

    UserService will make call to UserRepository class and get users details.

    package com.example.demo;
    
    import java.io.Serializable;
    
    public class User implements Serializable {
    
        private static final long serialVersionUID = 1L;
        private int id;
        private String email;
        private String firstName;
        private String lastName;
    
        // removed getter and setters
    
    }

    package com.example.demo;
    
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Optional;
    
    import org.springframework.stereotype.Repository;
    
    @Repository()
    public class UserRepository {
    
        private Map<Integer, User> users = new HashMap<>();
        
        
        public Collection<User> findAll() {
            return users.values();
        }
    
        public Optional<User> findUser(Integer userId) {
            return Optional.ofNullable(users.get(userId));
        }
    
        public User addUser(int id, User user) {
            users.put(id, user);
            return user;
        }
    
        public void deleteItem(Integer id) {
            users.remove(id);
        }
    
        public void updateUser(Integer id, User user) {
            users.put(id, user);
        }
    }

    package com.example.demo;
    
    import java.util.List;
    import java.util.Optional;
    import java.util.stream.Collectors;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
    
        @Autowired
        private UserRepository userRepository;
    
        public User createUser(final int id, final String email, 
            final String firstName, final String lastName) {
            return userRepository.addUser(id, new User(id, "harry@hotmail.com", "Harry", "Potter"));
        }
    
        public List<User> getAllUsers(final int count) {
            return userRepository.findAll().stream().limit(count).collect(Collectors.toList());
        }
    
        public Optional<User> getUser(final Integer id) {
            return userRepository.findUser(id);
        }
    
    }

    Step 3) Create GraphQL schema file to query the API

    Create a GraphQL schema file under src/main/resources folder which is written in SDL (Schema Definition Language). It provides the schema that describes the APIs. Note that GraphQL schema can contain only one root Query & one Mutation.

    type User {
        id: Int,
        email: String,
        firstName: String,
        lastName: String
    }
    
    type Query {
        users(count: Int):[User]
        user(id: String):User
    }
    
    type Mutation {
        createUser(id: Int!, email: String, firstName: String, lastName: String):User
    }

    Step 4) Create GraphQLApplication, UserQuery, UserMutation, classes

    package com.example.demo;
    
    import org.springframework.boot.ApplicationRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    
    @SpringBootApplication
    public class GraphQLApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(GraphQLApplication.class, args);
        }
        
        @Bean
        public ApplicationRunner userInitializer(UserRepository userRepository) {
            return args -> {
                userRepository.addUser(1, new User(1, "harry@hotmail.com", "Harry", "Potter"));
            };
        }
        
    }

    To handle the queries defined in GraphQL schema, we need to add Query & Mutation Resolvers. When a query is made, UserQuery will process it, while if want to add a record or make a mutation, it will be handled by UserMutation.

    package com.example.demo;
    
    import java.util.List;
    import java.util.Optional;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import com.coxautodev.graphql.tools.GraphQLQueryResolver;
    
    @Component
    public class UserQuery implements GraphQLQueryResolver {
    
        @Autowired
        private UserService userService;
    
        public List<User> getUsers(final int count) {
            return this.userService.getAllUsers(count);
        }
    
        public Optional<User> getUser(final Integer id) {
            return this.userService.getUser(id);
        }
    }    

    package com.example.demo;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import com.coxautodev.graphql.tools.GraphQLMutationResolver;
    
    @Component
    public class UserMutation implements GraphQLMutationResolver {
    
        @Autowired
        private UserService userService;
    
        public User createUser(final int id, final String email, final String firstName,
            final String lastName) {
                return userService.createUser(id, email, firstName, lastName);
        }
    }   

    Step 5) Running GraphQLApplication

    Run above GraphQLApplication, and launch http://localhost:8080/graphiql

    You will see GraphQL user interface where you can run queries. Run below queries and see result

    query {
      users(count: 2) {
        id
        email
        firstName
        lastName
      }
    }

    Query Result

    {
      "data": {
        "users": [
          {
            "id": 1,
            "email": "harry@hotmail.com",
            "firstName": "Harry",
            "lastName": "Potter"
          }
        ]
      }
    }

    mutation {
      createUser(id: 2, email: "sfdsf@sdfsdf", firstName: "XYZ", lastName: "sdfd") {
        id
      }
    }

    Mutation Result

    {
      "data": {
        "createUser": {
          "id": 2
        }
      }
    }


    References :

    GraphQL core concepts

    Comments

    Leave a Reply

    Your email address will not be published. Required fields are marked *











    Share This