Getting Started with GraphQL and Spring Boot

Getting Started with GraphQL and Spring Boot

GraphQL is a query language for APIs that allows clients to request limited data they need, making it possible for clients to gather data in a limited number of requests. In this article, we will build a simple GraphQL server with Spring Boot.

GraphQL is strongly typed protocol and all data operations are validated against a GraphQL schema.

Adding Maven Dependencies

Create a sample Spring Boot application and add the following dependencies.

  1. graphql-spring-boot-starter is used for enabling GraphQL servlet and it becomes available at a path /graphql. It initializes _GraphQLSchema_ bean.
  2. graphql-java allows to write schema with GraphQL schema language which is simple to understand.
  3. graphiql-spring-boot-starter provides user interface using which we could test our GraphQL queries and view query definition.
        <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>

Here is the complete POM file content.

<?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.techshard.graphql</groupId>
    <artifactId>springboot-graphql</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath />
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</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>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
Creating JPA Entity and Repository

Let’s create a simple entity called Vehicle and a corresponding JPA repository. We will use Lombok to avoid writing boilerplates such as getters, setters and so on.

package com.techshard.graphql.dao.entity;

import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDate;

@Data
@EqualsAndHashCode
@Entity
public class Vehicle implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column(name = "type", nullable = false)
    private String type;

    @Column(name = "model_code", nullable = false)
    private String modelCode;

    @Column(name = "brand_name")
    private String brandName;

    @Column(name = "launch_date")
    private LocalDate launchDate;

    private transient  String formattedDate;

    // Getter and setter
    public String getFormattedDate() {
        return getLaunchDate().toString();
    }
}

Here is the corresponding JPA repository.

package com.techshard.graphql.dao.repository;

import com.techshard.graphql.dao.entity.Vehicle;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface VehicleRepository extends JpaRepository<Vehicle, Integer> {
}

GraphQL Schema

GraphQL comes with its own language to write GraphQL Schema called Schema Definition Language (SDL). The schema definition consists of all the API functionalities available at an endpoint.

A typical example of GraphQL schema would look like this:

type Vehicle {
	id: ID!,
	type: String,
	modelCode: String,
	brandName: String,
	launchDate: String
}

type Query {
	vehicles(count: Int):[Vehicle]
	vehicle(id: ID):Vehicle
}

type Mutation {
	createVehicle(type: String!, modelCode: String!, brandName: String, launchDate: String):Vehicle
}

Create a folder graphql under src/main/resources and create a file vehicleql.graphqls under that folder. Copy the above contents and paste it in the vehicleql.graphqls file. Note that, the name of the file could be any name of your choice. Just make sure to keep the file extension as .graphqls.

In the above schema, each object is defined with type. The type system in GraphQL is the most basic component and it represents a kind of object that can be fetched from a service and the fields that the object contains within.

In our schema, we have an object called Vehicle which is our domain object. The type Query represents the query that can be made to the GraphQL server to fetch data. This query is interactive, they can be modified, and new results can be seen. The structure of query and result is same. This is important in GraphQL world, because we always get back the result that we expect.

We will see a working example in this article later.

The type Mutation represents the queries that are used to perform write operations on the data.

Root Query

Query or Mutation objects are root GraphQL objects, they don’t have any associated data class. In such cases, the resolver classes would implement GraphQLQueryResolver or GraphQLMutationResolver. These resolvers will be searched for methods that map to fields in their respective root types.

Let’s define root resolvers for Vehicle.

package com.techshard.graphql.query;

import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import com.techshard.graphql.dao.entity.Vehicle;
import com.techshard.graphql.service.VehicleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;

@Component
public class VehicleQuery implements GraphQLQueryResolver {

    @Autowired
    private VehicleService vehicleService;

    public List<Vehicle> getVehicles(final int count) {
        return this.vehicleService.getAllVehicles(count);
    }

    public Optional<Vehicle> getVehicle(final int id) {
        return this.vehicleService.getVehicle(id);
    }
}

