Affects:
- org.springframework.boot: 3.2.5
- org.springframework: 6.1.6
- kotlin: 1.9
After calling the suspend func
, we are post-processing the response (ex logging,...) through @AfterReturning
.
Until spring boot version 3.1.12, we were able to receive and process returning
value as desired.
However, when we upgraded the version to 3.2.x (and even 3.3.x), an issue occurred where MonoOnErrorResume was returned as a returning
value.
@AfterReturning("execution(* x.x.x.suspendFun(..))", returning = "response")
fun controllerSuccessLogging(joinPoint: JoinPoint, response: Any) {
logger.info("$response")
}
When looking at the log flow, it seems that starting from 3.2.x, the @AfterReturning part is executed before the target function ends.
boot 3.1.12
[2024-06-20 14:34:46,181] [INFO] [http-nio-8080-exec-1] [RequestLoggingAspect] API [/v1/resource/test] PARAMS [GetTestRequest(abc=123)]
[2024-06-20 14:34:46,184] [INFO] [http-nio-8080-exec-1] [MySQLExceptionHandleAspect] [SQL] info(statement=query.selResource.selectInfo parameter={abc=23} )
[2024-06-20 14:34:46,288] [INFO] [http-nio-8080-exec-1] [RequestLoggingAspect] GetTestResponse(result=ok) <-- works as intended
boot 3.2.5
[2024-06-20 14:31:52,967] [INFO] [http-nio-8080-exec-1] [RequestLoggingAspect] API [/v1/resource/test] PARAMS [GetTestRequest(abc=123)]
[2024-06-20 14:31:52,968] [INFO] [http-nio-8080-exec-1] [RequestLoggingAspect] MonoOnErrorResume <-- issue
[2024-06-20 14:31:52,991] [INFO] [http-nio-8080-exec-1] [MySQLExceptionHandleAspect] [SQL] info(statement=query.selResource.selectInfo parameter={abc=23} )
Are there any changes to usage, or are there any parts where support has ended?
Comment From: sdeleuze
That's related to #22462 which turns suspending functions to Mono
following the logic already implemented in the rest of the Coroutines support in Spring Framework.
I believe your former use case was working only when there was no invocation of suspending function in the body of your function, otherwise you would see COROUTINE_SUSPENDED
printed (for example when invoking delay(...)
.
You should be able to log the return value with aspects defined like:
@Around("execution(* DemoController+.*(..))")
fun afterReturningAdvice(joinPoint: ProceedingJoinPoint): Any? {
return (joinPoint.proceed(joinPoint.args) as Mono<Any>).doOnNext { println(it) }
}
So if I am not mistaken, the behaviour you see is expected.