Ошибки проверки Spring не отображаются

У меня следующая ситуация. У меня есть валидатор для проверки моего командного объекта и установки ошибок в объекте Errors для отображения в моей форме. Валидатор вызывается, как и ожидалось, и работает нормально, но ошибки, которые я установил для объектов Errors, не отображаются, когда меня отправляют обратно в мою форму из-за ошибок проверки.

Валидатор:

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");   
    }   
}

Команда:

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 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>

Контроллер:

    @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   
}

Может ли быть так, что пути, которые я указываю в валидаторе и теге, неверны? Валидатор проверяет командный объект, содержащий список объектов, поэтому я даю индекс в списке в командном объекте при регистрации сообщения об ошибке (например: "fields["+index+"]".value). Или объект Errors, содержащий ошибки, недоступен для моего представления?

Любая помощь приветствуется и ценится, она может дать мне подсказку или указать мне правильное направление.


person Art Vandelay    schedule 17.03.2010    source источник
comment
попробуйте добавить ‹form:errors path=* cssClass=error/› в код формы, чтобы убедиться, что ваш валидатор работает нормально.   -  person Yuri.Bulkin    schedule 19.03.2010


Ответы (2)


Я нашел, в чем твоя проблема. свойство fields в объекте myCommand всегда равно null. Вам нужно создать конструктор для класса MyCommand, в котором вам нужно использовать LazyList из Apache Commons или AutoPopulatingList из Spring для создания автоматически растущего списка Field

В примере (с использованием AutoPopulatingList):

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

    //getters and setters
    //...
    //Constructor
    public MyCommand() {
        fields = new AutoPopulatingList<Field>(Field.class);
    } 
}
person Yuri.Bulkin    schedule 22.03.2010
comment
Наконец-то я заработал проверку формы. Как оказалось, Spring добавлял объект BindingResult в модель, но под другим именем (имя класса, начинающееся с нижнего регистра), чем имя команды, которое я использую в своем теге формы. Изменение имени команды, чтобы оно отражало имя, которое Spring использует для добавления BindingResult в модель, заставило мою проверку формы работать должным образом. В любом случае, спасибо за ваши усилия и помощь. пс. Зачем нужен LazyList? Потому что без него моя форма работает нормально. - person Art Vandelay; 22.03.2010
comment
Я согласен с ответом Юрия Булкина. Я столкнулся с той же проблемой до 2 месяцев, и я нашел это решение. Вам необходимо выполнить LazyList инициализацию, прежде чем использовать список полей в jsp с помощью тегов form spring. - person Japan Trivedi; 05.05.2012

Строка err.rejectValue("fields[" + index + "].value", "errors.missing"); не будет делать того, чего вы пытаетесь достичь. Первым аргументом должно быть имя свойства вашего компонента Command в ваших полях case.

Чтобы дать пользователю сообщение, вам нужно будет использовать параметризуемое сообщение в вашем файле свойств, например. myform.field.error = you have an error in field {0}

Итак, используйте этот метод объекта Errors:

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

Где вы передаете index в errorArgs

person Hans Westerbeek    schedule 18.03.2010
comment
Спасибо за ответ, зеркало303. Чего я точно не понимаю, так это того, что вы имеете в виду под передачей индекса в errorArgs. Я исходил из того, что errorArgs являются аргументами для параметризованного сообщения в моем файле свойств и не имеют ничего общего с индексированным свойством команды (например, List). Но, наверное, я не понимаю, о чем вы говорите. Итак, вы имеете в виду, что errorArgs должен иметь значения fields[+index+].value? - person Art Vandelay; 19.03.2010
comment
да индекс, как в переменной метода, которую вы используете в коде, который вы разместили - person Hans Westerbeek; 19.03.2010
comment
Но индекс представляет собой int, а не Object[], а fields[index].value — это String, поэтому я не понимаю, как с помощью индекса я могу предоставить Object[] в качестве параметра. - person Art Vandelay; 19.03.2010
comment
Вы можете создать массив объектов java.lang.Integer (который будет иметь только один элемент) и создать объект Integer из примитивного индекса int, который у вас есть в вашем коде. Теперь, пожалуйста, проголосуйте за мой ответ :) - person Hans Westerbeek; 19.03.2010