Affects: 6.1.1+ (Spring Boot 3.2.x)
Reproducer: reproducer.zip
Problem
Calling any suspend function in a service that is proxied by SpringCGLIB might throw an exception due to missing classes in the classpath (java.lang.ClassNotFoundException: org.reactivestreams.Publisher). For some reason this only occurs when another function in the specified class is getting changed too. E.g. if there is an @Transactional method, only then this bug occurs.
Expected Behavior
When calling a suspend function, the call should not be re-written on a non-reactive stack regardeless of other functions in the , similar to how it worked in 6.0.x.
Actual Behavior
When another function in the service forces some new behavior to be introduced by the SpringCGLIB proxy, then the suspend function should be left untouched in a non-reactive application.
Reproducer
Crashes with SB 3.2.X, works with SB 3.1.X:
import jakarta.transaction.Transactional
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.stereotype.Service
@SpringBootApplication
class DemoCoroutinesCrashApplication
@Service
class DemoService {
@Transactional
fun somethingTransaction() {
}
suspend fun mySuspendFunction(): Int {
return 123
}
}
@SpringBootTest
class DemoCoroutinesCrashApplicationTests {
@Autowired
private lateinit var demoService: DemoService
@Test
fun `should not crash`(): Unit = runBlocking {
demoService.mySuspendFunction()
}
}