DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • DGS GraphQL and Spring Boot
  • Optimizing Natural Language Queries for Multi-Service Information Retrieval
  • Mastering Async Context Manager Mocking in Python Tests
  • Designing Scalable Java APIs With GraphQL

Trending

  • Mastering Fluent Bit: Installing and Configuring Fluent Bit on Kubernetes (Part 3)
  • Can You Run a MariaDB Cluster on a $150 Kubernetes Lab? I Gave It a Shot
  • Ethical AI in Agile
  • A Modern Stack for Building Scalable Systems
  1. DZone
  2. Data Engineering
  3. Databases
  4. Microservices With GraphQL

Microservices With GraphQL

A developer goes through some Java and XML code used to create a basic microservice application that uses GraphQL to fetch data.

By 
Arun Pandey user avatar
Arun Pandey
DZone Core CORE ·
May. 07, 19 · Tutorial
Likes (20)
Comment
Save
Tweet
Share
27.5K Views

Join the DZone community and get the full member experience.

Join For Free

GraphQL is an API that was invented and open sourced by Facebook as a better replacement for REST. It can be understood as Querby language for APIs, which enables declarative data fetching by exposing a single endpoint and responds to queries. In REST, there is always a dedicated endpoint for each type of request and can't be customized.

In GraphQL, the client decides what data they need and that's the reason the client sends a query (payload) to the server and the server sends the data back as per the query request. There is where they get the name GraphQL

Let's look at an example to understand the technical details. In this example, we will build a simple book store application using graphQL.

pom.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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.dugu.acc.dev</groupId>
    <artifactId>spring-graphql</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>spring-graphql</name>
    <description>GraphQL is invented by Facebook as a better replacement of REST for Web APIs</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath />
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </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>com.graphql-java</groupId>
            <artifactId>graphql-spring-boot-starter</artifactId>
            <version>3.6.0</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-java-tools</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

The GraphQL schema is the main concept of GraphQL, which is based on SDL (Schema Definition language). We can define the simple types as we can see 'type Book' in below example, and relations as well (for example, 'type Query' has a relation with Book). The relationship could be one to one, one to many, many to one, and many to many. In the below example, 'type Query' has a one to many (allBooks) and a one to one (Book) relationship. The schema is playing the major role to fetch the data.

The below file is under the src/main/resource folder of my GitHub repo (liked to at the end of the article).

book.schema

schema{
query: Query
  }


type Query{
allBooks: [Book]
Book(id: String): Book
 }

type Book{
bookId: String
bookName: String
publishedDate: String
writer: [String]
publisher: String
} 


BookSearchController.java

package com.arun.spring.graphql.api.controller;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.arun.spring.graphql.api.datafetcher.BookDataFetcher;
import com.arun.spring.graphql.api.datafetcher.AllBookDataFetcher;
import com.arun.spring.graphql.api.entity.Book;
import com.arun.spring.graphql.api.service.BookService;

import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;

@RestController
@RequestMapping("/bookstore")
public class BookSearchController {
 @Autowired
 private BookService service;
 // load graphqls file
 @Value("classpath:book.schema")
 private Resource schemaResource;
 @Autowired
 private AllBookDataFetcher allBookDataFetcher;
 @Autowired
 private BookDataFetcher bookDataFetcher;

 private GraphQL graphQL;

 // load schema at application start up
 @PostConstruct
 public void loadSchema() throws IOException {
  // get the schema
  File schemaFile = schemaResource.getFile();
  // parse schema
  TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(schemaFile);
  RuntimeWiring wiring = buildRuntimeWiring();
  GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring);
  graphQL = GraphQL.newGraphQL(schema).build();
 }

 private RuntimeWiring buildRuntimeWiring() {
  return RuntimeWiring.newRuntimeWiring().type("Query", typeWiring -> typeWiring
   .dataFetcher("allBooks", allBookDataFetcher).dataFetcher("book", bookDataFetcher)).build();
 }

 @GetMapping("/booksList")
 public List < Book > getBooksList() {
  return service.findAllBooks();
 }

 /*
  * In PostMan use Post URL: localhost:8080/bookstore/getAllBooks
  * and Body: query{
   allBooks{
 bookId,
 bookName
   }
 }
  */
 @PostMapping("/getAllBooks")
 public ResponseEntity < Object > getAllBooks(@RequestBody String query) {
  ExecutionResult result = graphQL.execute(query);
  return new ResponseEntity < Object > (result, HttpStatus.OK);
 }

 @GetMapping("/search/{bookId}")
 public Book getBookInfo(@PathVariable String movieId) {
  return service.findBookById(movieId);
 }

 @PostMapping("/getBookById")
 public ResponseEntity < Object > getBookById(@RequestBody String query) {
  ExecutionResult result = graphQL.execute(query);
  return new ResponseEntity < Object > (result, HttpStatus.OK);
 }
}


