BartoszMiller
BartoszMiller

Reputation: 1227

Include field name inside error message using Hibernate Validator

I'm using Hibernate Validator 4.2.0.Final and I'm looking for the simplest way to include class field name in my error message.

What I found is the following thread Using a custom ResourceBundle with Hibernate Validator. According to this I should create my custom annotation for each constraint annotation adding one property to each one.

Is there a cleaner way to achieve this?

The following code:

@Size(max = 5)
private String myField;

produces default error: size must be between 0 and 5.

I would like it to be: myField size must be between 0 and 5.

Upvotes: 30

Views: 26277

Answers (9)

Shahbaaz Khan
Shahbaaz Khan

Reputation: 177

A better way so that internationalization is supported.

//in ValidationMessages.properties

app.FieldName=MyField

app.validation.size.msg=size must be between {min} and {max} but provided ${validatedValue}

@Size(min=10, max=15, message = "{app.FieldName}"+" "+ "{app.validation.size.msg}") private String myField;

Upvotes: 1

Oleg
Oleg

Reputation: 422

If validating a REST call in a controller and using a controller advice, you can combine field and default message from MethodArgumentNotValidException like this:

@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    public ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException exception, HttpHeaders headers, HttpStatus status, WebRequest request) {
        String errorMessage = exception
                .getBindingResult()
                .getFieldErrors()
                .stream()
                .map(fieldError -> fieldError.getField() + " " + fieldError.getDefaultMessage())
                .collect(Collectors.joining(", "));


        return new ResponseEntity<>(errorMessage, HttpStatus.BAD_REQUEST);
    }

Upvotes: 1

user3640709
user3640709

Reputation: 93

If your messages are in .properties file then there is no interpolation variable for accessing property name but one way you can achieve that is

//in ValidationMessages.properties
app.validation.size.msg=size must be between {min} and {max}

@Size(min=10, max=15, message = "myField {app.validation.size.msg})
private String myField;

OR

//in ValidationMessages.properties
app.validation.size.msg=size must be between {min} and {max} but provided ${validatedValue}

@Size(min=10, max=15, message = "myField {app.validation.size.msg})
private String myField;

Reference: message interpolation

Upvotes: 8

Stephen.lin
Stephen.lin

Reputation: 166

use this method(ex is ConstraintViolationException instance):

Set<ConstraintViolation<?>> set =  ex.getConstraintViolations();
List<ErrorField> errorFields = new ArrayList<>(set.size());
ErrorField field = null;
for (Iterator<ConstraintViolation<?>> iterator = set.iterator();iterator.hasNext(); ) {
    ConstraintViolation<?> next =  iterator.next();
   System.out.println(((PathImpl)next.getPropertyPath())
            .getLeafNode().getName() + "  " +next.getMessage());


}

Upvotes: 0

Rocky Hu
Rocky Hu

Reputation: 1346

I put every field validation message into the properties file, like this:

field.student.name.size.message = Student name size is not valid.

and in the bean, use it like this:

@Size(max = 5, message = "${field.student.name.size.message}")  
private String myField;

I know it isn't a perfect solution, but I also don't find a better way.

Upvotes: 3

brunov
brunov

Reputation: 1003

You can get the name of the field with the getPropertyPath() method from the ConstraintViolation class.

A good default error message can be:

violation.getPropertyPath() + " " + violation.getMessage();

Which will give you "foo may not be null", or "foo.bar may not be null" in the case of nested objects.

Upvotes: 37

BartoszMiller
BartoszMiller

Reputation: 1227

For all those who are looking for a way to access class inside your validator. Putting hibernate annotating on a class level instead of variable level gives you access to a class object (assuming that you have defined a custom validator).

public class myCustomValidator implements ContraintValidator <MyAnnotation, MyAnnotatedClass> {

    public void initialize (...){ ... };

    public boolean isValid (MyAnnotatedClass myAnnotatedClass) {

        // access to elements of your myAnnotatedClass

    }
} 

Upvotes: 0

Jigar Parekh
Jigar Parekh

Reputation: 6273

use oval this has good number of annotations and possible ways to display messages.

Upvotes: 0

Ajinkya
Ajinkya

Reputation: 22710

I am not aware of any generic way but you can define custom error message and include field name in it.

@Size(max = 5, message = "myField size must be between 0 and 5")  
private String myField;

Upvotes: 2

Related Questions