Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to customize Hibernate @Size error message to indicate length of entered field

I would like to customize the error message for text fields to include the actual number of characters that were entered. I've been able to get this to work but am not satisfied with my solution, so I'm wondering what others have done to accomplish this.

  • Spring 4.1.2
  • Hibernate 4.3.10
  • Hibernate Validator 5.1.3

Field Annotation (limited to 10 for testing purposes - actual size is 150)

@Column(name = "NAME", nullable = false)
@Size(max=10)
private String name;

message.properties

Size.person.name=Maximum is {1} characters

JSP code

    <spring:bind path="person.name">
        <c:set var="nameError">${status.errorMessage}</c:set>
        <c:set var="nameDisplayValue">${status.displayValue}</c:set>
        <c:set var="nameCode">${status.errorCode}</c:set>
    </spring:bind>
    <c:if test="${fn:contains(nameCode,'Size')}">
        <c:set var="nameLen">${fn:length(nameDisplayValue)}</c:set>
        <c:if test="${nameLen gt 0}">
            <c:set var="nameError">${nameError += " (you entered " += nameLen += ")"}</c:set>  
        </c:if>
    </c:if>

    <div class="form-group col-sm-9 <c:if test="${not empty nameError}">has-error</c:if>">
        <label class="control-label" id="nameLabel" for="inputName">Name:<c:if test="${not empty nameError}">&nbsp;&nbsp;${nameError}</c:if></label>
        <form:input type="text" size="10" class="form-control" id="inputName" placeholder="Name" path="name" autocomplete="off"/>                                                           
    </div>

Output

enter image description here

This is ok for one field, but the form I'm working on has more than 10 fields that have size validation. Also, the size="10" setting for form:input does not appear to actually do anything, i.e., you can still enter more than 10 characters.

I know one option is to write a custom validator but that seems like overkill for what I want to do. Another would be to catch the error before the form is posted, but I'm trying to keep all of the validation server-side. Any suggestions would be greatly appreciated.

like image 316
LWK69 Avatar asked Aug 02 '15 15:08

LWK69


1 Answers

There is a good documentation about interpolating validation messages in the Hibernate documentation: Chapter 4. Interpolating constraint error messages.

If you create a file ValidationMessages.properties in the root of your classpath then you can change all validation messages there:

javax.validation.constraints.Size.message=Please enter at least {min} and at most {max} characters.

The parameters in {...} are just the attribute names of the annotation. That works for nearly every constraint. If you want to reference the validated value, you can use {validatedValue}. You can as well use Formatter to format the value:

... ${formatter.format('...', validatedValue)} ...

Unfortunately there is no format string for length.

So if you really want to have such a message for all @Size, then you will have to implement your own javax.validation.MessageInterpolator (see Custom message interpolation in the link above).

Additional remark: There is a side effect when changing the default validation message: @Size is available for collections as well. And in that case at least my message is not appropriate. I usually create a second validation message for this:

javax.validation.constraints.Size.Collection.message=Please select at least {min} and at most {max} elements.

And use that one in the constraint:

public final class ValidationMessages {
  public static final String COLLECTION_SIZE = 
      "javax.validation.constraints.Size.Collection.message";
}

public class MyClass {
    @Size(min = 1, max = 10, message = ValidationMessages.COLLECTION_SIZE)
    private Collection<String> elements;
}

With a matching rule in my code style tool I ensure that I don't forget to define the message for @Size annotations on collections.

like image 104
Tobias Liefke Avatar answered Nov 02 '22 23:11

Tobias Liefke