In order to simplify my error handling i wanted an ExceptionHandler, i have used the 4. point on http://www.baeldung.com/exception-handling-for-rest-with-spring .
My exception handler class looks like follows:
@ControllerAdvice
class APIExceptionHandler : ResponseEntityExceptionHandler() {
@ExceptionHandler(value = [(TestException::class)])
fun handleConflict(exception: TestException, request: WebRequest): ResponseEntity<Any> {
println("Handle")
return handleExceptionInternal(exception, "Response Body", HttpHeaders(), HttpStatus.BAD_REQUEST, request)
}
}
TestException
is just a simple Exception
that extends RuntimeException
class TestException : RuntimeException()
Anyhow, in my RestController
i am simply throwing an exception as soon as any call is made:
@GetMapping("/lobby/close")
fun closeLobby(@RequestParam(value = "uuid") uuid: String, @RequestHeader(value = "userSession") userSession: String): ResponseEntity<Any> {
throw TestException()
}
But the exception handler is not invoked.
However, calling this:
@GetMapping("/lobby/error")
fun error(): ResponseEntity<Any> {
throw TestException()
}
it is invoked.
I don't quite understand what the difference is, besides of the first version expecting parameters and a specific header.
UPDATE 24.03.2018
The problem seems to be, that the ExceptionHandler isn't being invoked if the clients request was malformed.
By default a malformed request leads to a pretty detailed error report, but the custom ExceptionHandler seems to disable this functionality.
Spring Boot @ControllerAdvice example. In the following Spring Boot application we use @ControllerAdvice to handle three exceptions: when a city is not found, when there is no data, and when a data for a new city to be saved is not valid. This is the project structure. This is the Gradle build file.
Class DefaultHandlerExceptionResolver. The default implementation of the HandlerExceptionResolver interface, resolving standard Spring MVC exceptions and translating them to corresponding HTTP status codes. This exception resolver is enabled by default in the common Spring DispatcherServlet .
The differences between @RestControllerAdvice and @ControllerAdvice is : @RestControllerAdvice = @ControllerAdvice + @ResponseBody . - we can use in REST web services. @ControllerAdvice - We can use in both MVC and Rest web services, need to provide the ResponseBody if we use this in Rest web services.
I got it working, here is my code.
@ControllerAdvice
class ControllerAdviceRequestError : ResponseEntityExceptionHandler() {
@ExceptionHandler(value = [(UserAlreadyExistsException::class)])
fun handleUserAlreadyExists(ex: UserAlreadyExistsException,request: WebRequest): ResponseEntity<ErrorsDetails> {
val errorDetails = ErrorsDetails(Date(),
"Validation Failed",
ex.message!!
)
return ResponseEntity(errorDetails, HttpStatus.BAD_REQUEST)
}
}
Exception class
class UserAlreadyExistsException(override val message: String?) : Exception(message)
Data class
data class ErrorsDetails(val time: Date, val message: String, val details: String)
MyController:
@PostMapping(value = ["/register"])
fun register(@Valid @RequestBody user: User): User {
if (userService.exists(user.username)) {
throw UserAlreadyExistsException("User with username ${user.username} already exists")
}
return userService.create(user)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With