Я пытаюсь вызвать метод, аннотированный @PreDestroy
в @ViewScoped
bean-компоненте, когда пользователь покидает страницу, связанную с этим bean-компонентом, в довольно большом веб-приложении на основе JSF.
Прочитав https://stackoverflow.com/a/15391453/5467214 и несколько других вопросов и ответов по SO, а также https://showcase.omnifaces.org/cdi/ViewScoped, я пришел к понимая, что аннотация OmniFaces ViewScoped
обеспечивает именно такое поведение, используя событие страницы unload
, а также sendBeacon
в современных браузерах.
Поэтому я использовал аннотацию @ViewScoped
из OmniFaces в своем bean-компоненте:
import javax.annotation.PreDestroy;
import org.omnifaces.cdi.ViewScoped;
@Named("DesktopForm")
@ViewScoped
public class DesktopForm implements Serializable {
...
}
и аннотировал метод, который я хочу вызвать, аннотацией PreDestroy
:
@PreDestroy
public void close() {
System.out.println("Destroying view scoped desktop bean");
...
}
К сожалению, этот метод "закрыть" не вызывается, когда я нажимаю на какую-либо ссылку или покидаю страницу. путем ввода совершенно нового URL. Вместо этого сетевой анализ моего браузера (текущий Firefox) показывает мне, что запрос POST отправляется при выходе со страницы, которая возвращается с кодом ошибки 403 http:
Как вы можете видеть на снимке экрана, «инициатором» POST-запроса является скрипт unload.js.jsf
с beacon
, упомянутым в скобках, который, как я полагаю, является частью библиотеки OmniFaces. Так что предположительно функционал, описанный в документации OmniFaces ViewScoped
, каким-то образом срабатывает, но не приводит к ожидаемому для меня поведению.
Браузер по-прежнему переходит на новую страницу, но аннотированный метод PreDestroy
не срабатывает. Когда я переключаюсь на стандартную версию ViewScoped
(javax.faces.view.ViewScoped
вместо org.omnifaces.cdi.ViewScoped
), естественно, метод все еще не вызывается, но также нет метода POST, приводящего к статусу ошибки 403 при выходе со страницы в анализе сети моего браузера ( потому что стандартная ViewScoped
аннотация Java не пытается вызвать какое-либо стороннее действие bean-компонента для unload
событий, я думаю)
Я использую MyFaces 2.3.10 в сочетании с OmniFaces 2.7.18 (и PrimeFaces 8.0.5, я не знаю, актуально ли это), Spring Security 5.7.3 и Java 11.
Поскольку «403» — это статус http для «запрещено», может ли это иметь какое-то отношение к использованию «http» вместо «https» в моей локальной среде разработки? Этот «отправить маяк» работает только с безопасными соединениями?
Любая помощь приветствуется!
Обновлено: я также ознакомился с официальной документацией аннотации OmniFaces ViewScoped
под https://omnifaces.org/docs/javadoc/2.7/index.html?org/omnifaces/cdi/ViewScoped.html, но не смог найти причину для проблемы, с которой я сталкиваюсь.
Большое спасибо за помощь, BalusC! Ваш совет помог мне решить мою проблему!
С помощью комментария BalusC к моему вопросу выше я смог решить свою проблему.
Дело дошло до того, что события unload
неправильно обрабатывались нашей цепочкой фильтров. В частности, им было отказано в доступе к методу doFilter
расширения нашего класса org.springframework.web.filter.GenericFilterBean
.
Поэтому я добавил
if (ViewScopeManager.isUnloadRequest(httpServletRequest)) {
chain.doFilter(request, response);
}
к методу doFilter
упомянутого класса, и тогда это сработало.
Кстати, мне пришлось обновить мою библиотеку OmniFaces с 2.7.18 до 3.13.3, потому что класс ViewScopeManager
OmniFaces 2 имеет только один метод isUnloadRequest , который принимает FacesContext
в качестве параметра, которого у меня не было в наше расширение GenericFilterBean
. С другой стороны, OmniFaces 3.1 предоставляет другой метод с тем же именем, который вместо этого работает с экземпляром HttpServletRequest
, к которому у меня был доступ, и поэтому проблема решена.
403 в основном означает, что используемая структура аутентификации не может проверить/авторизовать вошедшего в систему пользователя, связанного с запросом. Попробуйте деактивировать Spring Security (или перенастроить его на «разрешить все») и посмотреть, будет ли он по-прежнему возвращать 403. Если это работает, вам, вероятно, нужно перенастроить Spring Security, чтобы всегда разрешать запросы на выгрузку (см. также «Обнаружение запросов на выгрузку» в документации OmniFaces). ).