Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring validation errors not displayed

I have the following situation. I have a validator to validate my command object and set the errors on a Errors object to be displayed in my form. The validator is invoked as expected and works okay, but the errors i set on the Errors objects are not displayed, when i am sent back to my form because of the validation errors.

Validator:

public void validate(Object obj, Errors err) {   
    MyCommand myCommand = (MyCommand) obj;   
    int index = 0;   
    for (Field field : myCommand.getFields()) {   
        if (field.isChecked()) {   
            if ((field.getValue() == null) || (field.getValue().equals(""))) {   
                err.rejectValue("fields[" + index + "].value", "errors.missing");   
            }   
        }   
        index++;   
    }   
    if (myCommand.getLimit() < 0) {   
        err.rejectValue("limit", "errors.invalid");   
    }   
}

Command:

public class MyCommand {   
    private List<Field> fields;   
    private int limit;   

    //getters and setters   
}   

public class Field {   
    private boolean checked;   
    private String name;   
    private String value;   

    //getters and setters   
}

Form:

    <form:form id="myForm" method="POST" action="${url}" commandName="myCommand">   
    <c:forEach items="${myCommand.fields}" var="field" varStatus="status">   
        <form:checkbox path="fields[${status.index}].checked" value="${field.checked}" />   
        <c:out value="${field.name}" />   
        <form:input path="fields[${status.index}].value" />   
        <form:errors path="fields[${status.index}].value" cssClass="error" /></td>   
        <form:hidden path="fields[${status.index}].name" />   
    </c:forEach>   
    <fmt:message key="label.limit" />    
    <form:input path="limit" />   
    <form:errors path="limit" cssClass="error" />   
</form:form>

Controller:

    @RequestMapping(value = REQ_MAPPING, method = RequestMethod.POST)   
    public String onSubmit(Model model, MyCommand myCommand, BindingResult result) {   
    // validate   
    myCommandValidator.validate(myCommand, result);   
    if (result.hasErrors()) {   
        model.addAttribute("myCommand", myCommand);   
        return VIEW;   
    }   

    // form is okay, do stuff and redirect   
}

Could it be that the paths i give in the validator and tag are not correct? The validator validates a command object containing a list of objects, so that's why i give a index on the list in the command object when registering an error message (for example: "fields["+index+"]".value). Or is it that the Errors object containing the errors is not available to my view?

Any help is welcome and appreciated, it might give me a hint or point me in right direction.

like image 738
Art Vandelay Avatar asked Mar 17 '10 17:03

Art Vandelay


2 Answers

I found what is your problem. property fields in object myCommand always null. You need to create constructor for class MyCommand in which you need to use LazyList from Apache Commons or AutoPopulatingList from Spring to create auto growing list of Field

In example (using AutoPopulatingList):

public class MyCommand {   
    private List<Field> fields;   
    private int limit;   

    //getters and setters
    //...
    //Constructor
    public MyCommand() {
        fields = new AutoPopulatingList<Field>(Field.class);
    } 
}
like image 190
Yuri.Bulkin Avatar answered Oct 25 '22 20:10

Yuri.Bulkin


The line err.rejectValue("fields[" + index + "].value", "errors.missing"); will not do what you are trying to achieve. The first argument must be a property name of your Command bean, in your case fields.

To give the user a message you will have to use a parameterizable message in your properties file, eg. myform.field.error = you have an error in field {0}

So, use this method of the Errors object:

void rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage) 

Where you pass index into errorArgs

like image 26
Hans Westerbeek Avatar answered Oct 25 '22 20:10

Hans Westerbeek