Victor Orlyk
Victor Orlyk

Reputation: 1843

ktor failing to parse response No transformation found: class io.ktor.utils.io.ByteBufferChannel

I am relatively new to Kotlin and Ktor. And while playing around, I was trying to parse response from the HTTP response, but it always throws an error at me.

package com.example

import com.example.models.SpaceShip
import io.ktor.server.application.*
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.apache.*
import io.ktor.client.request.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.http.*
import kotlinx.serialization.Serializable

fun main(args: Array<String>): Unit =
    io.ktor.server.netty.EngineMain.main(args)



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

    install(ContentNegotiation) {
        json()
    }

    val client = HttpClient(Apache)

    routing {

        get("/spaceship") {
            val ship = SpaceShip("viktor", 2.2)
            call.respond(ship)
        }

        get("/consumeService") {
            val ship: SpaceShip =
                client.request("http://0.0.0.0:8080/spaceship"){
                    accept(ContentType.Application.Json)
                }.body()
            call.respond(ship)
        }
    }
}

@Serializable
data class SpaceShip(val name: String, val fuel: Double)

Here is the error while making a request to GET http://0.0.0.0:8080/consumeService

2022-04-17 10:59:09.432 [eventLoopGroupProxy-4-3] ERROR Application
                - Unhandled: GET - /consumeService
io.ktor.client.call.NoTransformationFoundException: No transformation found: class io.ktor.utils.io.ByteBufferChannel -> class com.example.models.SpaceShip
with response from http://0.0.0.0:8080/spaceship:
status: 200 OK
response headers: 
Content-Length: 28
, Content-Type: application/json; charset=UTF-8
, Connection: keep-alive

    at io.ktor.client.call.HttpClientCall.body(HttpClientCall.kt:92)
    at com.example.ApplicationKt$module$2$2.invokeSuspend(Application.kt:54)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:138)
    at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:112)
    at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:14)
    at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:62)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
    at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:138)
    at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:112)
    at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:14)
    at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:62)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
    at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:138)
    at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:112)
    at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:14)
    at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:62)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
    at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:138)
    at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:112)
    at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:14)
    at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:62)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:503)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.ktor.server.netty.EventLoopGroupProxy$Companion.create$lambda-1$lambda-0(NettyApplicationEngine.kt:263)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)

While request to GET http://0.0.0.0:8080/spaceship is successfull

Content-Length: 28
Content-Type: application/json
Connection: keep-alive

{
  "name": "viktor",
  "fuel": 2.2
}

Upvotes: 4

Views: 6802

Answers (1)

Victor Orlyk
Victor Orlyk

Reputation: 1843

thanks Pylyp Dukhov and Aleksei Tirman for helping solve this out. So yeah I din't know that i need to enable it twice

package com.example

import com.example.models.SpaceShip
import io.ktor.server.application.*
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.apache.*
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation as ClientContentNegotiation
import io.ktor.client.request.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation as ServerContentNegotiation
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.http.*
import kotlinx.serialization.json.Json

fun main(args: Array<String>): Unit =
    io.ktor.server.netty.EngineMain.main(args)



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

    install(ServerContentNegotiation) {
        json()
    }

    val client = HttpClient(Apache){
        install(ClientContentNegotiation){
            json(Json {
                prettyPrint = true
                isLenient = true
            })
        }
    }

    routing {

        get("/spaceship") {
            val ship = SpaceShip("viktor", 2.2)
            call.respond(ship)
        }

        get("/consumeService") {
            val ship: SpaceShip =
                client.request("http://0.0.0.0:8080/spaceship"){
                    accept(ContentType.Application.Json)
                }.body()
            call.respond(ship)
        }
    }
}

Upvotes: 5

Related Questions