In this class, we have methods to get a single Vehicle object and a list of Vehicle objects. Note that, we have defined these methods in our schema above.

Now, let’s define a Mutation resolver.

package com.techshard.graphql.mutation;

import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import com.techshard.graphql.dao.entity.Vehicle;
import com.techshard.graphql.service.VehicleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;

@Component
public class VehicleMutation implements GraphQLMutationResolver {

    @Autowired
    private VehicleService vehicleService;

    public Vehicle createVehicle(final String type, final String modelCode, final String brandName, final String launchDate) {
        return this.vehicleService.createVehicle(type, modelCode, brandName, launchDate);
    }
}

In this class, we only have one method to create a Vehicle object and this corresponds to type Mutation in our schema definition.

We will now define a service which would make actual transactions.

package com.techshard.graphql.service;

import com.techshard.graphql.dao.entity.Vehicle;
import com.techshard.graphql.dao.repository.VehicleRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class VehicleService {

    private final VehicleRepository vehicleRepository ;

    public VehicleService(final VehicleRepository vehicleRepository) {
        this.vehicleRepository = vehicleRepository ;
    }

    @Transactional
    public Vehicle createVehicle(final String type,final String modelCode, final String brandName, final String launchDate) {
        final Vehicle vehicle = new Vehicle();
        vehicle.setType(type);
        vehicle.setModelCode(modelCode);
        vehicle.setBrandName(brandName);
        vehicle.setLaunchDate(LocalDate.parse(launchDate));
        return this.vehicleRepository.save(vehicle);
    }

    @Transactional(readOnly = true)
    public List<Vehicle> getAllVehicles(final int count) {
        return this.vehicleRepository.findAll().stream().limit(count).collect(Collectors.toList());
    }

    @Transactional(readOnly = true)
    public Optional<Vehicle> getVehicle(final int id) {
        return this.vehicleRepository.findById(id);
    }
}

Testing the Application

The application is now ready for testing. Run the Spring Boot application. Open the link http://localhost:8080/graphiql in the browser. We will see a nice user interface as below.

On the right side of user interface, we can also explore documentation.

Now, run the following query.

mutation {
  createVehicle(type: "car", modelCode: "XYZ0192", brandName: "XYZ", launchDate: "2016-08-16") 
  {
    id
  }
}

This will create a row in the Vehicle table. The result would be:

{
  "data": {
    "createVehicle": {
      "id": "1"
    }
  }
}

Let us now run a query to get the data.

query {
  vehicles(count: 1) 
  {
    id, 
    type, 
    modelCode
	}
}

The output will be:

{
  "data": {
    "vehicles": [
      {
        "id": "1",
        "type": "bus",
        "modelCode": "XYZ123"
      }
    ]
  }
}

Note that we are requesting for only limited number of fields. We can change our query by adding or removing fields and see the new results.

Conclusion

In this article, we looked at the basic concepts of GraphQL. Check out the detailed documentation here.

The complete source code for this tutorial can be found on GitHub.

Building a Secure API with GraphQL & Spring Boot

Building a Secure API with GraphQL & Spring Boot

Build a Secure API with Spring Boot and GraphQL. GraphQL is a data query language developed by Facebook in 2012 to solve a shortcoming of REST APIs and traditional database models.

GraphQL is a data query language developed by Facebook in 2012 to solve a shortcoming of REST APIs and traditional database models. All too often, when programmers write REST API data queries, they default to retrieving entire data structures when they need only a part of it. For example, if you want to find out the number of comments on a blog post, a developer might typically retrieve the entire post and all associated fields along with all the comments and all their associated fields only to count the number of comments in the resulting array.

This is pretty inefficient. However, modern computers are fast. Even a shared server these days is pretty damn fast, as long as you have hundreds or thousands of users. However, when you get to Facebook scale, reaching a sizeable portion of the human beings on the internet, this breaks down. This kind of inefficiency becomes either unworkable or expensive.

It is possible, of course, to write a better SQL query (or NoSQL query) and write a specific API front end call to count the number of blog posts that is far more efficient - but you have to do this for every specific data query case.

