completed exception handlers

This commit is contained in:
2026-06-12 16:44:18 +03:00
parent 67403a8414
commit 6fcd2bdd85
6 changed files with 268 additions and 0 deletions
@@ -0,0 +1,200 @@
package com.andwati.orders.exception;
import com.andwati.orders.dto.response.ErrorResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolationException;
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 org.springframework.web.method.annotation.HandlerMethodValidationException;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleMethodArgumentNotValid(
MethodArgumentNotValidException exception,
HttpServletRequest request
) {
List<Map<String, String>> details = exception.getBindingResult()
.getFieldErrors()
.stream()
.map(this::fieldErrorToMap)
.toList();
return build(
HttpStatus.BAD_REQUEST,
"VALIDATION_ERROR",
"Request validation failed",
details,
request
);
}
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<ErrorResponse> handleConstraintViolation(
ConstraintViolationException exception,
HttpServletRequest request
) {
List<Map<String, String>> details = exception.getConstraintViolations()
.stream()
.map(violation -> Map.of(
"field", violation.getPropertyPath().toString(),
"message", violation.getMessage()
))
.toList();
return build(
HttpStatus.BAD_REQUEST,
"VALIDATION_ERROR",
"Request validation failed",
details,
request
);
}
@ExceptionHandler(HandlerMethodValidationException.class)
public ResponseEntity<ErrorResponse> handleHandlerMethodValidation(
HandlerMethodValidationException exception,
HttpServletRequest request
) {
return build(
HttpStatus.BAD_REQUEST,
"VALIDATION_ERROR",
"Request validation failed",
exception.getMessage(),
request
);
}
@ExceptionHandler(ProductNotFoundException.class)
public ResponseEntity<ErrorResponse> handleProductNotFound(
ProductNotFoundException exception,
HttpServletRequest request
) {
return build(
HttpStatus.NOT_FOUND,
"PRODUCT_NOT_FOUND",
exception.getMessage(),
null,
request
);
}
@ExceptionHandler(OrderNotFoundException.class)
public ResponseEntity<ErrorResponse> handleOrderNotFound(
OrderNotFoundException exception,
HttpServletRequest request
) {
return build(
HttpStatus.NOT_FOUND,
"ORDER_NOT_FOUND",
exception.getMessage(),
null,
request
);
}
@ExceptionHandler(InventoryNotFoundException.class)
public ResponseEntity<ErrorResponse> handleInventoryNotFound(
InventoryNotFoundException exception,
HttpServletRequest request
) {
return build(
HttpStatus.NOT_FOUND,
"INVENTORY_NOT_FOUND",
exception.getMessage(),
null,
request
);
}
@ExceptionHandler(InsufficientStockException.class)
public ResponseEntity<ErrorResponse> handleInsufficientStock(
InsufficientStockException exception,
HttpServletRequest request
) {
return build(
HttpStatus.CONFLICT,
"INSUFFICIENT_STOCK",
exception.getMessage(),
exception.getDetails(),
request
);
}
@ExceptionHandler(OrderNotCancellableException.class)
public ResponseEntity<ErrorResponse> handleOrderNotCancellable(
OrderNotCancellableException exception,
HttpServletRequest request
) {
return build(
HttpStatus.CONFLICT,
"ORDER_NOT_CANCELLABLE",
exception.getMessage(),
null,
request
);
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ErrorResponse> handleIllegalArgument(
IllegalArgumentException exception,
HttpServletRequest request
) {
return build(
HttpStatus.BAD_REQUEST,
"VALIDATION_ERROR",
exception.getMessage(),
null,
request
);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleUnexpected(
Exception exception,
HttpServletRequest request
) {
return build(
HttpStatus.INTERNAL_SERVER_ERROR,
"INTERNAL_ERROR",
"An unexpected error occurred",
null,
request
);
}
private Map<String, String> fieldErrorToMap(FieldError fieldError) {
Map<String, String> map = new HashMap<>();
map.put("field", fieldError.getField());
map.put("message", fieldError.getDefaultMessage());
return map;
}
private ResponseEntity<ErrorResponse> build(
HttpStatus status,
String error,
String message,
Object details,
HttpServletRequest request
) {
ErrorResponse response = new ErrorResponse(
error,
message,
details,
Instant.now(),
request.getRequestURI()
);
return ResponseEntity.status(status).body(response);
}
}
@@ -0,0 +1,28 @@
package com.andwati.orders.exception;
import java.util.Map;
import java.util.UUID;
public class InsufficientStockException extends RuntimeException {
private final Map<String, Object> details;
public InsufficientStockException(
UUID productId,
String productName,
int requestedQuantity,
int availableQuantity
) {
super("Insufficient stock for " + productName);
this.details = Map.of(
"productId", productId,
"productName", productName,
"requestedQuantity", requestedQuantity,
"availableQuantity", availableQuantity
);
}
public Map<String, Object> getDetails() {
return details;
}
}
@@ -0,0 +1,10 @@
package com.andwati.orders.exception;
import java.util.UUID;
public class InventoryNotFoundException extends RuntimeException {
public InventoryNotFoundException(UUID productId) {
super("Inventory record for product " + productId + " does not exist");
}
}
@@ -0,0 +1,10 @@
package com.andwati.orders.exception;
import java.util.UUID;
public class OrderNotCancellableException extends RuntimeException {
public OrderNotCancellableException(UUID orderId) {
super("Order " + orderId + " cannot be cancelled because it is not in PLACED status");
}
}
@@ -0,0 +1,10 @@
package com.andwati.orders.exception;
import java.util.UUID;
public class OrderNotFoundException extends RuntimeException {
public OrderNotFoundException(UUID orderId) {
super("Order " + orderId + " does not exist");
}
}
@@ -0,0 +1,10 @@
package com.andwati.orders.exception;
import java.util.UUID;
public class ProductNotFoundException extends RuntimeException {
public ProductNotFoundException(UUID productId) {
super("Product " + productId + " does not exist");
}
}