Являются ли JSF 2.x @ViewScoped управляемыми beans потоками безопасными?

Я уже пару часов занимаюсь поиском в Интернете по этой проблеме без каких-либо оценок.

Документы WELD и спецификация CDI довольно понятны в отношении безопасности потоков предоставляемых областей.

Например:

  • Область приложения - небезопасно

  • Сессия - небезопасно

  • Область запроса - безопасна, всегда связана с одним потоком

  • Область диалога - безопасна (из-за того, что WELD-прокси-сервер выполняет сериализацию доступа из нескольких потоков запросов)

Я не могу найти что-либо в области видимости, определенной JSF 2.x.

Он находится примерно в том же ведре, что и область разговора, поскольку очень много запросов на одновременное попадание в область видимости, несмотря на то, что она привязана к одному виду/пользователю. Я не знаю, является ли реализация JSF сериализовать доступ к bean из нескольких запросов.

Кто-нибудь знает спецификацию или реализации Morraja/MyFaces, которые могли бы прояснить это?

Ответы

Ответ 1

Область просмотра с безопасным потоком использования. Он может использоваться только одним окном/вкладкой браузера. А именно, это связано с уникальным скрытым полем ввода, которое устанавливается в исходном запросе GET. Каждая обратная передача на одном и том же представлении будет использовать один и тот же вид с охватом bean. Сам браузер уже "синхронизирует" запросы обратной передачи в том же окне/вкладке. Новое окно браузера/вкладка эффективно представляет собой новый запрос GET и поэтому создаст новое и полностью независимое представление.

Что касается обратных передач ajax, они зависят от спецификации. Это упоминается в главе 13.3.2 спецификации JSF 2:

13.3.2. Очередь запросов Ajax

Все запросы Ajax должны быть помещены в очередь запросов на стороне клиента, прежде чем они будут отправлены на чтобы гарантировать, что запросы Ajax обрабатываются в том порядке, в котором они отправлены. Запрос, ожидавший в очереди запрос самый длинный - следующий запрос для отправки. После отправки запроса функция обратного вызова запроса Ajax должна удалить запрос из очереди (также называемой dequeuing). Если запрос успешно завершен, его необходимо удалить из очереди. Если произошла ошибка, клиент должен быть уведомлен, но запрос все равно должен быть удален из очереди, поэтому следующий запрос может быть отправлено. Следующий запрос (самый старый запрос в очереди) должен быть отправлен. Обратитесь к jsf.ajax.requestJavaScript для более подробной информации о очереди запросов Ajax.

Только при использовании PrimeFaces очередь может быть отключена с помощью <p:ajax async="true">. При использовании этого в сочетании с областью видимости beans переопределение потоков должно быть пересмотрено так же, как и для сеанса beans.

См. также:

Ответ 2

ViewScoped beans сохраняются в "view" Map, который создается для каждого UIViewRoot. Когда два параллельных запроса обрабатываются средой исполнения JSF, обычно маловероятно, что для этих запросов создается/восстанавливается один и тот же экземпляр UIViewRoot, поскольку параметр формы javax.faces.ViewState в HTTP-запросе используется для определения того, существует ли существующий UIViewRoot экземпляр должен быть восстановлен или нет (при обратной передаче). Как показало BalusC, два разных окна браузера приведут к созданию двух разных видов beans, поскольку базовые параметры ViewStates отличаются как для вкладок браузера (если вы выдаете два разных HTTP-запроса, а браузер использует ответ каждого из них отображать отдельные вкладки, вместо использования кешированной копии).

Часть о потокобезопасности, однако, выходит за рамки вкладки/окна браузера. Внутри среды исполнения JSF (по крайней мере, в пределах Mojarra) нет встроенного механизма, который будет синхронизировать доступ к UIViewRoot и карте вида, если два HTTP-запроса (и, следовательно, два потока) представляют одно и то же значение javax.faces.ViewState в запросе обрабатываться контейнером. Следовательно, просмотр области beans не является потокобезопасным по своей природе, и ни один из них не доступен в потоковом безопасном режиме. Вы можете подтвердить это путем повторения запросов с теми же значениями javax.faces.ViewState и наблюдать за поведением контейнера /JVM, когда несколько таких запросов принимаются контейнером в течение короткой продолжительности (что дает возможность одновременного доступа к тому же UIViewRoot экземпляр несколькими потоками).