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

Я гуглил пару часов по этому вопросу без оценки.

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

Например:

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

  • Область сеанса - небезопасно

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

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

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

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

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


person Mark    schedule 14.09.2011    source источник


Ответы (2)


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

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

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

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

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

Смотрите также:

person BalusC    schedule 14.09.2011
comment
Я понимаю, что, как и в случае с областью диалога, в любой момент времени может быть несколько запросов ajax, каждый из которых приводит к потоку запросов, который может получить доступ к области просмотра. Подумайте о ком-то, кто рассылает спам, нажимая кнопку ajax, что приводит к модификации данных в bean-компоненте, если доступ к этим запросам не синхронизируется или сериализуется прокси-сервером, тогда могут возникнуть проблемы. - person Mark; 14.09.2011
comment
О, сюда. Да, запросы ajax из одного и того же представления ставятся в очередь на стороне клиента, как указано в спецификации JSF 2. Я обновлю ответ выдержкой из спецификации. Синхронные запросы не ставятся в очередь JSF, но в любом случае это делает браузер. - person BalusC; 14.09.2011
comment
спасибо за обновление, если я могу побеспокоить вас за 1 дополнительный вопрос: ясно, что цитируемая спецификация охватывает вызовы ajax, однако, если у вас есть ссылка на представление jsf, которое поддерживается bean-компонентом viewscoped, и это представление имеет метод для вызова вспомогательного компонента через af:event, скажем, событие preRenderView или что-то в этом роде. Если бы исходная ссылка была нажата спамом, я бы ожидал несколько вызовов этого метода (я думаю, я не на 100% уверен, когда именно начнется область просмотра), любая идея, будут ли эти вызовы поставлены в очередь таким образом, что ajax звонки есть? - person Mark; 14.09.2011
comment
Может быть, то, что я прошу, попадет в корзину синхронных запросов? Однако я не уверен, что браузер действительно ставит их в очередь, я провел некоторое тестирование в случае, который я только что описал, с bean-компонентами с областью сеанса, чтобы увидеть, что произойдет, и я определенно получаю параллельное выполнение метода. - person Mark; 14.09.2011
comment
Ссылки - это запросы GET, и каждый запрос GET будет воссоздавать компонент, даже если он находится в том же окне. Результат навигации, отличный от null/void, также воссоздаст bean-компонент. - person BalusC; 14.09.2011

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

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

person Vineet Reynolds    schedule 14.09.2011