AllBookDataFetcher.java

package com.arun.spring.graphql.api.datafetcher;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.arun.spring.graphql.api.entity.Book;
import com.arun.spring.graphql.api.repository.BookRepository;

import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;

@Component
public class AllBookDataFetcher implements DataFetcher < List < Book >> {
 @Autowired
 private BookRepository repository;

 @Override
 public List < Book > get(DataFetchingEnvironment environment) {
  return repository.findAll();
 }
}


BookDataFetcher.java

package com.arun.spring.graphql.api.datafetcher;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.arun.spring.graphql.api.entity.Book;
import com.arun.spring.graphql.api.repository.BookRepository;

import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;

@Component
public class BookDataFetcher implements DataFetcher < Book > {
 @Autowired
 private BookRepository repository;

 @Override
 public Book get(DataFetchingEnvironment environment) {
  String movieId = environment.getArgument("id");
  return repository.findOne(movieId);
 }
}


Book.java

package com.arun.spring.graphql.api.entity;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.ToString;

@ToString
@AllArgsConstructor
@NoArgsConstructor
@Table
@Entity
public class Book {
 @Id
 private String bookId;
 private String bookName;
 private String publishedDate;
 private String[] writer;
 private String publisher;
}


BookRepository.java

package com.arun.spring.graphql.api.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.arun.spring.graphql.api.entity.Book;

public interface BookRepository extends JpaRepository<Book, String> {

}


BookService.java

package com.arun.spring.graphql.api.service;

import java.util.*;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.arun.spring.graphql.api.entity.Book;
import com.arun.spring.graphql.api.repository.BookRepository;

@Service
public class BookService {
 @Autowired
 private BookRepository repository;

 @PostConstruct
 public void initBooks() {
  List < Book > books = new ArrayList < > ();
  books.add(new Book("101", "The Science of Marvel",
   "22-12-2017", new String[] {
    "Sebastian"
   },
   "Infinity Stones"));
  books.add(new Book("102", "The Sixth Extinction",
   "22-12-2017", new String[] {
    "Sebastian",
    "Elizabeth"
   },
   "Infinity Stones"));
  books.add(new Book("103", "The Science of Marvel -2",
   "22-12-2019", new String[] {
    "Sebastian"
   },
   "Infinity Stones"));
  repository.save(books);
 }

 public List < Book > findAllBooks() {
  return repository.findAll();
 }

 public Book findBookById(String movieId) {
  return repository.findOne(movieId);
 }
}


SpringGraphqlApplication.java

package com.arun.spring.graphql.api;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringGraphqlApplication {

 public static void main(String[] args) {
  SpringApplication.run(SpringGraphqlApplication.class, args);
 }
}

Start the SpringGraphqlApplication and then call the GraphQL endpoint as shown below using Postman:

In Postman, use the Post URL: localhost:8080/bookstore/getAllBooks  
and Body:  query{ allBooks{bookId,bookName }} 

You can add more fields in the body part and, accordingly, it will retrieve the data from server.

That's all for this talk. Enjoy the power of GraphQL.

GitHub URL: https://github.com/arunpandeycdac/MicroserviceWithSpringBootAndGraphQL

GraphQL

Opinions expressed by DZone contributors are their own.

Related

  • DGS GraphQL and Spring Boot
  • Optimizing Natural Language Queries for Multi-Service Information Retrieval
  • Mastering Async Context Manager Mocking in Python Tests
  • Designing Scalable Java APIs With GraphQL

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!