05 December 2016

Simple REST Server With Kotlin


With micro services being the latest important development in Software Engineering anyone doing server side development needs to be involved in this area. One of the major areas where Kotlin is being used is in server side development, especially micro services. This post will be covering how to create a simple REST server using the following technologies:


  • Gradle (any 2.x version)
  • Kotlin v1.0.5-2 (stable version)
  • Grizzly v2.3.28 (embedded HTTP web server)
  • Grizzly Jersey Container v2.23.2 (JAX-RS implementation for Grizzly)
  • Jackson v2.23.2 (JSON library)
  • Linux PC (using Debian, Ubuntu or Linux Mint)

Setup Project Directory

  1. Create a project directory called hello_rest_server
  2. Copy the Gradle wrapper directory and the gradlew file to the project directory
  3. In the project directory create a file called settings.gradle containing rootProject.name = 'hello-rest-server'
  4. Create a Gradle build file called build.gradle in the project directory containing the following:

-------------------------------------------------------------------------------------
group 'org.example'version '0.1-SNAPSHOT'
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.5-2'    }
}

apply plugin: 'kotlin'apply plugin: 'application'
repositories {
    mavenCentral()
}

dependencies {
    compile 'org.jetbrains.kotlin:kotlin-stdlib:1.0.5-2'    compile 'org.glassfish.grizzly:grizzly-framework:2.3.28'    compile 'org.glassfish.jersey.containers:jersey-container-grizzly2-http:2.23.2'    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.23.2'}

// A Task to run the program.run {
    mainClassName = 'org.example.hellorestserver.RestServerKt'    //args = ["arg1", "arg2"]}

// A Task to create a JAR file for the program.jar {
    from configurations.compile.collect { zipTree it }
    manifest.attributes 'Main-Class': 'org.example.hellorestserver.RestServerKt'}
-------------------------------------------------------------------------------------


Text version:

-------------------------------------------------------------------------------------
group 'org.example'
version '0.1-SNAPSHOT'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.5-2'
    }
}

apply plugin: 'kotlin'
apply plugin: 'application'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.jetbrains.kotlin:kotlin-stdlib:1.0.5-2'
    compile 'org.glassfish.grizzly:grizzly-framework:2.3.28'
    compile 'org.glassfish.jersey.containers:jersey-container-grizzly2-http:2.23.2'
    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.23.2'
}

// A Task to run the program.
run {
    mainClassName = 'org.example.hellorestserver.RestServerKt'
    //args = ["arg1", "arg2"]
}

// A Task to create a JAR file for the program.
jar {
    from configurations.compile.collect { zipTree it }
    manifest.attributes 'Main-Class': 'org.example.hellorestserver.RestServerKt'
}
-------------------------------------------------------------------------------------

Create Kotlin Source Files


Create the following directory structure in the project directory, along with the kt files as shown below:

src
├── main
│   ├── java
│   ├── kotlin
│   │   └── org
│   │       └── example
│   │           └── hellorestserver
│   │               ├── HelloResource.kt
│   │               └── restServer.kt
│   └── resources
└── test
    ├── java
    ├── kotlin
    └── resources


To begin restServer.kt will act as the entry point file for the REST server, which will be edited first by adding the following code:

-------------------------------------------------------------------------------------
package org.example.hellorestserver

import org.glassfish.grizzly.http.server.HttpServer
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory
import org.glassfish.jersey.jackson.JacksonFeature
import org.glassfish.jersey.server.ResourceConfig
import javax.ws.rs.ProcessingException
import javax.ws.rs.core.UriBuilder


fun main(args: Array) {
    val HOST = "localhost"    val PORT = 9000    val baseUri = UriBuilder.fromUri("http://$HOST/").port(PORT).build()
    var server: HttpServer? = null
    try {
        server = GrizzlyHttpServerFactory.createHttpServer(baseUri, createConfiguration())
        println("REST Server Address: $HOST:$PORT")
    } catch (ex: ProcessingException) {
        println("Server Error: ${ex.message}")
        println("Exiting REST server...")
        server?.shutdown()
    }
}

private fun createConfiguration(): ResourceConfig {
    val config = ResourceConfig(HelloResource::class.java)

    // Optional but good practise to manually specify the JSON mapping implementation to use.    config.packages("org.example.hellorestserver").register(JacksonFeature::class.java)
    return config
}
-------------------------------------------------------------------------------------


Text version:

-------------------------------------------------------------------------------------
package org.example.hellorestserver

import org.glassfish.grizzly.http.server.HttpServer
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory
import org.glassfish.jersey.jackson.JacksonFeature
import org.glassfish.jersey.server.ResourceConfig
import javax.ws.rs.ProcessingException
import javax.ws.rs.core.UriBuilder


fun main(args: Array) {
    val HOST = "localhost"
    val PORT = 9000
    val baseUri = UriBuilder.fromUri("http://$HOST/").port(PORT).build()
    var server: HttpServer? = null

    try {
        server = GrizzlyHttpServerFactory.createHttpServer(baseUri, createConfiguration())
        println("REST Server Address: $HOST:$PORT")
    } catch (ex: ProcessingException) {
        println("Server Error: ${ex.message}")
        println("Exiting REST server...")
        server?.shutdown()
    }
}

private fun createConfiguration(): ResourceConfig {
    val config = ResourceConfig(HelloResource::class.java)

    // Optional but good practise to manually specify the JSON mapping implementation to use.
    config.packages("org.example.hellorestserver").register(JacksonFeature::class.java)
    return config
}
-------------------------------------------------------------------------------------

