Spring Boot + Kotlin + GraphQL + MongoDB — Part 1

Hack the Stack

Aron Balog
6 min readMay 6, 2018

--

Spring Boot

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”. Most Spring Boot applications need very little Spring configuration.

Features

  • Create stand-alone Spring applications
  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
  • Provide opinionated ‘starter’ POMs to simplify your Maven configuration
  • Automatically configure Spring whenever possible
  • Provide production-ready features such as metrics, health checks and externalized configuration
  • Absolutely no code generation and no requirement for XML configuration

Kotlin

Kotlin is statically typed programming language for modern multi-platform applications. It drastically reduce the amount of boilerplate code.

Example of POJO with getters, setters, equals(), hashCode(), toString() and copy() in a single line:

data class Customer(val name: String, val email: String, val company: String)

Example of singleton:

object ThisIsASingleton {
val companyName: String = "JetBrains"
}

GraphQL

GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. GraphQL isn’t tied to any specific database or storage engine and is instead backed by your existing code and data.

A GraphQL service is created by defining types and fields on those types, then providing functions for each field on each type. For example, a GraphQL service that tells us who the logged in user is (me) as well as that user's name might look something like this:

type Query {
me: Person
}
type Person {
id: ID
name: String
}

Once a GraphQL service is running (typically at a URL on a web service), it can be sent GraphQL queries to validate and execute. A received query is first checked to ensure it only refers to the types and fields defined, then runs the provided functions to produce a result.

For example the query:

{
me {
name
}
}

Could produce the JSON result:

{
"me": {
"name": "Sherlock Holmes"
}
}

MongoDB

MongoDB is a document database with the scalability and flexibility that you want with the querying and indexing that you need.

  • MongoDB stores data in flexible, JSON-like documents, meaning fields can vary from document to document and data structure can be changed over time.
  • The document model maps to the objects in your application code, making data easy to work with.
  • MongoDB is a distributed database at its core, so high availability, horizontal scaling, and geographic distribution are built in and easy to use.

Let’s get started!

You can find this project at GitHub.

Go to start.spring.io and create starter package with following dependencies:

  • Web
  • MongoDB

application.properties configuration:

spring.data.mongodb.database=example
spring.data.mongodb.port=27017

MongoDB must be installed prior running the mvn clean install command.

If everything is ok, it should build successfully:

Run mvn spring-boot:run and try to open http://localhost:8080 in web browser.

Response should look like this:

Integrating GraphQL

Add following dependencies to pom.xml file:

<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>8.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-servlet</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.9.Final</version>
</dependency>

and run mvn clean install. This should install all needed dependencies into the project.

Create new package with name graphql and a new package query under it.

Under resources folder, create a graphql directory. In this folder we are going to create schema files.

Package & folder structure:

Package & folder structure

Our first GraphQL query

Create new Kotlin class Query under graphql package:

and create new file named query.graphqls in resources/graphql directory:

Query type is now paired with Query class. Pay attention to @Component annotation. It indicates that an annotated class is a “component”. In Spring, such classes are considered as candidates for auto-detection when using annotation-based configuration and classpath scanning, so no additional configuration is required.

Now, run project by executing following command in terminal:

mvn spring-boot:run

Making requests

GraphiQL

/ˈɡrafək(ə)l/

A graphical interactive in-browser GraphQL IDE.

Open GraphQL web interface — GraphiQL (http://localhost:8080/graphiql) in your browser. It should look like this:

GraphiQL interface

In the editor, type a query:

query {
version
}

and press play button to execute it. Server should respond with:

{
"data": {
"version": "1.0.0"
}
}

Congratulations! You have GraphQL service up and running.

Now, we are going to create MongoDB database, and make some read & write queries to it via GraphQL.

Creating an Entity

Entity in this example is Person.

Create new package data and data class Person inside it:

@Document annotation ensures a MongoDB document from person collection is mapped to this class.

Creating a Repository

Create new package repository and PersonRepository interface inside it:

We want our repository to be able to:

  • find person by its id
  • find all the persons containing characters from a given string (name)

MongoRepository extends CrudRepository so we can simply build queries by naming the repository functions properly.

findById is already provided by CrudRepository so there is no need to declare this function.

Creating a DAO

Create new package dao and PersonDao class inside it:

PersonDao injects PersonRepository interface so it can perform database queries.

Connecting GraphQL with MongoDB

Create new directory type inside resources/graphql directory and create person.graphqls (GraphQL schema) file inside it:

Extend query.graphqls like this:

Create new package query inside graphql package and create PersonQueryResolver class inside it:

PersonQueryResolver injects PersonDao, which is our connection to a data layer.

Note that query names and arguments inside query.graphqls match the method names and arguments inside PersonQueryResolver class. When the application boots, it collects all the GraphQLQueryResolver subclasses and match them with appropriate queries.

At this point, GraphQL queries should be able to read data from MongoDB database.

We need to write some data to the database to be able to read it. Execute following commands in terminal:

$ mongo
$ use example
$ db.person.insertOne( { _id: "1", name: "Sherlock Holmes" } );

Switch back web browser, go to GraphiQL interface, and run some queries!

query {
personsByName(name: "Sherlock") {
id
name
}
}

should return:

{
"data": {
"personsByName": [
{
"id": "1",
"name": "Sherlock Holmes"
}
]
}
}

Architecture graph

--

--

Aron Balog

Unstoppable coder, passionate about software architecture, primarily focused on iOS development. https://github.com/aronbalog | https://twitter.com/Aron_Balog