0

This is my exception handler

@ControllerAdvice(basePackageClasses = [SignUpController::class])
class ControllerAdvice: ResponseEntityExceptionHandler() {

    @ExceptionHandler(Exception::class)
    @ResponseBody
    fun handleControllerException(request: HttpServletRequest, ex: Throwable): ResponseEntity<*> {
        val status = HttpStatus.CONFLICT
        return ResponseEntity<Any>(ApiError(status.value(), ex.message), status)
    }
}

and my custom class

data class ApiError(val status: Int, val message: String?)

The handler work but error is throw like follow

{
    "timestamp": "2019-01-29T19:17:22.541+0000",
    "status": 401,
    "error": "Unauthorized",
    "message": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
    "path": "/sign-up"
}

But I'm expected for something like follow

{
    "apierror": {
        "status": ...,
        "message": ..."
    }
}

I'm based for this tutorials

https://www.toptal.com/java/spring-boot-rest-api-error-handling https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling https://medium.com/@jovannypcg/understanding-springs-controlleradvice-cd96a364033f

What I'm doing wrong? I'm missing any config?

Abner Escócio
  • 2,133
  • 2
  • 11
  • 29
  • Possible duplicate of [ExceptionHandler doesn't work with Throwable](https://stackoverflow.com/questions/22548508/exceptionhandler-doesnt-work-with-throwable) – ordonezalex Jan 30 '19 at 10:36

2 Answers2

-1

You need to annotate your ApiError class with the following:

@Data 
@JsonTypeInfo(
            include = JsonTypeInfo.As.WRAPPER_OBJECT,
            use = JsonTypeInfo.Id.CUSTOM, 
            property = "error",
            visible = true
) 
@JsonTypeIdResolver(LowerCaseClassNameResolver.class)
Bon
  • 160
  • 1
  • 9
-1

My workaround was, but is not the correct answer

on application.yaml

server:
  error:
    include-exception: true

on my controller I'm check if email and username exists and throw a custome message to exception

@RestController
@RequestMapping("/register")
class RegisterController: BaseController() {

    @ResponseStatus(HttpStatus.CREATED)
    @PostMapping("/save")
    fun register(@RequestBody user: ApplicationUser) {
        if (userRepository.existsByEmail(user.email)) {
            throw DataIntegrityViolationException("Email already exists")
        }
        if (userRepository.existsByUsername(user.username)) {
            throw DataIntegrityViolationException("Username already exists")
        }
        user.password = bCryptPasswordEncoder.encode(user.password)
        userRepository.save(user)
    }
}

and the return worked fine

{
    "timestamp": "2019-01-31T17:08:40.832+0000",
    "status": 500,
    "error": "Internal Server Error",
    "exception": "org.springframework.dao.DataIntegrityViolationException",
    "message": "Email already exists", //here is
    "path": "/register/save"
}
Abner Escócio
  • 2,133
  • 2
  • 11
  • 29