Above the host name and port number are stored in constants and referred to in the UriBuilder.fromUri function which creates a URI object. An attempt is made to start the server by creating an HttpServer object via the GrizzlyHttpServerFactory.createHttpServer function. Only 2 arguments need to be passed through, a URI and the resource configuration (ResourceConfig object).

Grizzly needs the resource configuration in order to know how to do the REST resource mapping. In this case the HelloResource class object (Java version) is passed as an argument to the ResourceConfig constructor in the defined createConfiguration function. If the server fails to start then a ProcessingException will be thrown. When that situation occurs the server error message is outputted to the console, followed by shutting down the server before exiting the program.

Now setup the REST resource mapping by adding the following code to HelloResource.kt:

-------------------------------------------------------------------------------------
package org.example.hellorestserver

import javax.ws.rs.GETimport javax.ws.rs.Pathimport javax.ws.rs.Producesimport javax.ws.rs.QueryParamimport javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response

@Path("/hello")
class HelloResource {
    @GET    @Produces(MediaType.APPLICATION_JSON)
    fun getMessage(@QueryParam("name") name: String): Response {
        println("Processing request...")
        return Response.ok(mapOf("msg" to "Hello $name! :)"), MediaType.APPLICATION_JSON).build()
    }
}
-------------------------------------------------------------------------------------


Text version:

-------------------------------------------------------------------------------------
package org.example.hellorestserver

import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response

@Path("/hello")
class HelloResource {
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    fun getMessage(@QueryParam("name") name: String): Response {
        println("Processing request...")
        return Response.ok(mapOf("msg" to "Hello $name! :)"), MediaType.APPLICATION_JSON).build()
    }
}
-------------------------------------------------------------------------------------

Above the HelloResource class handles the REST resource mapping for the /hello path (part of the URI). There is a single function (getMessage) which handles a GET HTTP request that contains a single URI query parameter called name. All that the function does is output a message to the console, and returns a message (as a HTTP 200 response via Response.ok function) in JSON (specified in the Produces annotation) form.

To start the REST server execute ./gradlew run in the project directory. Use the curl command to test out the server (eg curl localhost:9000/hello?name=Elvis). Exit the server using the Ctrl+c keyboard shortcut in the same console running the server.

29 comments:

  1. Great post! I am actually getting ready to across this information, It’s very helpful for this blog.Also great with all of the valuable information you have Keep up the good work you are doing well.


    rpa training in Chennai | rpa training in velachery

    rpa training in tambaram | rpa training in sholinganallur


    ReplyDelete
  2. I am sure this post has helped me save many hours of browsing other related posts just to find what I was looking for. Many thanks!
    Data Science training in Chennai | Data science training in bangalore
    Data science training in pune| Data science online training
    Pyton training in Kalyan nagar

    ReplyDelete
  3. Thank you for sharing such great information with us. I really appreciate everything that you’ve done here and am glad to know that you really care about the world that we live in
    java training in chennai

    java training in marathahalli | java training in btm layout

    ReplyDelete
  4. A very nice guide. I will definitely follow these tips. Thank you for sharing such detailed article. I am learning a lot from you.

    rpa training in electronic-city | rpa training in btm | rpa training in marathahalli | rpa training in pune

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Excellent Blog! I would like to thank for the efforts you have made in writing this post. I am hoping the same best work from you in the future as well. I wanted to thank you for this websites! Thanks for sharing. Great websites!
    AI course in mumbai

    ReplyDelete


  7. I like viewing web sites which comprehend the price of delivering the excellent useful resource free of charge. I truly adored reading your posting. Thank you!

    artificial intelligence course in mumbai

    ReplyDelete
  8. Great information.Really expecting a lot of articles.

    ReplyDelete
  9. I really enjoy simply reading all of your weblogs. Simply wanted to inform you that you have people like me who appreciate your work. Definitely a great post. Hats off to you! The information that you have provided is very helpful.

    data science interview questions

    ReplyDelete
  10. Really nice and interesting post. I was looking for this kind of information and enjoyed reading this one. Keep posting. Thanks for sharing.Best data science courses in hyerabad

    ReplyDelete


  11. Nice article and thanks for sharing with us. Its very informative





    Tableau Training in Hyderabad

    ReplyDelete

  12. Nice article and thanks for sharing with us. Its very informative


    AI Training in Hyderabad

    ReplyDelete
  13. Nice article and thanks for sharing with us. Its very informative


    Plots in THIMMAPUR

    ReplyDelete

  14. Hello! I just wish to give an enormous thumbs up for the nice info you've got right here on this post. I will probably be coming back to your weblog for more soon!
    data scientist training in hyderabad

    ReplyDelete
  15. Thanks for posting the best information and the blog is very important mdata science institutes in hyderabad

    ReplyDelete
  16. Software Development in Dubai
    https://www.nsreem.com/ourservices/software-development/
    NSREEM develop amazing desktop and web applications that are tailored to your specific requirements.
    NSREEM is #1 in Software Development in Dubai
    1633164662135-11

    ReplyDelete

  17. I was basically inspecting through the web filtering for certain data and ran over your blog. I am flabbergasted by the data that you have on this blog. It shows how well you welcome this subject. Bookmarked this page, will return for extra. data science course in jaipur

    ReplyDelete
  18. I wanted to leave a little comment to support you and wish you a good continuation. Wishing you the best of luck for all your blogging efforts.
    data science coaching in hyderabad

    ReplyDelete
  19. Very interesting blog. Alot of blogs I see these days don't really provide anything that I'm interested in, but I'm most definately interested in this one. Just thought that I would post and let you know. data analytics course in surat

    ReplyDelete
  20. Always so interesting to visit your site.What a great info, thank you for sharing. this will help me so much in my learning
    full stack web development course malaysia

    ReplyDelete