Компонент с областью просмотра, воссозданный при POST, когда параметры URL не используются

У меня есть управляемый JSF-компонент view-scoped, который поддерживает представление xhtml, где я считываю один параметр из URL-адреса, используя f:viewParam.

Представление представляет собой форму для пользователя. Однако, когда пользователь отправляет форму, нажимая p:commandButton, кажется, что bean-компонент с областью видимости воссоздается (я добавил аннотацию @PostConstruct, чтобы убедиться в этом) и поэтому не запоминает переменную экземпляра, считанную из f:viewParam (invId в приведенном ниже коде).

Сначала я перехожу к представлению с помощью команды GET, которая включает параметр URL, но сообщение POST, которое отправляется, когда пользователь нажимает кнопку p. :commandButton не включает параметр URL. Поэтому я думаю, что когда среда выполнения JSF не видит параметр URL в POST, она считает это другим представлением и воссоздает управляемый JSF bean-компонент. Когда я меняю область представления на сеансовую, код работает.

Вот код:

Посмотреть

<f:metadata>
    <f:viewParam name="invId" value="#{registerBean.invId}"/>
</f:metadata>
<h:form id="registrationForm">
     ....
    <p:commandButton value="register" action="#{registerBean.register}"
                     icon="ui-icon ui-icon-newwin" ajax="false"/>
</h:form>

поддерживающая фасоль

@ManagedBean                                      
@ViewScoped
public class RegisterBean implements Serializable {
    @ManagedProperty(value="#{invId}")
    private String invId;
    ...

Обновить

Оказывается, это вообще не было связано с параметрами URL. Следуя приведенному ниже совету BalusC, я удалил теги c:when, которые использовал мой вид (вместо этого полагаясь на атрибуты рендеринга для того же эффекта), и теперь bean-компонент с областью просмотра больше не создается заново, а поле invId сохраняется должным образом.


person Marcus Junius Brutus    schedule 08.01.2013    source источник
comment
Такое поведение является особенностью. Этот вопрос является возможным дубликатом: stackoverflow.com/questions/10352641/   -  person Elias Dorneles    schedule 08.01.2013
comment
@elias: это не тот же вопрос.   -  person BalusC    schedule 08.01.2013
comment
Маркус, @ManagedProperty не на месте, я бы избавился от него. Что касается конкретной проблемы, пожалуйста, покажите наименьший возможный фрагмент представления, который воспроизводит именно эту проблему путем простого копирования. Компонент с областью видимости будет воссоздан, когда вы привяжете атрибут обработчика тегов (например, <c:if>, <ui:include> и т. д.) к его свойству, но это не видно в опубликованном коде, который кажется слишком упрощенным. Вам необходимо предоставить именно ту информацию, которая вам нужна, чтобы воспроизвести проблему в совершенно пустом проекте со всеми настройками по умолчанию, в том числе самостоятельно.   -  person BalusC    schedule 08.01.2013
comment
@BalusC ты прав! Я читал в спешке и был пойман эффектом недавности.   -  person Elias Dorneles    schedule 08.01.2013
comment
@BalusC Я действительно использую как ‹c:if›, так и ‹ui:include›. Я удалю их, чтобы увидеть, воссоздан ли компонент или нет, и буду следить за выводами.   -  person Marcus Junius Brutus    schedule 08.01.2013
comment
@BalusC Я обновил сообщение. Если вы дадите символический ответ, я сразу же приму его.   -  person Marcus Junius Brutus    schedule 08.01.2013


Ответы (1)


Проблема не видна в коде, опубликованном до сих пор, но для JSF 2.0/2.1 это известная проблема, заключающаяся в том, что bean-компонент с областью видимости будет воссоздан, когда одно из его свойств будет привязано к атрибуту обработчика тегов, например JSTL <c:if> или Facelets <ui:include> или атрибут времени сборки представления компонента JSF, например id и binding, в то время как частичное сохранение состояния включено (по умолчанию).

Фоновое объяснение состоит в том, что любые выражения EL в этих атрибутах выполняются во время построения и восстановления представления. Поскольку bean-компоненты с областью видимости хранятся в представлении и, таким образом, доступны только после восстановления представления, такая оценка выражения EL приведет к созданию совершенно нового и отдельного bean-компонента с областью видимости. Это в основном проблема куриного яйца. Это исправлено в грядущей версии JSF 2.2.

Есть в основном 3 решения:

  1. Измените представление соответствующим образом, чтобы эти выражения EL оценивались только во время рендеринга представления. Например. заменить <c:if>/<c:choose> на rendered.
  2. Или привяжите эти атрибуты к bean-компоненту с областью действия запроса (уведомление о дизайне: вы можете просто внедрить bean-компонент с областью видимости в качестве управляемого свойства bean-компонента с областью запроса).
  3. Отключите частичное сохранение состояния, если это необходимо только для определенного представления.

Смотрите также:

person BalusC    schedule 08.01.2013
comment
Хотя это решение не решило именно ту проблему, с которой я столкнулся (я просто использовал старую версию Mojarra с известными ошибками), этот ответ показал мне некоторые новые концепции, которые я смог использовать для решения других проблем, с которыми столкнулся наш проект. вбегает. Большое спасибо, BalusC! - person Ampp3; 09.03.2015