Spring Boot + Kotlin + GraphQL + MongoDB — Part 1
Hack the Stack
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:
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:
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"
}
]
}
}