@NotNull : validation custom message not displaying

Viewed 13169

I am using spring data JPA for creating application. In that I am trying to implement server side validation using annotation. I added @NotNull annotation on filed with custom message. I also added @valid with @RequestBody

But problem is that when I am passing nAccountId as null I am not getting custom message i.e. Account id can not be null I am getting "message": "Validation failed for object='accountMaintenanceSave'. Error count: 1",.

Can any one please tell me why I am not getting custom message?

Controller code

@PutMapping("/updateAccountData")
public ResponseEntity<Object> saveData(@Valid @RequestBody AccountMaintenanceSave saveObj){
    return accService.saveData(saveObj);
} 

AccountMaintenanceSave class

import javax.validation.constraints.NotNull;

public class AccountMaintenanceSave {   

    @NotNull(message="Account id can not be null")
    public Integer nAccountId;
    @NotNull
    public String sClientAcctId;
    @NotNull
    public String sAcctDesc;
    @NotNull
    public String sLocation;
    @NotNull
    public Integer nDeptId; 
    @NotNull
    public Integer nAccountCPCMappingid;
    @NotNull
    public Integer nInvestigatorId;

    //Getter and Setter
}

RestExceptionHandler class

@ControllerAdvice
public class RestExceptionHandler { 

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleAllExceptionMethod(Exception ex, WebRequest requset) {

        ExceptionMessage exceptionMessageObj = new ExceptionMessage();

        exceptionMessageObj.setMessage(ex.getLocalizedMessage());
        exceptionMessageObj.setError(ex.getClass().getCanonicalName());
        exceptionMessageObj.setPath(((ServletWebRequest) requset).getRequest().getServletPath());

        // return exceptionMessageObj;
        return new ResponseEntity<>(exceptionMessageObj, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

I don't know what exactly happen previously and not getting proper message. Now using same code getting result like this with proper message

{
  "message": "Validation failed for argument at index 0 in method: public org.springframework.http.ResponseEntity<java.lang.Object> com.spacestudy.controller.AccountController.saveData(com.spacestudy.model.AccountMaintenanceSave), with 1 error(s): [Field error in object 'accountMaintenanceSave' on field 'nAccountId': rejected value [null]; codes [NotNull.accountMaintenanceSave.nAccountId,NotNull.nAccountId,NotNull.java.lang.Integer,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [accountMaintenanceSave.nAccountId,nAccountId]; arguments []; default message [nAccountId]]; default message [Account id can not be null]] ",
  "error": "org.springframework.web.bind.MethodArgumentNotValidException",
  "path": "/spacestudy/rockefeller/admin/account/updateAccountData"
}

In message filed can I print only [Account id can not be null]?

3 Answers

It's not so good to make your only ExceptionHandler to catch Exception.class make it ConstraintViolationException.class

Try this.

@ControllerAdvice
public class RestExceptionHandler { 

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleAllExceptionMethod(Exception ex, WebRequest requset) {

    ExceptionMessage exceptionMessageObj = new ExceptionMessage();

    // Handle All Field Validation Errors
    if(ex instanceof MethodArgumentNotValidException) {
        StringBuilder sb = new StringBuilder(); 
        List<FieldError> fieldErrors = ((MethodArgumentNotValidException) ex).getBindingResult().getFieldErrors();
        for(FieldError fieldError: fieldErrors){
            sb.append(fieldError.getDefaultMessage());
            sb.append(";");
        }
        exceptionMessageObj.setMessage(sb.toString());
    }else{
        exceptionMessageObj.setMessage(ex.getLocalizedMessage());
    }

    exceptionMessageObj.setError(ex.getClass().getCanonicalName());
    exceptionMessageObj.setPath(((ServletWebRequest) requset).getRequest().getServletPath());

    // return exceptionMessageObj;
    return new ResponseEntity<>(exceptionMessageObj, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
  }
}

Another approach to the solution:

I would suggest remove the exception handler for this validation fields in the POJO and rather let Spring handle the error response by adding the below property into application.properties. By adding this the message configured in the @notnull or any validation annotation can be captured and showed in the response by default and no explicit handling of this validation case is required.

server.error.include-message=always
server.error.include-binding-errors=always
Related