Подтвердить что ты не робот

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 ПОЛНОСТЬЮ? Любое понимание этих двух методов было бы весьма полезно. Приветствия.

4b9b3361

Ответ 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() нарушается в этом отношении, даже с приведенным выше кодом. Это задерживает представленное значение, если вы его используете, и это неприемлемо.