I want to handle the Exception of my api by adding a WebExceptionHandler. I can change the status code, but I am stuck when i want to change the body of the response : ex adding
ServerResponse has a method writeTo which can be used to write your body to ServerExchange (Spring framework does it this way). Only problem is that you have to provide Contextas a second parameter, so I have just copied HandlerStrategiesResponseContext from framework implementation.
Make sure that you are using at least Spring Boot 2.0.0 M2, before this version WebExceptionHandler was not registered while using RouterFunctions.
import org.springframework.http.HttpStatus
import org.springframework.http.HttpStatus.*
import org.springframework.http.codec.HttpMessageWriter
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.server.HandlerStrategies
import org.springframework.web.reactive.function.server.ServerResponse
import org.springframework.web.reactive.result.view.ViewResolver
import org.springframework.web.server.ServerWebExchange
import org.springframework.web.server.WebExceptionHandler
@Component
class GlobalErrorHandler() : WebExceptionHandler {
override fun handle(exchange: ServerWebExchange, ex: Throwable): Mono =
handle(ex)
.flatMap {
it.writeTo(exchange, HandlerStrategiesResponseContext(HandlerStrategies.withDefaults()))
}
.flatMap {
Mono.empty()
}
fun handle(throwable: Throwable): Mono {
return when (throwable) {
is EntityNotFoundException -> {
createResponse(NOT_FOUND, "NOT_FOUND", "Entity not found, details: ${throwable.message}")
}
else -> {
createResponse(INTERNAL_SERVER_ERROR, "GENERIC_ERROR", "Unhandled exception")
}
}
}
fun createResponse(httpStatus: HttpStatus, code: String, message: String): Mono =
ServerResponse.status(httpStatus).syncBody(ApiError(code, message))
}
private class HandlerStrategiesResponseContext(val strategies: HandlerStrategies) : ServerResponse.Context {
override fun messageWriters(): List> {
return this.strategies.messageWriters()
}
override fun viewResolvers(): List {
return this.strategies.viewResolvers()
}
}