profileShare

rasmusjy / tasteprint

Read-only snapshot

No repository description.

main default branch 169 files Expires Sep 13, 2026, 9:06 AM
ApiExceptionHandler.java 3,048 bytes
1 package com.tasteprint.shared;
2
3 import java.net.URI;
4 import java.util.LinkedHashMap;
5 import java.util.Map;
6
7 import jakarta.validation.ConstraintViolationException;
8
9 import org.springframework.dao.DataIntegrityViolationException;
10 import org.springframework.http.HttpStatus;
11 import org.springframework.http.ProblemDetail;
12 import org.springframework.security.core.AuthenticationException;
13 import org.springframework.web.bind.MethodArgumentNotValidException;
14 import org.springframework.web.bind.annotation.ExceptionHandler;
15 import org.springframework.web.bind.annotation.RestControllerAdvice;
16
17 @RestControllerAdvice
18 class ApiExceptionHandler {
19
20 @ExceptionHandler(NotFoundException.class)
21 ProblemDetail handleNotFound(NotFoundException exception) {
22 return problem(HttpStatus.NOT_FOUND, "Resource not found", exception.getMessage());
23 }
24
25 @ExceptionHandler(ConflictException.class)
26 ProblemDetail handleConflict(ConflictException exception) {
27 return problem(HttpStatus.CONFLICT, "Conflict", exception.getMessage());
28 }
29
30 @ExceptionHandler(ForbiddenException.class)
31 ProblemDetail handleForbidden(ForbiddenException exception) {
32 return problem(HttpStatus.FORBIDDEN, "Forbidden", exception.getMessage());
33 }
34
35 @ExceptionHandler(AuthenticationException.class)
36 ProblemDetail handleAuthentication(AuthenticationException exception) {
37 return problem(HttpStatus.UNAUTHORIZED, "Authentication failed", exception.getMessage());
38 }
39
40 @ExceptionHandler(MethodArgumentNotValidException.class)
41 ProblemDetail handleValidation(MethodArgumentNotValidException exception) {
42 ProblemDetail detail = problem(HttpStatus.BAD_REQUEST, "Validation failed", "Check the highlighted fields.");
43 Map<String, String> errors = new LinkedHashMap<>();
44 exception.getBindingResult().getFieldErrors().forEach(error ->
45 errors.putIfAbsent(error.getField(), error.getDefaultMessage()));
46 detail.setProperty("errors", errors);
47 return detail;
48 }
49
50 @ExceptionHandler(ConstraintViolationException.class)
51 ProblemDetail handleConstraintViolation(ConstraintViolationException exception) {
52 return problem(HttpStatus.BAD_REQUEST, "Validation failed", exception.getMessage());
53 }
54
55 @ExceptionHandler(DataIntegrityViolationException.class)
56 ProblemDetail handleIntegrityViolation() {
57 return problem(HttpStatus.CONFLICT, "Conflict", "That change conflicts with existing data.");
58 }
59
60 @ExceptionHandler(IllegalArgumentException.class)
61 ProblemDetail handleIllegalArgument(IllegalArgumentException exception) {
62 return problem(HttpStatus.BAD_REQUEST, "Invalid request", exception.getMessage());
63 }
64
65 private ProblemDetail problem(HttpStatus status, String title, String detail) {
66 ProblemDetail problem = ProblemDetail.forStatusAndDetail(status, detail);
67 problem.setTitle(title);
68 problem.setType(URI.create("https://tasteprint.app/problems/" + status.value()));
69 return problem;
70 }
71 }
72