GraphQL Java Example for Beginners [Spring Boot]
In this article, we will look at a GraphQL Java example and build a simple GraphQL server with Spring Boot.
Join the DZone community and get the full member experience.
Join For FreeGraphQL 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. GraphQL is a strongly-typed protocol and all data operations are validated against a GraphQL schema.
In this article, we will look at a GraphQL Java example and build a simple GraphQL server with Spring Boot.
Adding Maven Dependencies
Create a sample Spring Boot application and add the following dependencies.
- graphql-spring-boot-starter is used for enabling GraphQL servlet, and it becomes available at a path /graphql. It initializes the
GraphQLSchema
bean. - graphql-java allows us to write schema with GraphQL schema language, which is simple to understand.
- graphiql-spring-boot-starter provides a user interface with which we could test our GraphQL queries and view query definitions.
<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 Schemas called Schema Definition Language (SDL). The schema definition consists of all the API functionalities available at an endpoint.
A typical example of a 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 graphql folder under src/main/resources, and create a vehicleql.graphqls file 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 Query type 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 the query and result is the same. This is important in the GraphQL world because we always get back the result that we expect.
We will see a working example in this article later.
The Mutation type 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 Mutation type in our schema definition.
We will now define a service that will 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, and open this 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 should be:
{
"data": {
"createVehicle": {
"id": "1"
}
}
}
Let's 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 a 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 a basic GraphQL Java example with Spring Boot. Check out the detailed documentation here.
The complete source code for this tutorial can be found on GitHub.
Further Reading
Published at DZone with permission of Swathi Prasad, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments