Blog Infos
Author
Published
Topics
, ,
Published
Topics
, ,

If you haven’t set the Ktor project yet and need help, checkout

This tutorial is the second part of the series. It’ll be focussed on developing the simple static REST APIs for our dog project.

Here are the following APIs that we’ll be building

POST : Add a dog : http://127.0.0.1:8080/dogs

GET : Get all dogs : http://127.0.0.1:8080/dogs

GET : Get dog by id: http://127.0.0.1:8080/dogs/{id}

DELETE : Delete dog by id: http://127.0.0.1:8080/dogs/{id}

As we know, we need to define Routes for our application and we define them inside our modules. So let’s create a new class named as DogsRoute.kt.

Because our apis are static which means we’ll be saving our dogs into a list inside our application. So let’s create a list of dogs.

val dogs = mutableListOf<Dog>()

For our demo purposes, this will serve as a storage.

Now let’s create a Dog class as

@Serializable
data class Dog(val name: String, val color: String = "Unknown", val id: Int = 0)

As you can see we marked the class as Serializable which makes it eligible for being serialized during transactions.

Alright, it’s time to add our Routes inside our DogsRoute.kt:

POST — Add Dog

fun Route.addDogRoute() {
    post {
        val dog = call.receive<Dog>()
        dogs.add(dog)
        call.respond(HttpStatusCode.Created, "Dog saved")
    }
}

It is an extension function operated on Route object. Under the Route, we create a post request by keyword post. As this is a post request, there will be a body that we’ll receive. So we can extract the body by call.receive<Dog>().

Then we save our dog in the list and responds with a http code and a message with call.respond function.

GET — Dog by id

fun Route.getDogRoute() {
    get("{id}") {
        val id = call.parameters["id"]?.toInt()
        val dog = dogs.find { it.id == id }
        dog?.let {
            call.respond(HttpStatusCode.Found, it)
        } ?: call.respond(HttpStatusCode.NotFound, "No dog found with id $id")

    }
}

Similar to our add dog route, we simply created a GET request by using the keyword get and passing the dog id as path parameterWe check if there is any dog present with the given id and respond accordingly. This also shows how can we extract path parameters in a GET request.

GET — All Dogs

fun Route.getDogsRoute() {
    get {
        if (dogs.isNotEmpty())
            call.respond(HttpStatusCode.OK, dogs)
        else
            call.respond(HttpStatusCode.NotFound, "No dog found")
    }
}

Similar to our GET by id route, here we checks if the list of dogs is empty or not and respond accodingly.

DELETE — Dog by id

fun Route.deleteDogRoute() {
    delete("{id}") {
        val id = call.parameters["id"]?.toInt() ?: return@delete call.respond(
            HttpStatusCode.BadRequest,
            "Dog id required"
        )
        if (dogs.removeIf { it.id == id })
            call.respond(HttpStatusCode.Accepted, "Dog removed successfully")
        else
            call.respond(HttpStatusCode.NotFound, "No dog found with id $id")
    }
}

 

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

Jobs

In this route, we again extracts the dog id and remove it from the list and respond back to user.

Now we’ve defined all our routes, it is time to add them inside a module that we can then pass on to our application module. We can do that by adding all the routes inside the routing tag as follows

fun Application.registerDogsRoute() {
    routing {
        addDogRoute()
        getDogRoute()
        getDogsRoute()
        deleteDogRoute()
    }
}

Boom! Our routes are added to the dog module. One thing to note here is the we need a specific url path for all our dog specific routes i.e. all dog routes should start with /dogs and we can achieve it easily by modifying our registerDogsRoute module as

fun Application.registerDogsRoute() {
    routing {
        route("/dogs") {
            addDogRoute()
            getDogRoute()
            getDogsRoute()
            deleteDogRoute()
        }
    }
}

The only thing remains here is to add this module to our application module as follows

@Suppress("unused") // application.conf references the main function. This annotation prevents the IDE from marking it as unused.
fun Application.module() {
    configureSerialization()
    configureMonitoring()
    registerDogsRoute()
}

Whoa! We’ve just finished developing our APIs using Ktor and ready to test them. Let’s do it in the following tutorial and see them in action.

Full code can be found on github : here under static-apis branch.

Hope this would be helpful in some way.

Cheers! 🍺

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE
blog
Drag and Drop reordering in Recyclerview can be achieved with ItemTouchHelper (checkout implementation reference).…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu