Ответ 1
Другими словами, ваш @ViewScoped
bean ведет себя как @RequestScoped
bean. Он был воссоздан с нуля при каждом запросе обратной передачи. Существует много причин для этого, большинство из которых сводится к тому, что связанное представление JSF больше не доступно в состоянии JSF, которое, в свою очередь, по умолчанию связано с сеансом HTTP.
-
Вы используете Mojarra 2.1.17 или более позднюю версию, и представление содержит EL-выражения, которые привязывают свойство scope bean к атрибуту тега, которое оценивается во время просмотреть время сборки. Примерами являются JSTL
<c:if>
,<c:forEach>
и т.д. Или JSF<ui:include>
,<x:someComponent id="#{...}"
,<x:someComponent binding="#{...}">
и т.д. Это вызвано ошибкой в Mojarra (вопрос 1492). См. Также Почему обратный вызов @PostConstruct срабатывает каждый раз, даже если bean является @ViewScoped? JSFЭто уже исправлено в версии Mojarra 2.1.18. Если вы не можете перейти на более новую версию, обходным путем является отключение частичного сохранения состояния, как показано ниже в
web.xml
, см. Также JSTL в JSF2 Facelets... имеет смысл?<context-param> <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> <param-value>false</param-value> </context-param>
Или когда вы хотите настроить таргетинг только на определенный набор представлений JSF:
<context-param> <param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name> <param-value>/foo.xhtml;/bar.xhtml;/folder/baz.xhtml</param-value> </context-param>
Важно отметить, что привязка значения атрибута JSF-компонента
id
илиbinding
к объекту с ограниченным представлением bean является плохой практикой. Они действительно должны быть привязаны к собственному запросу bean, или следует искать альтернативу. См. Также Как работает атрибут привязки в JSF? Когда и как его использовать? -
Вы используете Mojarra 2.2.0, только эта версия имеет (но неизвестную) ошибку при сохранении области видимости, которая уже исправлена в 2.2.1, см. также issue 2912. Решение заключается в обновлении до более новой версии.
-
Аннотация
@ViewScoped
импортируется из неправильного пакета. JSF предлагает две аннотации@ViewScoped
, один изjavax.faces.bean
для JSF-управляемого beans, аннотированный с помощью@ManagedBean
, а другой из пакетаjavax.faces.view
для управляемого CDI beans с аннотацией@Named
. Когда аннотация bean не соответствует аннотации управления bean, то фактическая область bean станет bean базой по умолчанию для рамки управления, которая@RequestScoped
в управляемых JSF beans и@Dependent
в управляемом CDI beans.Вам нужно убедиться, что у вас есть одна из следующих конструкций и не смешивать их, см. также @ViewScoped bean, воссозданный при каждом обратном обращении при использовании JSF 2.2.
import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; @ManagedBean @ViewScoped public class CorrectJSFViewScopedBean implements Serializable {
import javax.inject.Named; import javax.faces.view.ViewScoped; @Named @ViewScoped public class CorrectCDIViewScopedBean implements Serializable {
-
Вид (случайно?) отмечен переходным процессом через
<f:view transient="true">
. Это в основном включает "без гражданства JSF", который является новым с Mojarra 2.1.19. Таким образом, представление JSF просто не будет сохранено в состоянии JSF вообще, и логичным следствием является то, что все ссылоченные области видимости beans больше не могут быть связаны с представлением JSF. См. Также Какова польза безгражданства в JSF? -
Веб-приложение настроено с параметром контекста
com.sun.faces.enableRestoreView11Compatibility
, установленным наtrue
, в неправильной попытке "избегать"ViewExpiredException
. С этим параметром контекстаViewExpiredException
никогда не будет выбрасываться, но представление (и все связанные с ним области видимости beans) будут только воссозданы с нуля. Однако, если это происходит по каждому запросу, то этот подход действительно скрывает еще одну проблему: представления истекают слишком рано. Это указывает на возможную проблему при сохранении состояний представления JSF и/или сеанса HTTP. Как правильно решить/настроить, перейдите в javax.faces.application.ViewExpiredException: просмотр не удалось восстановить. -
Путь к классам времени выполнения веб-приложений загрязнен несколькими различными версиями API JSF API или связанных с ним классов. Это вызывает повреждение/несоответствие в идентификаторах/маркерах для состояния представления JSF. Вы должны убедиться, что у вас нет нескольких JAR файлов JSF API в webapp
/WEB-INF/lib
. Если вы используете Maven, убедитесь, что вы помечаете серверные библиотеки как<scope>provided</scope>
. См. Также раздел "Установка JSF" в нашей странице вики JSF и ответ на этот связанный вопрос: Как правильно установить и настроить Библиотеки JSF через Maven?. -
Когда вы используете PrimeFaces
<p:dialog>
, убедитесь, что<p:dialog>
имеет свой собственный<h:form>
и что он не вложен в другой<h:form>
. См. Также p: fileUpload внутри p: диалог потеряет значения @ViewScoped. -
Когда вы комбинируете PrimeFaces
FileUploadFilter
с PrettyFaces, убедитесь, чтоFileUploadFilter
также работает в PrettyFaces-переписанных/пересылаемых запросах. См. Также ViewScoped bean перестроен, когда FileUploadListener вызвал использование PrettyFaces и Как использовать PrimeFaces p: fileUpload? Метод прослушивателя никогда не вызывается или UploadedFile имеет значение null. -
Когда вы используете PrettyFaces, неправильно настроенное правило перезаписи, которое перенаправляет ресурсы CSS/JS/image на страницу JSF, привязанную к
@ViewScoped
bean, также приведет к ошибочному поведению. См. Также CDI ViewScope и PrettyFaces: несколько вызовов в @PostConstruct (JSF 2.2).