Affects: v5.3.7


I'm using Kotlin Coroutines to build a Spring Webflux application and recently I got an issue working with suspending functions and Project Reactor.

When I return a publisher with an error in a suspend function the transaction is not rolled back.

e.g.

@Transactional
suspend fun save(name: String): Flux<Employee> {
  repository.save(Employee(name = name)).awaitSingle()
  return Flux.error(RuntimeException())
}

But when I change the return type to Flow the transaction is rolled back.

e.g.

@Transactional
suspend fun save(name: String): Flow<Employee> {
  repository.save(Employee(name = name)).awaitSingle()
  return Flux.error<Employee>(RuntimeException()).asFlow()
}

Idk if I'm missing something here so please let me know.

I've created a small project with some test cases to reproduce this issue here.

Comment From: poutsma

The cause for the difference between the way Flows are treated is this line.

@sdeleuze I have a proposed fix for this issue here. Could you please review?

Comment From: sdeleuze

If I understand the proposed changes right, this would add special handling of Mono and other Publisher (including Flux) in addition to Flow for suspending functions.

I think this is a change that generally makes sense, not only fixing this use case on Reactive transaction, but also improving the DevXP for people returning Mono and Flux in suspending functions (not super common, but we had that use case reported in the past).

That said, if I am not mistaken, this would be a breaking change where we would need feedback, so I recommend shipping that as part of the next Spring Framework 6 milestone.