Skip to content

Commit b8532e6

Browse files
committed
Merge branch 'exceptions' into dev
2 parents 0fb44cd + 0c4ebd4 commit b8532e6

7 files changed

+247
-0
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package br.com.catalog.exceptions;
2+
3+
import br.com.catalog.exceptions.abstract_handler.AbstractExceptionHandler;
4+
import br.com.catalog.exceptions.business_exceptions.*;
5+
import com.auth0.jwt.exceptions.JWTCreationException;
6+
import com.auth0.jwt.exceptions.JWTVerificationException;
7+
import jakarta.persistence.EntityNotFoundException;
8+
import lombok.extern.slf4j.Slf4j;
9+
import org.springframework.http.HttpStatus;
10+
import org.springframework.http.ResponseEntity;
11+
import org.springframework.security.access.AccessDeniedException;
12+
import org.springframework.security.authentication.BadCredentialsException;
13+
import org.springframework.web.bind.MethodArgumentNotValidException;
14+
import org.springframework.web.bind.annotation.ExceptionHandler;
15+
import org.springframework.web.bind.annotation.ResponseBody;
16+
import org.springframework.web.bind.annotation.ResponseStatus;
17+
import org.springframework.web.bind.annotation.RestControllerAdvice;
18+
19+
@RestControllerAdvice
20+
@Slf4j
21+
public class GlobalExceptionHandler extends AbstractExceptionHandler {
22+
public GlobalExceptionHandler() {
23+
super(log);
24+
}
25+
26+
@ExceptionHandler(InvalidTokenException.class)
27+
@ResponseStatus(HttpStatus.UNAUTHORIZED)
28+
@ResponseBody
29+
public ResponseEntity<ApiError> handleInvalidTokenException(final InvalidTokenException ex) {
30+
log.error("Invalid or expired token", ex);
31+
var apiError = new ApiError(
32+
HttpStatus.UNAUTHORIZED.value(),
33+
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
34+
"Token invalido ou expirado");
35+
return new ResponseEntity<>(apiError, HttpStatus.UNAUTHORIZED);
36+
}
37+
38+
@ExceptionHandler(AccessDeniedException.class)
39+
@ResponseStatus(HttpStatus.FORBIDDEN)
40+
@ResponseBody
41+
public ResponseEntity<ApiError> handleAccessDeniedException(final AccessDeniedException ex) {
42+
log.error("Access denied", ex);
43+
var apiError = new ApiError(
44+
HttpStatus.FORBIDDEN.value(),
45+
HttpStatus.FORBIDDEN.getReasonPhrase(),
46+
"Você não tem permissão para acessar este recurso");
47+
return new ResponseEntity<>(apiError, HttpStatus.FORBIDDEN);
48+
}
49+
50+
@ExceptionHandler(EntityNotFoundException.class)
51+
@ResponseStatus(HttpStatus.NOT_FOUND)
52+
@ResponseBody
53+
public ResponseEntity<ApiError> handleEntityNotFoundException(final EntityNotFoundException ex) {
54+
log.error("Brand not found thrown", ex);
55+
var apiError = new ApiError(
56+
HttpStatus.NOT_FOUND.value(),
57+
HttpStatus.NOT_FOUND.getReasonPhrase(),
58+
"Entidade não encontrada");
59+
return new ResponseEntity<>(apiError, HttpStatus.NOT_FOUND);
60+
}
61+
62+
@ExceptionHandler(IllegalPageSizeException.class)
63+
@ResponseStatus(HttpStatus.BAD_REQUEST)
64+
@ResponseBody
65+
public ResponseEntity<ApiError> handleIllegalPageSizeException(final IllegalPageSizeException ex) {
66+
log.error("Illegal page size thrown", ex);
67+
var apiError = new ApiError(
68+
HttpStatus.BAD_REQUEST.value(),
69+
HttpStatus.BAD_REQUEST.getReasonPhrase(),
70+
"Tamanho da página deve ser entre 10 e 20");
71+
return new ResponseEntity<>(apiError, HttpStatus.BAD_REQUEST);
72+
}
73+
74+
@ExceptionHandler(BrandAlreadyExistsException.class)
75+
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
76+
@ResponseBody
77+
public ResponseEntity<ApiError> handleBrandAlreadyExistsException(final BrandAlreadyExistsException ex) {
78+
log.error("Brand already exists", ex);
79+
var apiError = new ApiError(
80+
HttpStatus.UNPROCESSABLE_ENTITY.value(),
81+
HttpStatus.UNPROCESSABLE_ENTITY.getReasonPhrase(),
82+
"Marca já existe");
83+
return new ResponseEntity<>(apiError, HttpStatus.UNPROCESSABLE_ENTITY);
84+
}
85+
86+
@ExceptionHandler(MethodArgumentNotValidException.class)
87+
@ResponseStatus(HttpStatus.BAD_REQUEST)
88+
@ResponseBody
89+
public ResponseEntity<ApiError> handleMethodArgumentNotValidException(final MethodArgumentNotValidException ex) {
90+
log.error("Method argument not valid", ex);
91+
var apiError = new ApiError(
92+
HttpStatus.BAD_REQUEST.value(),
93+
HttpStatus.BAD_REQUEST.getReasonPhrase(),
94+
"Exceção de validação de argumento");
95+
return new ResponseEntity<>(apiError, HttpStatus.BAD_REQUEST);
96+
}
97+
98+
@ExceptionHandler(IllegalArgumentException.class)
99+
@ResponseStatus(HttpStatus.BAD_REQUEST)
100+
@ResponseBody
101+
public ResponseEntity<ApiError> handleIllegalArgumentException(final IllegalArgumentException ex) {
102+
log.error("Illegal argument", ex);
103+
var apiError = new ApiError(
104+
HttpStatus.BAD_REQUEST.value(),
105+
HttpStatus.BAD_REQUEST.getReasonPhrase(),
106+
"Argumento ilegal");
107+
return new ResponseEntity<>(apiError, HttpStatus.BAD_REQUEST);
108+
}
109+
110+
@ExceptionHandler(ProductAlreadyExistsException.class)
111+
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
112+
@ResponseBody
113+
public ResponseEntity<ApiError> handleProductAlreadyExistsException(final ProductAlreadyExistsException ex) {
114+
log.error("Product already exists", ex);
115+
var apiError = new ApiError(
116+
HttpStatus.UNPROCESSABLE_ENTITY.value(),
117+
HttpStatus.UNPROCESSABLE_ENTITY.getReasonPhrase(),
118+
"Produto já existe");
119+
return new ResponseEntity<>(apiError, HttpStatus.UNPROCESSABLE_ENTITY);
120+
}
121+
122+
@ExceptionHandler(UserAlreadyExistsException.class)
123+
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
124+
@ResponseBody
125+
public ResponseEntity<ApiError> handleUserAlreadyExistsException(final UserAlreadyExistsException ex) {
126+
log.error("User already exists", ex);
127+
var apiError = new ApiError(
128+
HttpStatus.UNPROCESSABLE_ENTITY.value(),
129+
HttpStatus.UNPROCESSABLE_ENTITY.getReasonPhrase(),
130+
"Usuário já existe");
131+
return new ResponseEntity<>(apiError, HttpStatus.UNPROCESSABLE_ENTITY);
132+
}
133+
134+
@ExceptionHandler(BadCredentialsException.class)
135+
@ResponseStatus(HttpStatus.UNAUTHORIZED)
136+
@ResponseBody
137+
public ResponseEntity<ApiError> handleBadCredentialsException(final BadCredentialsException ex) {
138+
log.error("Bad Credentials", ex);
139+
var apiError = new ApiError(
140+
HttpStatus.UNAUTHORIZED.value(),
141+
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
142+
"Credenciais incorretas");
143+
return new ResponseEntity<>(apiError, HttpStatus.UNAUTHORIZED);
144+
}
145+
146+
@ExceptionHandler(JWTCreationException.class)
147+
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
148+
@ResponseBody
149+
public ResponseEntity<ApiError> handleJWTCreationException(final JWTCreationException ex) {
150+
log.error("JWT Creation Exception", ex);
151+
var apiError = new ApiError(
152+
HttpStatus.INTERNAL_SERVER_ERROR.value(),
153+
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
154+
"Erro ao gerar token");
155+
return new ResponseEntity<>(apiError, HttpStatus.INTERNAL_SERVER_ERROR);
156+
}
157+
158+
@ExceptionHandler(JWTVerificationException.class)
159+
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
160+
@ResponseBody
161+
public ResponseEntity<ApiError> handleJWTVerificationException(final JWTVerificationException ex) {
162+
log.error("JWT Verification Exception", ex);
163+
var apiError = new ApiError(
164+
HttpStatus.INTERNAL_SERVER_ERROR.value(),
165+
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
166+
"Erro ao verificar token");
167+
return new ResponseEntity<>(apiError, HttpStatus.INTERNAL_SERVER_ERROR);
168+
}
169+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package br.com.catalog.exceptions.abstract_handler;
2+
3+
import com.fasterxml.jackson.annotation.JsonFormat;
4+
import org.slf4j.Logger;
5+
import org.springframework.http.HttpStatus;
6+
import org.springframework.http.ResponseEntity;
7+
import org.springframework.web.bind.annotation.ExceptionHandler;
8+
import org.springframework.web.bind.annotation.ResponseBody;
9+
import org.springframework.web.bind.annotation.ResponseStatus;
10+
11+
import java.time.LocalDateTime;
12+
13+
public abstract class AbstractExceptionHandler {
14+
private final Logger log;
15+
16+
protected AbstractExceptionHandler(Logger log) {
17+
this.log = log;
18+
}
19+
20+
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
21+
@ResponseBody
22+
@ExceptionHandler(Exception.class)
23+
public ResponseEntity<ApiError> handlerGeneric(final Exception ex) {
24+
log.error("UNEXPECTED ERROR", ex);
25+
var apiError = new ApiError(
26+
HttpStatus.INTERNAL_SERVER_ERROR.value(),
27+
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
28+
"An unexpected internal server error occured");
29+
return new ResponseEntity<>(apiError, HttpStatus.INTERNAL_SERVER_ERROR);
30+
}
31+
32+
public record ApiError(
33+
@JsonFormat(pattern = "dd-MM-yyyy HH:mm:ss")
34+
LocalDateTime timestamp,
35+
int code,
36+
String status,
37+
String description
38+
) {
39+
public ApiError(int code, String status, String description) {
40+
this(LocalDateTime.now(), code, status, description);
41+
}
42+
}
43+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package br.com.catalog.exceptions.business_exceptions;
2+
3+
public class BrandAlreadyExistsException extends RuntimeException {
4+
public BrandAlreadyExistsException(String message) {
5+
super(message);
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package br.com.catalog.exceptions.business_exceptions;
2+
3+
public class IllegalPageSizeException extends RuntimeException {
4+
public IllegalPageSizeException(String message) {
5+
super(message);
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package br.com.catalog.exceptions.business_exceptions;
2+
3+
public class InvalidTokenException extends RuntimeException {
4+
public InvalidTokenException(String message, Throwable cause) {
5+
super(message, cause);
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package br.com.catalog.exceptions.business_exceptions;
2+
3+
public class ProductAlreadyExistsException extends RuntimeException {
4+
public ProductAlreadyExistsException(String message) {
5+
super(message);
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package br.com.catalog.exceptions.business_exceptions;
2+
3+
public class UserAlreadyExistsException extends RuntimeException {
4+
public UserAlreadyExistsException(String message) {
5+
super(message);
6+
}
7+
}

0 commit comments

Comments
 (0)