micronaut-projects / micronaut-core

Micronaut Application Framework
http://micronaut.io
Apache License 2.0
6.05k stars 1.06k forks source link

Wrong handling of flow #10796

Open frederic-kneier opened 6 months ago

frederic-kneier commented 6 months ago

Expected Behavior

If a controller returns a coroutine flow from a suspend function, only the first value of the flow is returned as an object instead of all items as a json array. In case of Strings it even returns invalid json.

Actual Behaviour

The controller should return all items, just like a non suspending function

Steps To Reproduce

import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.toList

@Controller
class HelloController {

    @Get("/hello-list-wrapped")
    suspend fun getList() = value().toList()

    @Get("/hello-blocking-wrapped")
    fun getBlocking() = value()

    @Get("/hello-suspend-wrapped")
    suspend fun getSuspend() = value()

    @Get("/hello-list-plain")
    suspend fun getListPlain() = value().toList().map { it.content }

    @Get("/hello-blocking-plain")
    fun getBlockingPlain() = value().map { it.content }

    @Get("/hello-suspend-plain")
    suspend fun getSuspendPlain() = value().map { it.content }

    private fun value() = flow {
        emit(Value("hello"))
        emit(Value("world"))
    }

    data class Value(val content: String)
}

/hello-list-wrapped: [{"content":"hello"},{"content":"world"}] (OK) /hello-blocking-wrapped: [{"content":"hello"},{"content":"world"}] (OK) /hello-suspend-wrapped: {"content":"hello"} (Only first entry)

/hello-list-plain: ["hello","world"] (OK) /hello-blocking-plain: [hello,world] (Invalid Json) /hello-suspend-plain: hello (Invalid json with only first entry)

Environment Information

No response

Example Application

No response

Version

4.3.4

sdelamo commented 5 months ago

@frederic-kneier could you create a sample app reproducing the errors.

frederic-kneier commented 3 months ago

I think this controller is all you need to reproduce the problem.