JSF 2.1 ViewScopedBean @PreDestroy метод не вызывается - PullRequest
9 голосов
/ 18 июля 2011

У меня есть метод в представлении Scoped Bean с аннотацией @PreDestroy и другой с аннотацией @PostConstruct.

Метод @PostConstruct правильно вызывается каждый раз, когда я перехожу на страницу, котораяиспользует этот bean-объект области видимости.

Однако, когда я перехожу на новую страницу (которая не использует этот компонент области видимости) с помощью <h:link/>, метод @PreDestroy никогда не вызывается.

Я не говорю о изменении вручную URL или конца сеанса , только из-за случая навигации.

Что мне не хватает?

Заранее спасибо

Ответы [ 2 ]

17 голосов
/ 05 января 2012

Это по замыслу.Он будет удален только тогда, когда действие POST приведет к навигации, которая не является обратной передачей к тому же представлению (т. Е. Метод действия не вернул null или void, а выполнил String, даже когдапросто пусто).

<h:link> создает ссылку GET, которая не вызывает никакого действия POST.Поскольку невозможно надежно уведомить серверную часть с помощью (XML) HTTP-запроса, когда представление выгружено, JSF не может быть уведомлено об уничтожении bean-объекта области видимости, связанного с представлением.В этом случае bean-объект области видимости будет уничтожен только по истечении сеанса или когда превышено максимальное количество логических представлений в сеансе (по умолчанию 15), и связанный вид является первым по порядку.

ЕслиВы действительно хотите уничтожить объект видимости, заданный с помощью действия navigaiton, тогда лучше всего сделать это вместо POST-запроса на <h:commandLink> и выполнить перенаправление, возвращая результат навигации с параметром ?faces-redirect=true,Но это, в конце концов, не оптимизировано для SEO, так как боты не будут индексировать ссылки POST.

В конце концов, мне было бы все равно, какое представление все еще находится в сеансе.Если вы собираетесь провести некоторую очистку или ведение журнала, я бы искал альтернативные способы, в зависимости от конкретных функциональных требований.

В теории это было бы возможно с помощью события HTML DOM onbeforeunload, но это нестандартное событие, и поведение браузера не определено относительно того, что происходит, когда вы отправляете ajax-запрос во время этого события.Это иногда прибывает, но иногда также нет.

Обновление : в практике это было реализовано в OmniFaces @ViewScoped начиная с OmniFaces 2.2.Первоначально с помощью синхронный XHR и начиная с OmniFaces 2.6 с помощью маяк .Это работает довольно хорошо в основных браузерах.Начиная с OmniFaces 2.3, он даже немедленно уничтожает соответствующее состояние просмотра на стороне сервера JSF, а с OmniFaces 2.6 он даже немедленно уничтожает физические компоненты, тем самым дополнительно сокращая ненужное использование памяти.См. Также среди прочих JSF: Мохарра против OmniFaces @ViewScoped: @PreDestroy вызван, но бин не может быть собран мусором

2 голосов
/ 23 мая 2015

Я подготовил небольшой проект NetBeans, демонстрирующий, когда JSF2.2 CDI-совместимые бины @ViewScoped (javax.faces.view.ViewScoped) выпущены для сбора мусора в различных случаях навигации (для Mojarra 2.2.9, Glassfish4, NetBeans8.0.2, JDK1.7), доступно для скачать здесь . Код здесь опущен, см., Пожалуйста, загрузку.

Обработанные случаи навигации и результаты суммированы этим изображением:

Image showing index page using @ViewSCoped bean with JSF navigation cases to a done landing page

Чтобы отслеживать компоненты @ViewScoped, используйте VisualVM против Glassfish (или встроенный профилировщик NetBeans в мини-проекте) и отфильтруйте представление класса гистограммы кучи памяти сэмплера по имени пакета «webel.com.jsf».На следующем рисунке показаны нелепые 66 экземпляров webel.com.jsf.Jsf22ViewBean после обильного эксперимента с h: link, браузерными GET-адресами URL и браузерными RETOAD GET, экземпляры которых не будут собираться мусором (который можно протестировать с помощью VisualVM Perform GCкнопка):

enter image description here

Для сравнения, отойдя от index.xhtml (который использует бин @ViewScoped один раз для простого чтения EL-переменной) к done.xhtml (который делаетне использовать компонент вообще) использование h: commandButton и выражение метода действия или строка действия приводят к тому, что компонент @ViewScoped освобождается для сборки мусора (всегда есть одна ссылка из WeldClientProxy на компонент @ViewScoped и при переходе по немувперед и назад с помощью h: commandButton WeldClientProxy перемещается от одного освобождаемого компонента к следующему).

...