Putting Kotlin, MongoDB, Spring Boot and Heroku Together
Rewriting the PetClinic Sample Application in Kotlin
Intro
One of the rules I try to follow recently is that when I have some free time I spend it programming for fun in Kotlin. I guess you could call it a hobby. It also proved to be a great way to learn this language, as well as the JVM platform.
If you haven't heard yet, Kotlin is a new language that is statically-typed and can compile to both JVM bytecode and JavaScript. And even though Kotlin hasn’t been released, everyone can download it and start coding in it.
What’s a better way to learn a language than by writing a web application? Especially when the language is fully compatible with the Java platform, and you can leverage any Java framework. In my case I chose Spring, but mostly because it would give me a chance to try Spring Boot, the new Spring extension that helps bootstrap an application.
Kotlin
Now let’s get back to Kotlin. The easiest way to create a Kotlin project is by using Gradle. If you haven’t tried Gradle yet, I strongly recommend it. Gradle is simple but very powerful, probably the best build tool for Java.
Here is a build.gradle file that sets up the Kotlin plugin for your project:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath ‘org.jetbrains.kotlin:kotlin-gradle-plugin:<version>’
}
}
apply plugin: “kotlin”
repositories {
mavenCentral()
}
dependencies {
compile ‘org.jetbrains.kotlin:kotlin-stdlib:<version>’
}
Spring Boot
The sample below shows how to define a web application using Spring Boot and Kotlin.
Controller
ComponentScan
EnableAutoConfiguration
class AppController {
RequestMapping(array("/"))
ResponseBody
fun home(): String {
return "Hello World!"
}
}
fun main(args: Array<String>) {
SpringApplication.run(array(javaClass<AppController>()), args)
}
Pretty simple, but what’s even better , there are no XML files. Doesn’t it sound fantastic?
MongoDB and Kotlin NoSQL
Since I’m coding for fun I can choose any database I like, right? Why not try something new, like MongoDB?
Spring has a really great extension that helps access MongoDB. We may try it later, but this time we’ll do it another way. Some time ago I’ve started a project called Kotlin NoSQL, which is a small library for accessing NoSQL databases, including MongoDB.
To add the library to your project, use the following dependency in your build.gradle file.
dependencies {
compile group: ‘org.jetbrains.kotlin’, name: ‘kotlin-nosql-mongodb’, version: ‘0.1-SNAPSHOT’
}
The Kotlin NoSQL library lets us define a schema for our database and run typed queries in Kotlin. The sample below contains a schema definition for the Owners collection:
object Owners : Schema<Owner>(“owners”, javaClass()) {
val firstName = string(“firstName”)
val lastName = string(“lastName”)
val address = string(“address”)
val city = string(“city”)
val telephone = string(“telephone”);
{
ensureIndex(text = array(firstName, lastName, telephone))
}
}class Owner(val firstName: String, val lastName: String, val address: String, val city: String, val telephone: String) {
val id: Id<String, Owners>? = null
}
And here’s how we can inject a reference to our MongoDB instance in the application:
Configuration open class AppConfig {
Bean open fun getMongoDB(): MongoDB {
val mongoURI = MongoClientURI(System.getenv(“MONGO_URI”))
return MongoDB(uri = mongoURI, schemas = array(Owners, Pets, PetTypes, Vets, Visits, Specialities))
}
}
Once we've defined the MongoDB bean we can get it’s instance in our controller classes:
Controller RequestMapping(value = array(“/owners”))
class OwnerController [Autowired] (val db: MongoDB) {
}
Take a look at the sample below how the search controller is implemented:
RequestMapping(array("/"), method = array(RequestMethod.GET))
fun search(RequestParam("q") query: String, model: Model): String {
model.addAttribute("owners", Owners.findAll { text(query) }.toList())
}
return "owners/index"
}
The next sample shows how to get a map of owners and corresponding pets by a search query:
val ownerPets = Owners.findAll { text(query) }.map { owner -> Pair(owner, Pets.findAll { ownerId.equal(owner.id) }.toList())}.toList())
Kotlin NoSQL is still in progress and not everything is supported yet. If you decide to pitch in, send your pull requests to the GitHub repository.
Heroku
And finally, since we have a working application, why don’t we deploy it to the cloud? Heroku runs both Java and Scala, why can’t we run Kotlin there as well?
With such a great tool like Gradle, impossible is nothing, because Heroku provides a dedicated buildpack for Gradle applications.
To deploy a Kotlin application to Heroku simply add the following code to your build.gradle file:
apply plugin:'application'mainClassName = "kotlinx.nosql.mongodb.samples.petclinic.controllers.ControllersPackage"
applicationName = "app"task stage(dependsOn: ['clean', 'installApp'])
And don't forget to add the following Procfile file to the root directory.
web: ./build/install/app/bin/app
That’s it. Now you can deploy your Kotlin application to Heroku.
MongoLab
Before we run the application in the cloud, we also need a cloud database. The only problem I faced here is that not every cloud provider has the latest version of MongoDB hosted. Having the latest version was important for me because I needed full-text search support enabled.
Finally I found MongoLab which has Mongo 2.4 with an option to enable the experimental fulltext search.
Summary
I hoped you enjoyed the article. The source code for my application is available on GitHub, and the application is running on Heroku.
Your feedback is very welcome!