From 3e1b6030bfd8392b3983e823aa772a95beb3010c Mon Sep 17 00:00:00 2001 From: "DESKTOP-E7L6HLO\\Noyan" Date: Tue, 16 Jul 2024 20:03:05 +0300 Subject: [PATCH] Task 27 : Define GlobalExceptionHandler in userservice --- .../handler/GlobalExceptionHandler.java | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 userservice/src/main/java/com/springbootmicroservices/userservice/exception/handler/GlobalExceptionHandler.java diff --git a/userservice/src/main/java/com/springbootmicroservices/userservice/exception/handler/GlobalExceptionHandler.java b/userservice/src/main/java/com/springbootmicroservices/userservice/exception/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..e296af1 --- /dev/null +++ b/userservice/src/main/java/com/springbootmicroservices/userservice/exception/handler/GlobalExceptionHandler.java @@ -0,0 +1,194 @@ +package com.springbootmicroservices.userservice.exception.handler; + +import com.springbootmicroservices.userservice.exception.*; +import com.springbootmicroservices.userservice.model.common.CustomError; +import jakarta.validation.ConstraintViolationException; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.ArrayList; +import java.util.List; + +/** + * Global exception handler named {@link GlobalExceptionHandler} for handling various types of exceptions in the application. + */ +@RestControllerAdvice +public class GlobalExceptionHandler { + + /** + * Handles MethodArgumentNotValidException thrown when validation on an argument annotated with @Valid fails. + * + * @param ex The MethodArgumentNotValidException instance. + * @return ResponseEntity with CustomError containing details of validation errors. + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + protected ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex) { + + List subErrors = new ArrayList<>(); + + ex.getBindingResult().getAllErrors().forEach( + error -> { + String fieldName = ((FieldError) error).getField(); + String message = error.getDefaultMessage(); + subErrors.add( + CustomError.CustomSubError.builder() + .field(fieldName) + .message(message) + .build() + ); + } + ); + + CustomError customError = CustomError.builder() + .httpStatus(HttpStatus.BAD_REQUEST) + .header(CustomError.Header.VALIDATION_ERROR.getName()) + .message("Validation failed") + .subErrors(subErrors) + .build(); + + return new ResponseEntity<>(customError, HttpStatus.BAD_REQUEST); + + } + + /** + * Handles ConstraintViolationException thrown when a bean validation constraint is violated. + * + * @param constraintViolationException The ConstraintViolationException instance. + * @return ResponseEntity with CustomError containing details of constraint violations. + */ + @ExceptionHandler(ConstraintViolationException.class) + protected ResponseEntity handlePathVariableErrors(final ConstraintViolationException constraintViolationException) { + + List subErrors = new ArrayList<>(); + constraintViolationException.getConstraintViolations() + .forEach(constraintViolation -> + subErrors.add( + CustomError.CustomSubError.builder() + .message(constraintViolation.getMessage()) + .field(StringUtils.substringAfterLast(constraintViolation.getPropertyPath().toString(), ".")) + .value(constraintViolation.getInvalidValue() != null ? constraintViolation.getInvalidValue().toString() : null) + .type(constraintViolation.getInvalidValue().getClass().getSimpleName()) + .build() + ) + ); + + CustomError customError = CustomError.builder() + .httpStatus(HttpStatus.BAD_REQUEST) + .header(CustomError.Header.VALIDATION_ERROR.getName()) + .message("Constraint violation") + .subErrors(subErrors) + .build(); + + return new ResponseEntity<>(customError, HttpStatus.BAD_REQUEST); + + } + + /** + * Handles RuntimeException thrown for general runtime exceptions. + * + * @param runtimeException The RuntimeException instance. + * @return ResponseEntity with CustomError containing details of the runtime exception. + */ + @ExceptionHandler(RuntimeException.class) + protected ResponseEntity handleRuntimeException(final RuntimeException runtimeException) { + CustomError customError = CustomError.builder() + .httpStatus(HttpStatus.NOT_FOUND) + .header(CustomError.Header.API_ERROR.getName()) + .message(runtimeException.getMessage()) + .build(); + + return new ResponseEntity<>(customError, HttpStatus.NOT_FOUND); + } + + /** + * Handles PasswordNotValidException thrown when a password is not valid. + * + * @param ex The PasswordNotValidException instance. + * @return ResponseEntity with CustomError containing details of the exception. + */ + @ExceptionHandler(PasswordNotValidException.class) + protected ResponseEntity handlePasswordNotValidException(final PasswordNotValidException ex) { + CustomError customError = CustomError.builder() + .httpStatus(HttpStatus.BAD_REQUEST) + .header(CustomError.Header.API_ERROR.getName()) + .message(ex.getMessage()) + .build(); + + return new ResponseEntity<>(customError, HttpStatus.BAD_REQUEST); + } + + /** + * Handles TokenAlreadyInvalidatedException thrown when a token is already invalidated. + * + * @param ex The TokenAlreadyInvalidatedException instance. + * @return ResponseEntity with CustomError containing details of the exception. + */ + @ExceptionHandler(TokenAlreadyInvalidatedException.class) + protected ResponseEntity handleTokenAlreadyInvalidatedException(final TokenAlreadyInvalidatedException ex) { + CustomError customError = CustomError.builder() + .httpStatus(HttpStatus.BAD_REQUEST) + .header(CustomError.Header.API_ERROR.getName()) + .message(ex.getMessage()) + .build(); + + return new ResponseEntity<>(customError, HttpStatus.BAD_REQUEST); + } + + /** + * Handles UserAlreadyExistException thrown when a user already exists. + * + * @param ex The UserAlreadyExistException instance. + * @return ResponseEntity with CustomError containing details of the exception. + */ + @ExceptionHandler(UserAlreadyExistException.class) + protected ResponseEntity handleUserAlreadyExistException(final UserAlreadyExistException ex) { + CustomError customError = CustomError.builder() + .httpStatus(HttpStatus.CONFLICT) + .header(CustomError.Header.API_ERROR.getName()) + .message(ex.getMessage()) + .build(); + + return new ResponseEntity<>(customError, HttpStatus.CONFLICT); + } + + /** + * Handles UserNotFoundException thrown when a user is not found. + * + * @param ex The UserNotFoundException instance. + * @return ResponseEntity with CustomError containing details of the exception. + */ + @ExceptionHandler(UserNotFoundException.class) + protected ResponseEntity handleUserNotFoundException(final UserNotFoundException ex) { + CustomError customError = CustomError.builder() + .httpStatus(HttpStatus.NOT_FOUND) + .header(CustomError.Header.API_ERROR.getName()) + .message(ex.getMessage()) + .build(); + + return new ResponseEntity<>(customError, HttpStatus.NOT_FOUND); + } + + /** + * Handles UserStatusNotValidException thrown when a user status is not valid. + * + * @param ex The UserStatusNotValidException instance. + * @return ResponseEntity with CustomError containing details of the exception. + */ + @ExceptionHandler(UserStatusNotValidException.class) + protected ResponseEntity handleUserStatusNotValidException(final UserStatusNotValidException ex) { + CustomError customError = CustomError.builder() + .httpStatus(HttpStatus.BAD_REQUEST) + .header(CustomError.Header.API_ERROR.getName()) + .message(ex.getMessage()) + .build(); + + return new ResponseEntity<>(customError, HttpStatus.BAD_REQUEST); + } + + +}