JSF getValue() v.s. getSubmittedValue()
В последнее время я разрабатываю несколько приложений JSF, и меня беспокоит несогласованность API-интерфейсов веб-компонентов.
Я заметил, что при вызове .getValue() или .getSubmittedValue() в объекте компонента JSF в коде на стороне сервера существует чрезвычайно непредсказуемое поведение. Иногда, когда я вызываю .getValue() в раскрывающемся списке, я заметил, что получаю значение, поскольку это было до того, как я выбрал свое значение (так что значение из последнего обновления страницы), из которого .getSubmittedValue() получает меня правильное значение, как таковое:
UIInput name = new UIInput(); // This is the control I have in a bean.
public void submit(ActionEvent ae)
{
someMethod(name.getValue().toString()); // Retrieves the "old" value
someMethod(name.getSubmittedValue().toString()); // Retrieves the correct value
}
Кроме того, я заметил, что вызов .getSubmittedValue() в поле формы иногда приводит к исключению нулевого указателя, потому что это значение не было создано в объекте компонента, и в этом случае, когда я вызываю .getValue() в этом Я получаю правильное значение, например:
HtmlInputText name = new HtmlInputText(); // This is the control I have in a bean.
public void submit(ActionEvent ae)
{
someMethod(name.getValue().toString()); // Retrieves the correct value
someMethod(name.getSubmittedValue().toString()); // Throws NullPointerException
}
Это просто "причуда" структуры JSF, или я просто неправильно использую API ПОЛНОСТЬЮ? Любое понимание этих двух методов было бы весьма полезно. Приветствия.
Ответы
Ответ 1
Так как это результат # 1 в Google для поиска по getValue или getSubmittedValue, я просто хотел бы добавить, что разница между ними имеет решающее значение при проверке (т.е. при написании настраиваемого валидатора)
Чтобы процитировать документацию API для getSubmittedValue():
Это не пустое значение только между декодированием и проверять фазы, или когда валидация для компонента не удалось. После преобразования и валидация преуспела, (преобразованное) значение сохраняется в локальное свойство "value" этого компонент, а представленное значение reset до нуля.
Источник: http://myfaces.apache.org/core11/myfaces-api/apidocs/javax/faces/component/UIInput.html#getSubmittedValue()
Это означает, что если проверка/преобразование произошла для привязки, к которой вы пытаетесь получить доступ, вы должны вызвать getValue(), иначе вам нужно будет вызвать getSubmittedValue() и обработать его самостоятельно. Порядок, в котором они происходят, кажется, диктуется порядком, который они появляются в пользовательском интерфейсе, но я не думаю, что это гарантировано. Даже если это так, вы не должны рассчитывать на это, так как изменение поля в пользовательском интерфейсе не должно нарушать ваш код.
Вы можете определить, была ли проверка/преобразование выполнена, просто посмотрев на то, что возвращает isLocalValueSet(). Если он возвращает true, то valdation/conversion выполняется, поэтому вы должны вызвать getValue(). В противном случае вам нужно будет вызвать getSubmittedValue(), и это даст вам сырой ввод, введенный пользователем, и вы, скорее всего, захотите проанализировать его на что-то более значимое.
Например, объект календаря будет возвращать объект Date при вызове getValue(), но был вызван объект String при вызове getSubmittedValue(). Это до вашего конвертера для синтаксического анализа строки в Date, чтобы ее можно было проверить.
Было бы здорово, если бы у спецификации JSF был метод, который сделал бы это для нас, но AFAIK это не так. Если определенные даты должны быть указаны до других дат, а некоторые из них необходимы только в определенных обстоятельствах, нужно будет написать несколько валидаторов, чтобы справиться с этим. Таким образом, это может легко стать проблемой. Это похоже на то, что вы не можете делать какие-либо проверки в пустое поле, а это означает, что вы не можете сделать это поле условно необходимым. Если проверка была выполнена во всех полях, даже в пустых, пользовательский валидатор мог быть написан для того, чтобы генерировать исключение, если это необходимо, а это не так. Есть некоторые вещи с JSF, которые просто боль; если/пока они не будут исправлены, нам просто нужно иметь дело с ними.
Чтобы поговорить со спецификой проблемы в исходном посте: разница в том, где вы находитесь в жизненном цикле. Метод submit
выглядит как прослушиватель действий для кнопки, которая ставит его в конце жизненного цикла; действия и прослушиватели действий запускаются в фазе "Invoke Application", которая предшествует отклику рендера, но после проверки. Если вы собираетесь программировать в JSF, вы должны изучить и понять жизненный цикл. Это стоит того времени.
Ответ 2
Чтобы процитировать документацию на EditableValueHolder.getSubmittedValue:
Возвращает значение submitValue этот компонент. Этот метод должен только используется encodeBegin() и/или encodeEnd() этого компонент или его соответствующий Renderer.
Как правило, вы даже не вызываете getValue. Вместо этого атрибут значения компонента должен быть привязан к вашей модели (возможно, bean). Ваша бизнес-логика будет взаимодействовать с моделью, а не с компонентом.
Если переданное значение не задано как значение, я предполагаю, что некоторая проверка не выполняется. Единственная проблема заключается в том, что ваше мероприятие уволено. Две предпосылки для проблемы здесь:
- У вас есть устаревшая ссылка на объект компонента.
- Вы установили непосредственный атрибут в UICommand, что означает, что событие запускается в фазе, где компонент будет находиться в неудовлетворительном состоянии.
Невозможно быть уверенным в предоставленной информации.
Ответ 3
Я работаю над xpages, которые основаны на JSF, поэтому.. он может быть одним и тем же...
В любом случае, getSubmittedValue(); всегда возвращает то, что вы видите на вкладке сети firebug/chrome develepers. Это значение в отправленном пакете. Я показал это (хром) на вкладке заголовков, в разделе данных формы, с именем $$ xspsubmitvalue.
С другой стороны, getValue() является специфичным для компонента. < - на 100% не уверены.
Ответ 4
TL; DR ответ:
UIViewRoot viewRoot = context.getViewRoot();
UIInput input = (UIInput)viewRoot.findComponent(":form:inputID");
String inputValueString;
if (input.isLocalValueSet()) {
inputValueString = (String)input.getValue(); //validated and converted already
} else {
inputValueString = (String)input.getSubmittedValue(); //raw input
}
или, по крайней мере, то, что говорят другие ответы...
Просто используйте .getSubmittedValue()
и рассмотрите последствия преобразования необработанного ввода (если необходимо, если для этого необработанного ввода требуется преобразование). .getValue()
нарушается в этом отношении, даже с приведенным выше кодом. Это задерживает представленное значение, если вы его используете, и это неприемлемо.