diff --git a/src/main/java/org/springframework/samples/petclinic/rest/advice/ExceptionControllerAdvice.java b/src/main/java/org/springframework/samples/petclinic/rest/advice/ExceptionControllerAdvice.java
index a49745d00..ef6f974c9 100644
--- a/src/main/java/org/springframework/samples/petclinic/rest/advice/ExceptionControllerAdvice.java
+++ b/src/main/java/org/springframework/samples/petclinic/rest/advice/ExceptionControllerAdvice.java
@@ -16,8 +16,7 @@
package org.springframework.samples.petclinic.rest.advice;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -33,23 +32,41 @@
import static org.springframework.http.HttpStatus.BAD_REQUEST;
/**
+ * Global Exception handler for REST controllers.
+ *
+ * This class handles exceptions thrown by REST controllers and returns
+ * appropriate HTTP responses to the client.
+ *
* @author Vitaliy Fedoriv
+ * @author Alexander Dudkin
*/
-
@ControllerAdvice
public class ExceptionControllerAdvice {
- @ExceptionHandler(Exception.class)
- public ResponseEntity exception(Exception e) {
- ObjectMapper mapper = new ObjectMapper();
- ErrorInfo errorInfo = new ErrorInfo(e);
- String respJSONstring = "{}";
- try {
- respJSONstring = mapper.writeValueAsString(errorInfo);
- } catch (JsonProcessingException e1) {
- e1.printStackTrace();
+ /**
+ * Record for storing error information.
+ *
+ * This record encapsulates the class name and message of the exception.
+ *
+ * @param className The name of the exception class
+ * @param exMessage The message of the exception
+ */
+ private record ErrorInfo(String className, String exMessage) {
+ public ErrorInfo(Exception ex) {
+ this(ex.getClass().getName(), ex.getLocalizedMessage());
}
- return ResponseEntity.badRequest().body(respJSONstring);
+ }
+
+ /**
+ * Handles all general exceptions by returning a 500 Internal Server Error status with error details.
+ *
+ * @param e The exception to be handled
+ * @return A {@link ResponseEntity} containing the error information and a 500 Internal Server Error status
+ */
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity handleGeneralException(Exception e) {
+ ErrorInfo info = new ErrorInfo(e);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(info);
}
/**
@@ -73,13 +90,38 @@ public ResponseEntity handleMethodArgumentNotValidException(MethodArgument
return new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST);
}
- private class ErrorInfo {
- public final String className;
- public final String exMessage;
+ /**
+ * Handles {@link DataIntegrityViolationException} which typically indicates database constraint violations.
+ * This method returns a 404 Not Found status if an entity does not exist.
+ *
+ * @param ex The {@link DataIntegrityViolationException} to be handled
+ * @return A {@link ResponseEntity} containing the error information and a 404 Not Found status
+ */
+ @ExceptionHandler(DataIntegrityViolationException.class)
+ @ResponseStatus(code = HttpStatus.NOT_FOUND)
+ @ResponseBody
+ public ResponseEntity handleDataIntegrityViolationException(DataIntegrityViolationException ex) {
+ ErrorInfo errorInfo = new ErrorInfo(ex);
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorInfo);
+ }
- public ErrorInfo(Exception ex) {
- this.className = ex.getClass().getName();
- this.exMessage = ex.getLocalizedMessage();
+ /**
+ * Handles exception thrown by Bean Validation on controller methods parameters
+ *
+ * @param ex The thrown exception
+ * @return an empty response entity
+ */
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ @ResponseStatus(BAD_REQUEST)
+ @ResponseBody
+ public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
+ BindingErrorsResponse errors = new BindingErrorsResponse();
+ BindingResult bindingResult = ex.getBindingResult();
+ if (bindingResult.hasErrors()) {
+ errors.addAllErrors(bindingResult);
+ return ResponseEntity.badRequest().body(new ErrorInfo("MethodArgumentNotValidException", "Validation failed"));
}
+ return ResponseEntity.badRequest().build();
}
+
}
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/controller/PetRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/controller/PetRestControllerTests.java
index 06f1b5a99..fe78a0c4b 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/controller/PetRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/controller/PetRestControllerTests.java
@@ -241,7 +241,8 @@ void testAddPetError() throws Exception {
String newPetAsJSON = mapper.writeValueAsString(newPet);
given(this.clinicService.findPetById(999)).willReturn(null);
this.mockMvc.perform(post("/api/pets")
- .content(new String()).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
+ // empty content to force badRequest response
+ .content("{}").accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isBadRequest());
}
}
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/controller/UserRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/controller/UserRestControllerTests.java
index 9c5f504d6..532ce94ee 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/controller/UserRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/controller/UserRestControllerTests.java
@@ -64,7 +64,7 @@ void testCreateUserSuccess() throws Exception {
void testCreateUserError() throws Exception {
User user = new User();
user.setUsername("username");
- user.setPassword("password");
+ user.setPassword(""); // empty password to force badRequest Response
user.setEnabled(true);
ObjectMapper mapper = new ObjectMapper();
String newVetAsJSON = mapper.writeValueAsString(userMapper.toUserDto(user));