How can the status code for a response provided by a @ExceptionHandler be set when the @Controller returns a reactive type (Mono)?
It seems that it is not possible via returning a ResponseEntity or annotating the @ExceptionHandler method with @ResponseStatus.
A fairly minimal test showing the issue (note that the response body and content type are correctly verified while the status code is OK when it should be INTERNAL_SERVER_ERROR):
class SpringWebMvcWithReactiveResponseTypeExceptionHandlerCheckTest {
@RestController
@RequestMapping("/error-check", produces = ["text/plain;charset=UTF-8"])
class ExceptionHandlerCheckController {
@GetMapping("errorMono")
fun getErrorMono(): Mono<String> {
return Mono.error(Exception())
}
}
@ControllerAdvice
class ErrorHandler : ResponseEntityExceptionHandler() {
@ExceptionHandler(Exception::class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
fun handleException(ex: Exception): ResponseEntity<*> = ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.contentType(MediaType.APPLICATION_PROBLEM_JSON)
.body(mapOf("key" to "value"))
}
val mockMvc = MockMvcBuilders
.standaloneSetup(ExceptionHandlerCheckController())
.setControllerAdvice(ErrorHandler())
.build()
@Test
fun `getErrorMono returns HTTP Status OK instead of the one set by an ExceptionHandler`() {
mockMvc.get("/error-check/errorMono")
// .andExpect { status { isInternalServerError() } }
.andExpect { status { isOk() } }
.asyncDispatch()
.andExpect {
content {
contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE)
json("""
{
"key": "value"
}
""",strict = true
)
}
}
}
}
(build.gradle.kts excerpt showing relevant dependencies):
plugins: {
id("org.springframework.boot") version "2.4.5"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-webflux")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}