Skip to content
Snippets Groups Projects
Commit 06656507 authored by Henrik's avatar Henrik
Browse files

feat: add exception classes and handler class

parent 9baf35da
Branches feat/model-classes
No related tags found
1 merge request!4feat: add exception classes and handler class
Pipeline #273408 failed
package no.ntnu.idi.stud.savingsapp.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* Represents an exception response containing status code and message.
*/
@Data
@AllArgsConstructor
public class ExceptionResponse {
private int status;
private String message;
/**
* Creates a ResponseEntity containing the exception response.
*
* @param status The HTTP status code.
* @param message The message describing the exception.
* @return A ResponseEntity containing the exception response.
*/
protected static ResponseEntity<ExceptionResponse> toResponseEntity(HttpStatus status, String message) {
ExceptionResponse response = new ExceptionResponse(status.value(), message);
return ResponseEntity.status(status).body(response);
}
}
package no.ntnu.idi.stud.savingsapp.exception;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import no.ntnu.idi.stud.savingsapp.exception.auth.InvalidCredentialsException;
import no.ntnu.idi.stud.savingsapp.exception.user.PermissionDeniedException;
import no.ntnu.idi.stud.savingsapp.exception.user.UserAlreadyExistsException;
import no.ntnu.idi.stud.savingsapp.exception.user.UserNotFoundException;
import no.ntnu.idi.stud.savingsapp.exception.user.UsernameTakenException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
/**
* Global exception handler that handles various exceptions thrown by the application.
* Customizes the response for different types of exceptions.
*/
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
/**
* Handles validation errors for method arguments.
*
* @param e The MethodArgumentNotValidException containing validation errors.
* @param headers The headers for the response.
* @param status The HTTP status code.
* @param request The current web request.
* @return A ResponseEntity containing the error response.
*/
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException e, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
String error = e.getMessage();
FieldError fieldError = e.getFieldError();
if (fieldError != null) {
error = fieldError.getDefaultMessage();
}
ExceptionResponse response = new ExceptionResponse(HttpStatus.BAD_REQUEST.value(), error);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}
/**
* Handles exceptions by returning an {@link HttpStatus#BAD_REQUEST} response.
*
* @param e The exception.
* @return A ResponseEntity containing the error response.
*/
@ExceptionHandler({ConstraintViolationException.class})
public ResponseEntity<ExceptionResponse> handleBadRequest(Exception e) {
String error = e.getMessage();
if (e instanceof ConstraintViolationException constraintViolationException) {
for (ConstraintViolation<?> violation : constraintViolationException.getConstraintViolations()) {
error = violation.getMessage();
break;
}
}
return ExceptionResponse.toResponseEntity(HttpStatus.BAD_REQUEST, error);
}
/**
* Handles exceptions by returning an {@link HttpStatus#UNAUTHORIZED} response.
*
* @param e The exception.
* @return A ResponseEntity containing the error response.
*/
@ExceptionHandler({InvalidCredentialsException.class, AccessDeniedException.class,
AuthenticationException.class, CredentialsExpiredException.class, PermissionDeniedException.class})
public ResponseEntity<ExceptionResponse> handleUnauthorized(Exception e) {
return ExceptionResponse.toResponseEntity(HttpStatus.UNAUTHORIZED, e.getMessage());
}
/**
* Handles exceptions by returning an {@link HttpStatus#CONFLICT} response.
*
* @param e The exception.
* @return A ResponseEntity containing the error response.
*/
@ExceptionHandler({UserAlreadyExistsException.class, UsernameTakenException.class})
public ResponseEntity<ExceptionResponse> handleConflict(Exception e) {
return ExceptionResponse.toResponseEntity(HttpStatus.CONFLICT, e.getMessage());
}
/**
* Handles exceptions by returning an {@link HttpStatus#NOT_FOUND} response.
*
* @param e The exception.
* @return A ResponseEntity containing the error response.
*/
@ExceptionHandler({UserNotFoundException.class})
public ResponseEntity<ExceptionResponse> handleNotFound(Exception e) {
return ExceptionResponse.toResponseEntity(HttpStatus.NOT_FOUND, e.getMessage());
}
/**
* Handles remaining exceptions by returning an {@link HttpStatus#INTERNAL_SERVER_ERROR} response.
*
* @param e The exception.
* @return A ResponseEntity containing the error response.
*/
@ExceptionHandler(Exception.class)
public ResponseEntity<ExceptionResponse> handleRemainingExceptions(Exception e) {
return ExceptionResponse.toResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
}
/**
* Customizes the default exception handler.
*
* @param e The exception.
* @param body The body of the response.
* @param headers The headers for the response.
* @param statusCode The HTTP status code.
* @param request The current web request.
* @return A ResponseEntity containing the error response.
*/
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception e, Object body, HttpHeaders headers, HttpStatusCode statusCode, WebRequest request) {
ExceptionResponse response = new ExceptionResponse(statusCode.value(), e.getMessage());
return super.handleExceptionInternal(e, response, headers, statusCode, request);
}
}
package no.ntnu.idi.stud.savingsapp.exception.auth;
/**
* Exception thrown when authentication fails due to invalid credentials.
*/
public class InvalidCredentialsException extends RuntimeException {
/**
* Constructs an InvalidCredentialsException with the default message.
*/
public InvalidCredentialsException() {
super("Invalid credentials");
}
}
package no.ntnu.idi.stud.savingsapp.exception.user;
/**
* Exception thrown when a user attempts an action they don't have permission to.
*/
public final class PermissionDeniedException extends RuntimeException {
/**
* Constructs a PermissionDeniedException with the default message.
*/
public PermissionDeniedException() {
super("Permission denied");
}
}
package no.ntnu.idi.stud.savingsapp.exception.user;
/**
* Exception thrown when attempting to create a user that already exists in the system.
*/
public final class UserAlreadyExistsException extends RuntimeException {
/**
* Constructs a UserAlreadyExistsException with the default message.
*/
public UserAlreadyExistsException() {
super("User already exists");
}
}
package no.ntnu.idi.stud.savingsapp.exception.user;
/**
* Exception thrown when attempting to retrieve a user that does not exist in the system.
*/
public final class UserNotFoundException extends RuntimeException {
/**
* Constructs a UserNotFoundException with the default message.
*/
public UserNotFoundException() {
super("User not found");
}
/**
* Constructs a UserNotFoundException with the default message.
*/
public UserNotFoundException(String string) {
super(string);
}
}
package no.ntnu.idi.stud.savingsapp.exception.user;
/**
* Exception thrown when attempting to create a user that already exists in the system.
*/
public final class UsernameTakenException extends RuntimeException {
/**
* Constructs a UserAlreadyExistsException with the default message.
*/
public UsernameTakenException() {
super("Username is taken");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment