Issue
I have a simple Spring Boot WebFlux
api and I am trying to use Ktor
to call it.
Here is my controller
@RestController
@RequestMapping("api/v1")
class TestController {
@RequestMapping(method = [RequestMethod.GET], value = ["/values"], produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
fun sayHello(@RequestParam(value = "name") name:String): Flux<Example> {
return Flux.interval(Duration.ofSeconds(1))
.map { Example(number = generateNumber()) }
.share()
}
fun generateNumber(): Int{
return ThreadLocalRandom.current().nextInt(100)
}
}
It just returns an object with a number every second
Now on the client side is where I want to use Ktor to get the data but I am unsure what to do. Reading the docs it looks like Scoped streaming is what I need but I am not sure how to get it to work with my controller
Here is the client code I have so far.
suspend fun getData(): Flow<Example> {
return flow {
val client = HttpClient()
client.get<HttpStatement>("http://192.168.7.24:8080/api/v1/values?name=hello").execute{
val example = it.receive<Example>()
emit(example)
}
}
}
When I try to make the call on the Android
client I get this error
NoTransformationFoundException: No transformation found: class io.ktor.utils.io.ByteBufferChannel (Kotlin reflection is not available)
So it looks like I cant just serialize the stream into my object so how do I serialize ByteReadChannel
to an object?
This is my first time trying out spring and ktor
Solution
To be able to serialize the data into an object you need to do t manually by reading the data into a byte array
client.get<HttpStatement>("http://192.168.7.24:8080/api/v1/values?name=hello").execute{
val channel = it.receive<ByteReadChannel>()
val byteArray = ByteArray(it.content.availableForRead)
channel.readAvailable(byteArray,0,byteArray.size)
val example:Example = Json.parse<Example>(stringFromUtf8Bytes(byteArray))
}
Answered By - tyczj