Reputation: 1843
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
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