There’s also the problem of wanting more data. What if you want a set of users blog posts and their associated comments AND you also want another set of unrelated data? Typically you make two separate calls to the REST API. In fact, a REST API interaction can result in dozens of calls over the course of a specific API interaction as all necessary data is retrieved. Again, on modern broadband and with relatively few users, this is functional. With hundreds of millions or even billions of users, it breaks down. Milliseconds of efficiency matter. Reducing the number of network calls matters.

There has to be a better way, a more generalized way to allow a front end to request only the data it wants, and to reduce the number of network interactions by combining requests for data.

This is why Facebook developed GraphQL. It provides a framework to describe your data model and allow consumers of the data to ask for exactly what they want and to retrieve predictable results.

When Would I Use GraphQL?

GraphQL is enormously powerful and flexible, and when used at internet scale, can provide a significant performance improvement over traditional REST APIs. So why wouldn’t you use it? Well, in my experience, on smaller projects, I felt like I was often just moving a lot of REST logic into GraphQL schema definitions, where validation and authorization code ended up being nested into a fairly ugly gigantic schema. I also felt like I was duplicating my data type definitions: once in GraphQL and another time in my ORM (this may not be a problem with all implementations).

GraphQL also brings a unique set of security concerns - there’s nothing wrong with it; it’s just going to be different than using REST APIs or SQL queries so you need to spend a little time researching security. I would consider using it in a situation where an application was going to scale quickly or where the data set might evolve significantly over time. If I had a limited set of well defined data on a smaller project, I’d probably just stick with a REST API.

How Do I Use GraphQL?

From a developer perspective, there are two major components:

  • the type descriptions
  • the query language

The type descriptions end up looking a lot like ORMs (if you’re familiar with those). You define types and fields on those types. Later you also define functions to retrieve that information from your database.

For example, let’s look at a very simple blog post definition.

type Post {  
    id: ID!  
    text: String!  
}

Pretty basic. A post has an id and a text field. Let’s add some comments to the Post type definition.

type Post {  
    id: ID!  
    text: String!  
    comments: [Comment!]!  
}  

type Comment {
id: ID!
text: String!
}

Now the type Post contains an array of type Comments. How do we turn this into a usable GraphQL schema definition?

We need to do two things:

  1. Define a “Query” type–the entry point for all GraphQL queries into our data
  2. Write methods for each field on each type that return the requested field from the data type
Define Your GraphQL Schema Query

In the simple example application we’re building, we would want to be able to query for Posts, so lets add a Query type with a post field of type Post. Our GraphQL schema would now look like this:

type Query {
post(id: ID!): Post
}

type Post {
id: ID!
text: String!
comments: [Comment!]!
}

type Comment {
id: ID!
text: String!
}

Just to reiterate, the types Post and Comment directly describe our data structure, and the type Query is a GraphQL-ism, a special type that defines the read-only entry point for the schema. There is also a Mutation type that provides a mutable access point in the schema.

Another thing to note is that fields can have arguments. If you look at the post field on the Query type, you’ll notice it has an argument of type ID. This argument can be specified in the query and will be passed to the function that is called to retrieve the data.

The exclamation points, by the way, simply mean that the type is non-nullable.

Types in GraphQL

GraphQL is basically about defining fields on types and querying for those fields. It is strongly typed, and has 5 built in scalar types:

  • Int: a 32-bit integer
  • Float: A signed double-precision floating-point value
  • String: A UTF‐8 character sequence
  • Boolean: true or false
  • ID: unique identifier, serialized as a String

Custom Scalar types can also be defined, such as a Date type, for example, and methods must be provided for serialization, deserialization, and validation.

Enums and Lists/Arrays can also be specified. We created a List of Comments in our Post type above.

The official GraphQL documentation have more information on types and schemas.

Using GraphQL in Java

In this tutorial, we are going to use a project called graphql-tools to integrate GraphQL with Spring Boot. According to the project github page readme, graphql-tools “allows you to use the GraphQL schema language to build your graphql-java schema and allows you to BYOO (bring your own object) to fill in the implementations.”

