Как распространить сеансовые компоненты CDI из сеанса HTTP в сеанс WebSocket?

Я много искал эту проблему, прежде чем опубликовать этот вопрос, и Доступ к HttpSession из HttpServletRequest в веб-сокете @ServerEndpoint — один из лучших вопросов/ответов, которые мне удалось найти, но, похоже, он не решает мою проблему.

Таким образом я смог получить доступ к HttpSession из веб-сокета, но я не могу получить доступ к тем же экземплярам сеансового компонента CDI, что и из обычных HTTP-запросов.

Я также пытался сохранить в сеансе экземпляр HttpSessionContextImpl Weld и пытался использовать его на стороне WebSocket, но он не открывал предыдущие bean-компоненты.

Тогда мой вопрос: возможно ли получить доступ к одним и тем же экземплярам управляемого сеанса CDI в обоих случаях (события WebSocket и обычные запросы HTTP)?

На данный момент для меня важно, чтобы эта функция работала в Wildfly 9/10, но было бы здорово иметь общее решение, работающее, например, и на Tomcat > 7 (с использованием jBoss Weld или любой другой реализации).

Заранее спасибо за вашу поддержку.


person Ivano85    schedule 23.03.2016    source источник
comment
Вы проверили, что вы обращаетесь к тому же сеансу? Получаете ли вы какие-либо cdi-бины с областью сеанса при использовании веб-сокетов? Если да, то сеансы, вероятно, не совпадают, если нет, то прослушиватель/перехватчик, ответственный за инициализацию контекста сеанса, вероятно, не работает (тогда либо сделайте это вручную, либо попробуйте свернуть свой собственный контекст сеанса).   -  person Thomas    schedule 23.03.2016
comment
Да, я отлаживал версию wildfly, и экземпляр HttpSession одинаково виден в обоих контекстах и ​​содержит те же экземпляры bean-компонентов, что и во время HTTP-запроса, но я не могу сделать их управляемыми в контексте веб-сокета (как во время onOpen, так и во время ServerEndpointConfig казни).   -  person Ivano85    schedule 23.03.2016


Ответы (1)


Тогда мой вопрос: возможен ли доступ к одним и тем же экземплярам управляемого сеансового компонента CDI в обоих случаях (события WebSocket и обычные HTTP-запросы)?

Только во время рукопожатия, потому что это HTTP-запрос. Сеанс HTTP доступен только во время запроса HTTP, но не во время запроса WS. Надеюсь, причина теперь очевидна, поскольку CDI хранит bean-компоненты с областью сеанса в сеансе HTTP, который идентифицируется только с помощью HTTP-запроса, а во время запроса WS нигде нет средств физического HTTP-запроса, и поэтому сеанс HTTP также недоступен.

Лучше всего создать уникальный идентификатор, сохранить его в bean-компоненте с областью действия сеанса, добавить его в URL-адрес WS (как путь или параметр запроса), извлечь его во время onOpen и сохранить в bean-компоненте с областью действия приложения. На обычных серверах Java EE компоненты CDI с областью действия приложения доступны через @Inject в классе конечной точки WS обычным способом (но не в Tomcat/Jetty/и т. д., вам придется вручную захватить их через BeanManager). Наконец, просто позвольте bean-компоненту с областью действия сеанса, содержащему уникальный идентификатор, обращаться к bean-компоненту с областью действия приложения для любых открытых сокетов по этому идентификатору.

По крайней мере, я пошел по этому пути при разработке тега OmniFaces <o:socket> для JSF. Все это с открытым исходным кодом, вы можете найти ссылки на исходный код в нижней части его демонстрационной страницы.

person BalusC    schedule 23.03.2016
comment
Спасибо за ваш ответ. Я посмотрю на ссылку, которую вы разместили, как только будет возможно. Хотя я искал более чистое решение, если его не будет, я прекращу реализацию пользовательского решения, подобного вашему. - person Ivano85; 23.03.2016
comment
Нет ни одного. Как объяснено, в этот момент нигде нет HTTP-запроса/сеанса. Никакая магия не может этого изменить. Однако для этого у меня есть новая область CDI, такая как @WebsocketScoped. - person BalusC; 23.03.2016
comment
Да, конечно, я уже реализовал пользовательские контексты @RequestScoped и @SessionScoped, которые будут использоваться во всех случаях, когда официальные недоступны (т. е. большинство тегированных контекстов). Поэтому я был бы признателен за любую идею для реализации этого. В худшем случае кто-нибудь знает, как пользовательская реализация контекста @SessionScoped может надежно находить (и делать управляемые) сеансовые компоненты доступными в атрибутах HttpSession? На мой взгляд, эта магия была бы действительно чистым решением... - person Ivano85; 23.03.2016
comment
Нет сеанса HTTP во время запроса/сеанса WS. Невозможно внедрить вещь, связанную с запросом/сеансом HTTP/CDI, в вещь, связанную с WS. Однако, с другой стороны, есть способ внедрить фиктивную область, связанную с WS, в запрос/сеанс HTTP/CDI (через компонент области приложения, как я подробно описал в своем ответе). С другой стороны, возможно, эти связанные вопросы и ответы также полезны: stackoverflow.com/q/32426674 - person BalusC; 23.03.2016
comment
Я думаю собрать все вместе и, возможно, я попытаюсь использовать только свои пользовательские контексты @RequestScoped и @SessionScoped вместо контекстов контейнера или использовать аналогичное решение, чтобы иметь максимально чистую реализацию. Затем я опубликую свое решение, если я добьюсь успеха. А пока я принимаю ваш ответ ;-). Спасибо вам за ваши предложения. - person Ivano85; 23.03.2016