I am new to spring-boot I’m trying to add validation to my DTO class like below.
import javax.validation.constraints.NotBlank; @Getter @Setter public class EmployeeDto { private Long id; @NotBlank(message = "Employee first name is required") private String firstName; private String lastName; @NotBlank(message = "EmployeeNUM is required") private String employeeNum; }
Below is my REST endpoint to save employee.
import javax.validation.Valid; @PostMapping("/employee") public ResponseEntity<?> addEmployee(@Valid @RequestBody EmployeeDto employeeDto) throws ClassNotFoundException { return ResponseEntity.ok(employeeService.saveEmployee(deptId,employeeDto)); }
I create a Validation class like below to validate the DTO fields.
@ControllerAdvice @RestController public class Validation { @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) public Map<String, String> handleValidationExceptions( MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getAllErrors().forEach((error) -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return errors; } }
expected output is
{ “firstName”:”Employee first name is required”, “employeeNum”:”EmployeeNUM is required” }
But I’m getting only the 400 bad request when hit the endpoint through postman. What is the issue with my code? How to fix and get the expected output as mentioned above?
Advertisement
Answer
Try to extend the ResponseEntityExceptionHandler
class like this:
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import javax.validation.ConstraintViolationException; import java.time.Instant; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * * Handle all exceptions and java bean validation errors for all endpoints income data that use the @Valid annotation * * @author Ehab Qadah */ @ControllerAdvice public class GeneralExceptionHandler extends ResponseEntityExceptionHandler { @Override protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException exception, HttpHeaders headers, HttpStatus status, WebRequest request) { List<String> validationErrors = exception.getBindingResult() .getFieldErrors() .stream() .map(error -> error.getField() + ": " + error.getDefaultMessage()) .collect(Collectors.toList()); return getExceptionResponseEntity(HttpStatus.BAD_REQUEST, request, validationErrors); } @ExceptionHandler({ConstraintViolationException.class}) public ResponseEntity<Object> handleConstraintViolation( ConstraintViolationException exception, WebRequest request) { List<String> validationErrors = exception.getConstraintViolations().stream(). map(violation -> violation.getPropertyPath() + ": " + violation.getMessage()) .collect(Collectors.toList()); return getExceptionResponseEntity(HttpStatus.BAD_REQUEST, request, validationErrors); } private ResponseEntity<Object> getExceptionResponseEntity(final HttpStatus status, WebRequest request, List<String> errors) { final Map<String, Object> body = new LinkedHashMap<>(); final String errorsMessage = CollectionUtils.isNotEmpty(errors) ? errors.stream().filter(StringUtils::isNotEmpty).collect(Collectors.joining(",")):status.getReasonPhrase(); final String path = request.getDescription(false); body.put("TIMESTAMP", Instant.now()); body.put("STATUS", status.value()); body.put("ERRORS", errorsMessage); body.put("PATH", path); body.put("MESSAGE", status.getReasonPhrase()); return new ResponseEntity<>(body, status); } }