It works great if you have, or want to have, plain old java objects (POJO) that define your data model. Which I do.

What would our POJOs look like?

class Post {

protected int id;  
protected String text;  

Post(int id) {  
    this.id = id;  
    this.text = "";  
    this.comments = new ArrayList&lt;Comment&gt;();  
}  

Post(int id, String text, ArrayList&lt;Comment&gt; comments) {  
    this.id = id;  
    this.text = text;  
    this.comments = comments;  
}  

protected ArrayList&lt;Comment&gt; comments;  

}

class Comment {

private int id;  
private String text;  

Comment(int id, String text) {  
    this.id = id;  
    this.text = text;  
}  

}

These classes would define the basic types of our data model, and would correspond to the types in the GraphQL schema. They would be defined in separate java class files. (See what I mean about having duplicate data definitions?)

We would also need to define a couple “Resolvers”. Resolvers are used by graphql-tools to resolve non-scalar types. Each type in our GraphQL schema that contains non-scalar types needs to have an associated Resolver. Thus our Query type and our Post type need resolvers, but our Comment` type does not.

Here is what the Post Resolver might look like:

class PostResolver implements GraphQLResolver<Post> {

public List&lt;Comment&gt; getComments(Post post) {  
    return post.comments;  
}  

}

And here is a skeleton for the Query Resolver:

class Query implements GraphQLQueryResolver {

Post getPost(int id) {
    // Do something to retrieve the post
}  

}

Download the Spring Boot Example App

So now we get to the exciting part! Building a Spring Boot application that uses GraphQL, and securing that application with Okta (which we’ll get to last, and which Okta has made super easy).

Now would be a great time to go ahead and download our example application. It’s based on the example-graphql-tools project from this awesome project on the graphql-java github page.

git clone https://github.com/oktadeveloper/okta-springboot-graphql-example.git

This project is actually two sub-projects:

  • OktaShowToken: used to retrieve a working authorization token from an Okta OAuth OIDC application
  • OktaGraphQL: Spring Boot resource server based on GraphQL (to which we’ll be adding Okta Auth at the end
Create Okta OAuth Application and Install HTTPie

This tutorial makes the assumption that you already have a free Okta Developer account (if not, why don’t you head over to developer.okta.com and create one).

Why Okta?

At Okta, our goal is to make identity management a lot easier, more secure, and more scalable than what you’re used to. Okta is a cloud service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. Our API enables you to:

  • Authenticate and authorize your users
  • Store data about your users
  • Perform password-based and social login
  • Secure your application with multi-factor authentication
  • And much more! Check out our product documentation

Create a New OIDC App in Okta

To create a new OIDC app on Okta, you can begin with the default settings, then:

  1. Log in to your developer account, navigate to Applications, and click on Add Application.
  2. Select Web and click Next.
  3. Give the application a name, add http://localhost:8080/login as a Login redirect URI, and click Done.

We’re going to use HTTPie, a great HTTP command line client. So if you don’t have that installed, check it out and follow the installation instructions on httpie.org.

Check Out the OktaGraphQL Example App

Let’s ignore the OktaShowToken project for a moment and take a look at the OktaGraphQL, which is initially configured to run without authentication.

You’ll notice that there isn’t really much to it, beyond the POJO classes and resolvers in the com.okta.springbootgraphql.resolvers package, as well as the GraphQL schema definition found in src/main/resources/graphql-tools.graphqls.

Most of this should be pretty self-explanatory at this point. I’ll simply point out that our Query class (the query resolver) is a bit of a quick and dirty hack to avoid having to setup an actual database data source. We’re just generating the Posts and Comments on the fly based on their ID number. In the real implementation, you’d be adding some more business layer logic here, such as authorization, and looking up the data in your data source.

class Query implements GraphQLQueryResolver {

Post getPost(int id) {  

    if (id == 1) {  
        ArrayList&lt;Comment&gt; comments = new ArrayList&lt;Comment&gt;() {{  
            add(new Comment(1, "GraphQL is amazing!"));  
        }};  
        return new Post(id, "Okta + GraphQL is pretty sweet.", comments);  
    }  
    else if (id == 2) {  
        ArrayList&lt;Comment&gt; comments = new ArrayList&lt;Comment&gt;() {{  
            add(new Comment(1, "I can't believe how easy this is."));  
        }};  
        return new Post(id, "Is GraphQL better than a REST API?", comments);  
    }  
    else {  
        return null;  
    }  
}

}

Run Your First GraphQL Query

Open a terminal and from the OktaGraphQL project directory, start the Spring Boot application using the ./gradlew bootRuncommand.

It may take a few seconds to get started. You should see some output that ends like this:

Tomcat started on port(s): 9000 (http) with context path ''
Started GraphQLToolsSampleApplication in 19.245 seconds (JVM running for 19.664)

Leave that terminal window open and open another terminal window. Navigate again to the project root. Use the following command to run our first GraphQL Query:

http POST http://localhost:9000/graphql/ < json-requests/post1-all-data.json

Here we’re making a POST request with content type application/json (because this is the default for HTTPie) and we’re sending the query found in the json-requests/post1-all-data.json file as the request body.

The request body from json-requests/post1-all-data.json:

{
"query": "{ post(id: '1') { id, text, comments { id, text} } }"
}

The expected result:

HTTP/1.1 200
Content-Length: 122
Content-Type: application/json;charset=UTF-8
Date: Fri, 03 Aug 2018 21:50:25 GMT
{
"data": {
"post": {
"comments": [
{
"id": "1",
"text": "GraphQL is amazing!"
}
],
"id": "1",
"text": "Okta + GraphQL is pretty sweet."
}
}
}

At this point you could play around with the JSON request files, asking for less data or requesting a different post.

We’re going to move on to adding authentication.

Add Okta for OAuth

At this point we’re gonna need a few things from your Okta OAuth application settings:

The client ID and client secret can be found in the general settings for your application (select the Application menu, select the application you want to use, and finally select the General tab).

In the OktaGraphQL project, create a gradle.properties file and fill in the following properties:

oktaClientId={yourClientId}
oktaBaseUrl=https://{yourOktaDomain}

In the src/main/resources/application.yml file, add the following properties:

okta:
oauth2:
issuer: ${oktaBaseUrl}/oauth2/default
clientId: ${oktaClientId}
scopes: 'email profile openid'

Add the following dependencies to the build.gradle file in the OktaGraphQL project. These are the Spring Boot OAuth dependencies and the Okta Spring Boot starter.

compile group: 'com.okta.spring', name: 'okta-spring-boot-starter', version: '0.6.0'
compile group: 'org.springframework.security.oauth', name: 'spring-security-oauth2', version: '2.3.3.RELEASE'
compile ('org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.0.1.RELEASE')

Now let’s add two annotations (@EnableResourceServer and @EnableOAuth2Sso) to the GraphQLToolsSampleApplication class. It should look like this:

package com.okta.springbootgraphql;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;

@SpringBootApplication
@EnableResourceServer
@EnableOAuth2Sso
public class GraphQLToolsSampleApplication {

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

}

Stop your Spring Boot app (if it’s still running) and restart it using ./gradlew bootRun.

Run a query against the GraphQL server and you’ll see a 401 error:

HTTP/1.1 401
Cache-Control: no-store
Content-Type: application/json;charset=UTF-8
Date: Fri, 03 Aug 2018 22:10:50 GMT
Pragma: no-cache
Transfer-Encoding: chunked
WWW-Authenticate: Bearer realm="api://default", error="unauthorized", error_description="Full authentication is required to access this resource"
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
Get an Access Token

To access our protected GraphQL server now, we need an Okta access token. Typically this would be managed through the context of an application front end. For the purposes of this tutorial, we’re going to use our OktaShowToken application to retrieve an authorization token from our Okta application.

In the OktaShowToken project, create a gradle.properties file and fill in the following properties:

oktaClientId={yourClientId}
oktaClientSecret={yourClientSecret}
oktaBaseUrl=https://{yourOktaDomain}

Open a terminal, go to the OktaShowToken project root, and run ./gradlew bootRun.

Once the application completes launching, navigate to http://localhost:8080.

You’ll go through the Okta login and authentication process. You should see the Okta login screen.

After logging in, you’ll see a page of text that contains your access token. Leave this page open and/or copy this token somewhere where you can use it later.

Use the Access Token to Access the GraphQL Endpoint

First lets store the token value in a temporary shell variable:

TOKEN={accessTokenValue}

Then let’s run the request again setting the authorization header. You’ll need to run the following command from the OktaGraphQL directory.

http POST http://localhost:9000/graphql/ Authorization:"Bearer $TOKEN" < json-requests/post1-all-data.json

You should see these familiar results:

HTTP/1.1 200
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 122
Content-Type: application/json;charset=UTF-8
Date: Fri, 03 Aug 2018 22:22:00 GMT
Expires: 0
Pragma: no-cache
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
{
"data": {
"post": {
"comments": [
{
"id": "1",
"text": "GraphQL is amazing!"
}
],
"id": "1",
"text": "Okta + GraphQL is pretty sweet."
}
}
}
Learn More About Spring Boot, GraphQL, and Secure API Design

And that’s it! GraphQL is obviously a pretty deep subject, and if you’re coming from a traditional REST API background, you’ll need to dig into it a little to shift paradigms and properly implement everything.

In their docs, the GraphQL people make a point of repeatedly stating that GraphQL does not replace your business logic layer, but instead provides a data access query language and type schema that sits between your business logic layer and the outside world. Take a look at their docs on authorization to get a feel for this.

But as you can see, Okta’s Spring Boot Starter makes securing a GraphQL endpoint incredibly simple. If you’re interested in learning more about Spring Boot or GraphQL

Thanks For Visiting, Keep Visiting. If you liked this post, share it with all of your programming buddies!

This post was originally published here

How to Build a GraphQL API using Spring Boot

How to Build a GraphQL API using Spring Boot

This article will give an introduction to setting up a GraphQL server using Spring Boot so that it can be added to existing applications or used in new ones.

Introduction

In this tutorial we will build a Pokemon API that consumes data from a Postgres database, with a simple endpoint that performs a search by id.

Postgres setup

If you already have Postgres installed locally, you can skip this part, otherwise the easiest way to do it is by running a Docker image. Just install Docker and then:

docker run -p5432:5432 -d postgres:11.4-alpine

This command will start a Postgres instance on port 5432 with default user postgres and default database postgres.

Spring Boot setup

We will start by creating the initial project files using Spring Initializr. I've selected:

  • Gradle
  • Java
  • Spring Boot 2.1.6
  • Spring Web Starter
  • Spring Data JPA
  • PostgreSQL Driver

Besides Spring dependencies, we need to add the GraphQL libraries:

  • GraphQL Spring Boot Starter: will automatically create an /graphqlendpoint
  • GraphQL Spring Boot Starter Test: for our unit tests
  • GraphQL Java Tools: from its own documentation: "maps fields on your GraphQL objects to methods and properties on your java objects". This library requires version 1.3.* of Kotlin, so you need to create a gradle.properties file on the project root directory with content:
kotlin.version=1.3.10

Database connection

After adding the dependencies, you can edit the src/main/resources/application.properties file to add the Postgres configuration. If you are using the Docker command above to start Postgres locally, your file should be like this:

## PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=

#drop n create table again, good for testing, comment this in production
spring.jpa.hibernate.ddl-auto=create-drop

Run your application to test if everything is working so far: ./gradlew bootRun.

GraphQL Schema

GraphQL has a great schema language that adds type declatarations to its request and return values and couples this to the API implementation. Which means that what you declare on the schema must be implemented.

If we want to add an endpoint to search a pokemon by its id we should declare on src/main/resources/schema.graphqls file:

type Pokemon {
    id: ID!
    name: String!
}

type Query {
    pokemon(id: ID!): Pokemon
}

Our next step now must be the database search of a Pokemon instance by its id, or else the application won't run.

Query resolver

The declared schema expects to returns a Pokemon type that contains required attributes id and name.

To our application, that means Pokemon is a Java class with id and nameproperties but also a database table. We can use javax.persistenceannotations to automatically map Pokemon to database table with columns id and name:

@Entity
@Table(name = "pokemon")
public class Pokemon {

    public Pokemon(final Long id, final String name) {
        this.id = id;
        this.name = name;
    }

    @Id
    public Long id;

    @Column
    public String name;
}

The other expected class should be a Spring Bean that implements GraphQLQueryResolver interface and should have a method with name getPokemon, that matches the parameters and response exactly like we defined in the scheme:

@Component
public class Query implements GraphQLQueryResolver {

    public Pokemon getPokemon(Long id) {
        return new Pokemon(1L, "Pikachu");
    }
}

We can now perform an request at our new endpoint to check if its response is our Pikachu.

GraphiQL

GraphiQL configures an endpoint at our API that allow us to test any query. In our project it will run on address <a href="http://localhost:8080/graphiql" target="_blank">http://localhost:8080/graphiql</a>.

The left column is where we should write the queries, and the right column is the results. For example, if we enter the query:

# Searches a Pokemon with id 25 and returns its field 'name'
query {
  pokemon(id: 25){
    name
  }
}

We should expect the result on right column:

{
  "data": {
    "pokemon": {
      "name": "Pikachu"
    }
  }
}

So far it doesn't matter which parameter id we pass because we've fixed the response object, but now we will implement a database search.

Fetch Pokemons from database

Currently our application is not doing a real database search but returning a fixed instance. Let's now implement this part.

First we create a PokemonRepository interface that extends JpaRepository:

@Repository
public interface PokemonRepository extends JpaRepository<Pokemon, Long> {
}

Then we change our Query class to autowire this bean and perform the real database fetch:

@Component
public class Query implements GraphQLQueryResolver {

    @Autowired
    private PokemonRepository repository;

    public Pokemon getPokemon(Long id) {
        // Not returning a fixed instance anymore
        return repository.findById(id).orElse(null);
    }
}

Unit test

Our automated test will make use of GraphQLTestTemplate class which allow us to enter a query and verify its response. For example, if we want to test the search pokemon by id query, we first have to create a file in src/test/resources with this query:

# src/test/resources/get-pokemon-by-id.graphql
query {
    pokemon(id: "1") {
        id
        name
    }
}

The test class should be annotated with @GraphQLTest so it can resolve the GraphQLTestTemplate instance, and PokemonRepository should be annotated with @MockBean so we can mock its response using Mockito.

@RunWith(SpringRunner.class)
@GraphQLTest
public class DemoApplicationTests {

    @Autowired
    private GraphQLTestTemplate graphQLTestTemplate;

    @MockBean
    private PokemonRepository pokemonRepository;

    @Test
    public void getById() throws IOException {
        Pokemon pokemon = new Pokemon(1L, "Pikachu");
        when(pokemonRepository.findById(any()))
                .thenReturn(Optional.of(pokemon));

        GraphQLResponse response =
                graphQLTestTemplate.postForResource("get-pokemon-by-id.graphql");

        assertTrue(response.isOk());
        assertEquals("1", response.get("$.data.pokemon.id"));
        assertEquals("Pikachu", response.get("$.data.pokemon.name"));
    }
}

Basically the scenario we are testing here is the following:

  • Given the repository returns a pikachu when called the findByIdmethod
  • When we query GraphQL Api with get-pokemon-by-id.graphql
  • Then we expect the response to be a JSON containing the pikachu from repository
Conclusion

The challenge of implementing a GraphQL Api using Spring Boot relies mostly in the configuration and small details of Spring Boot functionality. Overall I think the integration works very well, specially the GraphQL Java Tools that enforces the code implementation.

Thanks for reading. If you liked this post, share it with all of your programming buddies!

Further reading

Spring & Hibernate for Beginners (includes Spring Boot)

Spring Framework Master Class - Learn Spring the Modern Way!

Master Microservices with Spring Boot and Spring Cloud

Spring Boot and OAuth2: Getting the Authorization Code

Monitor Your Java Apps with Spring Boot Actuator

An Introduction to Spring Boot

How to build GraphQL APIs with Kotlin, Spring Boot, and MongoDB?

Build a Rest API with Spring Boot using MySQL and JPA

Angular 8 + Spring Boot 2.2: Build a CRUD App Today!

Spring Boot vs. Spring MVC vs. Spring: How Do They Compare?

Top 4 Spring Annotations for Java Developer in 2019

GraphQL Tutorial: Understanding Spring Data JPA/SpringBoot

GraphQL Tutorial: Understanding Spring Data JPA/SpringBoot

Let's understand Spring Data JPA and Spring Boot with a practical example.

Let's understand Spring Data JPA and Spring Boot with a practical example.

GraphQL is a query language for APIs. Generally, while making REST endpoints in our APIs, the normal trend is to make an endpoint for a requirement. Let’s say your endpoint is returning a list of employees, and each employee has general properties, such as name, age, and address (suppose address is another model mapped to the employee in such a way that each employee has an address). Now, at one point in time, you require data only for their address i.e. a list of all addresses in the database (only country, city, and street). For this, you will require an all-new endpoint in your service.

Here comes the power of GraphQL, which lets you deal with only a single endpoint and that changes its output based on the body of the request. Each request will call the same endpoint but with a different RequestBody. It will receive only the result that it requires.

Refer to the code on GitHub for complete code files. It’s a maven project with an H2 database that has data.sql at classpath for database queries. This code rotates around getting a list of all employees from the database.

Now, let’s begin with a practical implementation with Spring Boot.

We have two model classes: employee and address with respective getters and setters.

@Entity
@Table
public class Employee {
String name;
@Id
String id;
int age;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "addid")
Address address;
  //......getters and setters....//
}

@Entity
@Table
public class Address {
@Id
@GeneratedValue
String addid;
String country;
String city;
String flat;
  //......getters and setters....//
}

To implement the repository, we have the EmployeeRepo as:

@Repository
public interface EmployeeRepo extends CrudRepository<Employee, String> {

public List<Employee> findAll();

}


Now, GraphQL requires a .graphqls file at the classpath, which it parses and understands the type of request it needs to handle. You will find employee.graphqls in the code. Let me explain that.

It contains:

type Employee{

.......Employee details

}

and type Address{

........Address Details

}

Here, we are defining the schema of our classes, which will, in one way or another, be returned as a response to the endpoint i.e either it will return all employees, the addresses of all employees, only the names of all employees, etc.

We also defined:

type Query{

allEmployee: [Employee]
}

Type of query (a query that will be sent by the client or that will be present in RequestBody) here is returning list of employees.

So, RequestBody to our endpoint will contain a root query as allEmployee.

Let’s discuss requests here:

  1. Requests that require all employees without their addresses:
{
allEmployee{
name
    age
id
}
}

  1. Requests that require only employee names and the country that they belong to:
{
allEmployee{
name
address {
country
}
}

}

  1. Requests that require only the address of all employees will be:
{
allEmployee{

address {
country
                city
                flat
                addid
}
}

}

For an explanation of the service layer of the code, read part 2, which is coming soon.

Meanwhile, you can access the full code on GitHub.

Learn More

Node.js - Express Persistent Session Store with PostgreSQL + Sequelize

Build a Simple Web App with Express, Angular, and GraphQL

How to Install PostgreSQL on Ubuntu 18.04

Understanding the basics of RESTful APIs

An Introduction to Queries in PostgreSQL

GraphQL with React: The Complete Developers Guide

GraphQL with Angular & Apollo - The Full-stack Guide

GraphQL: Learning GraphQL with Node.Js

Complete guide to building a GraphQL API

GraphQL: Introduction to GraphQL for beginners