3131import org .springframework .web .bind .annotation .ResponseBody ;
3232
3333import java .net .URI ;
34+ import java .util .List ;
35+ import java .util .Map ;
3436import java .time .Instant ;
37+ import java .util .Objects ;
3538
3639/**
3740 * Global Exception handler for REST controllers.
@@ -53,16 +56,17 @@ public class ExceptionControllerAdvice {
5356 * Private method for constructing the {@link ProblemDetail} object passing the name and details of the exception
5457 * class.
5558 *
56- * @param ex Object referring to the thrown exception.
59+ * @param e Object referring to the thrown exception.
5760 * @param status HTTP response status.
5861 * @param url URL request.
5962 */
60- private ProblemDetail detailBuild (Exception ex , HttpStatus status , StringBuffer url , String detail ) {
63+ private ProblemDetail detailBuild (Exception e , HttpStatus status , StringBuffer url , String detail ) {
6164 ProblemDetail problemDetail = ProblemDetail .forStatus (status );
6265 problemDetail .setType (URI .create (url .toString ()));
63- problemDetail .setTitle (ex .getClass ().getSimpleName ());
66+ problemDetail .setTitle (e .getClass ().getSimpleName ());
6467 problemDetail .setDetail (detail );
6568 problemDetail .setProperty ("timestamp" , Instant .now ());
69+ problemDetail .setProperty ("schemaValidationErrors" , List .of ());
6670 return problemDetail ;
6771 }
6872
@@ -76,7 +80,7 @@ private ProblemDetail detailBuild(Exception ex, HttpStatus status, StringBuffer
7680 @ ExceptionHandler (Exception .class )
7781 @ ResponseBody
7882 public ResponseEntity <ProblemDetail > handleGeneralException (Exception e , HttpServletRequest request ) {
79- logger .error ("Unexpected error occurred" , e );
83+ logger .error ("Unexpected error at {} {}" , request . getMethod (), request . getRequestURI () , e );
8084 HttpStatus status = HttpStatus .INTERNAL_SERVER_ERROR ;
8185 ProblemDetail detail = this .detailBuild (e , status , request .getRequestURL (), ERROR_UNEXPECTED );
8286 return ResponseEntity .status (status ).body (detail );
@@ -93,7 +97,11 @@ public ResponseEntity<ProblemDetail> handleGeneralException(Exception e, HttpSer
9397 @ ExceptionHandler (DataIntegrityViolationException .class )
9498 @ ResponseBody
9599 public ResponseEntity <ProblemDetail > handleDataIntegrityViolationException (DataIntegrityViolationException e , HttpServletRequest request ) {
96- logger .error ("Data integrity violation: {}" , e .getMessage ());
100+ logger .warn ("Data integrity violation at {} {}: {}" ,
101+ request .getMethod (),
102+ request .getRequestURI (),
103+ e .getMessage ());
104+ logger .debug ("Data integrity violation stacktrace" , e );
97105 HttpStatus status = HttpStatus .NOT_FOUND ;
98106 ProblemDetail detail = this .detailBuild (e , status , request .getRequestURL (), ERROR_DATA_INTEGRITY );
99107 return ResponseEntity .status (status ).body (detail );
@@ -112,13 +120,27 @@ public ResponseEntity<ProblemDetail> handleMethodArgumentNotValidException(Metho
112120 HttpStatus status = HttpStatus .BAD_REQUEST ;
113121 BindingErrorsResponse errors = new BindingErrorsResponse ();
114122 BindingResult bindingResult = e .getBindingResult ();
123+ ProblemDetail detail = this .detailBuild (e , status , request .getRequestURL (), ERROR_INVALID_REQUEST );
115124 if (bindingResult .hasErrors ()) {
116125 errors .addAllErrors (bindingResult );
117- logger .error ("Invalid request: {}" , bindingResult .getAllErrors ());
118- ProblemDetail detail = this .detailBuild (e , status , request .getRequestURL (), ERROR_INVALID_REQUEST );
126+ List <Map <String , String >> schemaValidationErrors = bindingResult .getFieldErrors ().stream ()
127+ .map (fieldError -> Map .of (
128+ "field" , fieldError .getField (),
129+ "rejectedValue" , Objects .toString (fieldError .getRejectedValue (), "null" ),
130+ "defaultMessage" , Objects .toString (fieldError .getDefaultMessage (), "Validation failed" ),
131+ "message" , "Field '%s' %s (rejected value: %s)" .formatted (
132+ fieldError .getField (),
133+ Objects .toString (fieldError .getDefaultMessage (), "Validation failed" ),
134+ Objects .toString (fieldError .getRejectedValue (), "null" ))))
135+ .toList ();
136+ logger .debug ("Validation error at {} {}: {}" ,
137+ request .getMethod (),
138+ request .getRequestURI (),
139+ bindingResult .getFieldErrors ());
140+ detail .setProperty ("schemaValidationErrors" , schemaValidationErrors );
119141 return ResponseEntity .status (status ).body (detail );
120142 }
121- return ResponseEntity .status (status ).build ( );
143+ return ResponseEntity .status (status ).body ( detail );
122144 }
123145
124146}
0 commit comments