Spring Boot with GraphQL — Part 1

Saloni Kaur
3 min readMar 25, 2019

This is Part 1 of more articles to come, where I have documented the steps I took to create a Spring Boot server which exposes a GraphQL endpoint.

I will be starting from the basics and moving on to make the application more advanced.

This example uses Apache Maven. Below is the POM file. All the versions of the different dependencies needed to compile and run the example are listed below. I have used the latest versions of the dependencies available at the point of writing this article.

<groupId>com.saloni</groupId>
<artifactId>graphqlguide</artifactId>
<version>1.0-SNAPSHOT</version>

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

<properties>
<java.version>1.9</java.version>

<graphql-spring-boot-starter.version>5.0.2</graphql-spring-boot-starter.version>
<graphql-java-tools.version>5.2.4</graphql-java-tools.version>
</properties>

<dependencies>
<!-- spring-boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- graphql-java -->
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>${graphql-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>${graphql-java-tools.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>${graphql-spring-boot-starter.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<!-- spring-boot-maven-plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

Spring Boot Starters is a one-stop-shop for all the Spring and related technologies. We include the spring-boot-starter-web dependency which will automatically setup an embedded Apache Tomcat.

GraphQL-Java project provides a Java implementation for GraphQL. It comes with graphql-spring-boot-starter which will auto-configure a GraphQL Servlet that is accessible via /graphql. With graphiql-spring-boot-starter, an interface for editing and testing your GraphQL API is provided at /graphiql. If you know GraphQL, you know there is a concept of schema files which defines the GraphQL endpoints and contracts. For that, graphql-java-tools library is needed as it helps create a GraphQL schema by parsing all GraphQL schema files found on the classpath.

I personally like to use Lombok library to avoid the repetitive boilerplate codes in Java POJOs. It allows us to use annotations for getters/setters as wells as constructors.

We use spring-boot-maven-plugin, which is a Maven plugin, that allows us to build a single, runnable jar and startup our GraphQL API server via a Maven command.

Schema

A schema defines your GraphQL API by specifying each field that can be interacted with as well as the operations to CRUD (Query/Mutations) data. Below is a .graphqls file which can be placed anywhere in the classpath. I’ve placed it in src/main/resources/schema.graphqls.

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

type Query {
teacher(id: ID!): Teacher
}

In order for the GraphQL schema to be built, Java POJOs will be required. Below is Teacher.java for sample. We are using Lombok annotations instead of defining getters, setters, constructors.

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
private String id;
private String name;
}

Resolver

When using GraphQL Java Tools, we need to use resolvers implementing GraphQLQueryResolver interface.

public class SchoolQueryResolver implements GraphQLQueryResolver {

@Autowired
private TeacherRepository teacherRepository;

public Teacher teacher(String id){
return teacherRepository.find(id);
}
}

Repository

The resolver will most likely fetch data from the database and for separation of concern, we have added a repository to do that.

@Component
public class TeacherRepository {

private Map<String, Teacher> teachers;

public TeacherRepository(Map<String, Teacher> teachers) {
this.teachers = new HashMap<>();
}

public Teacher find(String id){
return teachers.get(id);
}

}

We cannot just run the app yet without a main method. Every Spring app requires the @SpringBootApplication defined on the class where the main method exists.

@SpringBootApplication
public class Application {

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

Now, you may start your app using the main method or by running the command:

mvn spring-boot:run

Then access the interactive graphql playground at: http://localhost:8080/graphiql

Common mistakes:

We usually tend to over-achieve in our learning journey or even when we are just starting an application from scratch. In my case, sometimes I tend to define extra queries in the schema.graphqls, that I know will be required in the future. In that case, we must also define those methods in the resolver class. If not the server will not start.

Also note that this class has to be defined in a package other than src/main/java. In our case, it is defined in src/main/java/com.graphqlguide. This is because Spring component scanning does not take place in the default package.

Github repo: https://github.com/missa4892/graphqlguide

--

--