@ViewScoped вызывает @PostConstruct при каждом запросе обратной передачи - PullRequest
28 голосов
/ 04 апреля 2011

Это не кажется правильным.Я делал некоторую очистку своего кода, и я только заметил это.Каждый запрос ajax запускает конструктор и @PostConstruct моего @ViewScoped компонента.Даже простое разбиение базы данных запускает его.

I понял , что @ViewScoped длиннее @RequestScoped и что его не следует восстанавливать при каждом запросе.Только после полной перезагрузки страницы по GET.

1 Ответ

50 голосов
/ 04 апреля 2011

Другими словами, ваш @ViewScoped бин ведет себя как @RequestScoped бин. Он был воссоздан с нуля при каждом запросе обратной передачи. Для этого есть много возможных причин, большинство из которых сводится к тому, что связанное представление JSF больше не доступно в состоянии JSF, которое, в свою очередь, по умолчанию связано с сеансом HTTP.

При условии, что вы можете убедиться, что сам HTTP-сеанс не является основной причиной проблемы, т. Е. Когда @SessionScoped работает абсолютно нормально, просмотрите приведенный ниже список возможных причин. В противном случае, если сам HTTP-сеанс также удаляется и воссоздается при каждом отдельном запросе, вам нужно сделать шаг назад и посмотреть файл cookie сеанса и конфигурацию сервера. Любая причина, связанная с прерванным сеансом HTTP, по крайней мере выходит за рамки JSF.

  1. Вы используете Mojarra 2.1.17 или более раннюю версию, и представление содержит выражения EL, которые связывают свойство bean-объекта области видимости с атрибутом тега, который оценивается во время времени построения представления . Примерами являются JSTL <c:if>, <c:forEach> и т. Д. Или JSF <ui:include>, <x:someComponent id="#{...}", <x:someComponent binding="#{...}"> и т. Д. Это вызвано ошибкой в ​​Мохарре ( выпуск 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>
    

    Важно отметить, что привязка значения атрибута id или binding компонента JSF к свойству bean-объекта области видимости является плохой практикой. Они действительно должны быть привязаны к свойству bean-объекта в области запроса, или нужно искать альтернативу. См. Также Как работает атрибут 'binding' в JSF? Когда и как его следует использовать?

  2. Вы используете Mojarra 2.2.0, только в этой версии есть (пока неизвестная) ошибка в поддержании области просмотра, которая уже исправлена ​​в 2.2.1, см. Также выпуск 2912 . Решение заключается в обновлении до более новой версии.

  3. Аннотация @ViewScoped импортирована из неправильной упаковки. JSF предлагает две аннотации @ViewScoped, одну из пакета javax.faces.bean для управляемых компонентов JSF с аннотацией @ManagedBean и другую из пакета javax.faces.view для управляемых компонентов CDI с аннотацией @Named. Если аннотация области bean-компонента не соответствует аннотации управления bean-компонентом, тогда фактическая область действия bean-компонента станет стандартной областью структуры управления bean-компонентом, которая равна @RequestScoped в управляемых компонентах JSF и @Dependent в управляемых bean-компонентах CDI.

    Вы должны убедиться, что у вас есть одна из следующих конструкций и не смешивать их, см. Также @ 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 {
    
  4. Вид (случайно?) Помечен как переходный через <f:view transient="true">. Это в основном включает «JSF без гражданства», который является новым с Mojarra 2.1.19. Таким образом, представление JSF просто не будет сохранено в состоянии JSF вообще, и логическое следствие этого состоит в том, что все компоненты, на которые ссылается представление, больше не могут быть связаны с представлением JSF. См. Также В чем польза безгражданства в JSF?

  5. Веб-приложение настроено с параметром контекста com.sun.faces.enableRestoreView11Compatibility, установленным на true, в неверной попытке «избежать» ViewExpiredException. С этим параметром контекста ViewExpiredException никогда не будет выброшено, но представление (и все связанные с ним компоненты видимости bean-компонентов) будут просто воссозданы с нуля. Однако, если это происходит при каждом запросе, тогда этот подход на самом деле скрывает другую проблему: представления истекают слишком рано. Это указывает на возможную проблему в поддержании состояний представления JSF и / или сеанса HTTP. Как решить / настроить это правильно, перейдите к javax.faces.application.ViewExpiredException: представление не может быть восстановлено .

  6. Путь к классам времени выполнения веб-приложения загрязнен несколькими различными версиями API JSF или соответствующими классами.Это вызывает повреждение / несоответствие в идентификаторах / маркерах для состояния просмотра JSF.Вам нужно убедиться, что в веб-приложении /WEB-INF/lib нет нескольких JAR-файлов JSF API.Если вы используете Maven, убедитесь, что вы отметили предоставленные сервером библиотеки как <scope>provided</scope>.См. Также раздел «Установка JSF» в нашей вики-странице JSF и ответ на этот связанный с этим вопрос: Как правильно установить и настроить библиотеки JSF через Maven? .

  7. Когда вы используете PrimeFaces <p:dialog>, убедитесь, что <p:dialog> имеет свой собственный <h:form> и что он не вложен в другой <h:form>.См. Также p: fileUpload внутри p: диалоговое окно с потерями значений @ViewScoped .

  8. Когда вы объединяете PrimeFaces FileUploadFilter с PrettyFaces, убедитесь, что FileUploadFilter также работает на переписанных / переадресованных запросах PrettyFaces.См. Также Переопределение bean-компонента ViewScoped при вызове FileUploadListener с использованием PrettyFaces и Как использовать PrimeFaces p: fileUpload?Метод слушателя никогда не вызывается или UploadedFile имеет значение null / выдает ошибку / не используется .

  9. Когда вы используете PrettyFaces, неправильно настроенное правило перезаписи, которое перенаправляет CSS / JS /Ресурсы изображений для страницы JSF, связанной с компонентом @ViewScoped, также будут вводить в заблуждение.См. Также CDI ViewScope и PrettyFaces: множественные вызовы @PostConstruct (JSF 2.2) .

...