| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java EE (J2EE) и Spring > сделать UserSessionContext, как? |
| Автор: sandello 18.9.2007, 15:04 |
| Есть JBossAS + EJB3. Есть бизнес логика, которая выполняется набором Session EJB на AS. Некоторые из этих бинов предоставляют «точку входа» в систему. Нужно сделать какой-то контекст, который будет один для всего стека вызовов, начиная с точки входа. Другими словами при «дерганьи» за эту точку входа создается какой-то контекст, к которому можно получить доступ из любого метода. При совершении вызова другого бина этот контекст распространяется туда. Т.е. если в первом бине в контекст положить значение, то во втором его можно добыть. При этом значения не будут никак пересекаться со значениями из «паралелльного» контекста (другой вызов точки входа). Как можно решить такую задачу? Особенно в случае нескольких AS. Тривиальный вариант добавлять в этот контекст в качестве аргумента лучше не расматривать, интересно другое решение. |
| Автор: Maksym 18.9.2007, 15:33 |
| sandello http://en.wikipedia.org/wiki/Singleton_pattern не проканает? |
| Автор: Maksym 18.9.2007, 18:36 |
А то. |
| Автор: sandello 19.9.2007, 06:20 |
Я честно говоря не знаю, как JBoss поднимает и хранит запущенные бины... Но есть подозрение, что никто не гарантирует одного потока... особенно, если идут вызовы между бинами. Какой-то из них может оказаться удаленным. Второе, после окончания обработки моего запроса поток не умирает и нужно позаботиться, что бы этот контекст очистить. Подозреваю, что задача в общем случае решения не имеет. Проще сделать руками - обеспечить передачу между бинами и складывание в ENV каждого бина. |
| Автор: mindflyer 19.9.2007, 09:59 | ||||||
| В случае одного сервера задачу легко и удобно решить с помощью threadLocal контекста создаваемого и уничтожаемого в интерсепторе. Т.е. создаешь свой интерсептор, вешаешь его на SB (SessionBean) и все обращения к SB проходят через него. Если лень навешивать интерсепторы явно на все SB, то можно прописать в файл ejb3-interceptors-aop.xml. Все вызовы между бинами идут в одном потоке, поэтому проблем не будет. Если где-то тебе понадобиться запустить обработку в нескольких потоках, то просто скопируй контекст и в их threadLocal. Почистить не забудь Для интерсептора прописываемого в ejb3-interceptors-aop.xml код будет такой:
Для явно указываемых в SB:
Если контекст нужно передавать в другой сервер, то тут, конечно, сложнее. Между серверами я не делал, но реализовывал между клиентом и сервером (принципиальной разницы быть не должно). Объект invocation (из первого примера), который использует JBoss для вызовов SB, хранит метаинформацию (invocation.getMetaData(...)). Так вот, берём прописываем два интерсептора: один для вызывающей стороны - в ejb3-interceptors-aop.xml в стеки с именами "*ClientInterceptors", который будет сохранять контекст в метадату, и второй для принимающей стороны, который будет извлекать контекст и устанавливать его в threadLocal, у меня он прописан примерно так:
Плюс в другие домены рядом с "<interceptor-ref name="org.jboss.ejb3.security.AuthenticationInterceptorFactory"/>". Причину сейчас уже не помню. Таким образом можно осуществить передачу в одну сторону. В обратную сторону я не делал, но немного исследовал этот вопрос и увидел, что JBoss для передачи в обратную сторону использует invocation.getResponseContextInfo(). Так что и здесь проблем быть не должно. |
| Автор: sandello 19.9.2007, 10:13 | ||
По смыслу задачи, threadLocal нужно чистить только при клиентском вызове. Поэтому на все SB нельзя. Только на те, что торчат интерфейсами наружу. Проблема будет для бинов, которые обрабатывают и внешние (контекста еще нет, нужно чистить/создавать), и внутренние (контекст чистить _нельзя_). Если нет передачи между вызовами, то контекст лепить вообще нет необходимости: штатный java:comp/env дает все что нужно (или я ошибаюсь?).
Можешь про это подробнее? Где почитать? Для меня сейчас главная проблема обеспечить передачу этого контекста между бинами, которые находятся на одном или нескольких узлах. |
| Автор: mindflyer 19.9.2007, 10:48 | ||||
Пусть интерсептор и проверяет требуется ли создание контекста. Как в приведённом мною примере.
Почитать можно на сайте JBoss про EJB3 и AOP. Точных ссылок не помню, да и бОльшую часть информации выяснял экспериментально. Там всё достаточно просто, возьми для примера один из интерсепторов прописанных в том файле, и напиши свой по аналогии. |
| Автор: sandello 30.1.2008, 07:28 |
| Решение, честно говоря, выглядит как затычка, за которой надо очень хорошо присматривать.... Ибо может не сработать. Думаю просто тупо добавить еще один аргумент в каждый бизнес метод бина. А остальное можно и аспектами доделать. |
| Автор: mindflyer 30.1.2008, 11:15 |
| А что именно не нравится? И почему может не сработать? У нас этот код написан полтора года назад, и с тех пор ни разу к нему не возвращались. Собственно, кроме меня в нашей команде никто и не знает как это работает - потому что никому и не нужно это знать, всё работает прозрачно и стабильно. По-умолчанию, контекст создаётся для абсолютно всех вызовов EJB SB, в нём устанавливается id клиентского приложения, текущий пользователь, ряд дополнительных характеристик. Сам id приходит с клиента в invocation.getMetaData(). Этот id пишется в логи в каждую запись, создаваемую в рамках обработки запроса от клиента. Что, как ты сам заметил в соседней теме, очень удобно. Плюс есть ряд других контекстов, расширяющих дефолтовый, для обработки специфических запросов. Если тебя смущают интерсепторы, то можно просто создавать/уничтожать те же самые ThreadLocal контексты руками в точке входа запроса. Если таких точек немного, то и такой вариант прокатит. Но, ИМХО, вот это уже точно сложнее отслеживать, чем в предлагаемом мною решении. У нас есть один use-case, где жизненный цикл контекста контролируется явным образом в SFSB - но там такая специфика, что он должен жить именно всё время жизни SFSB. Да и там для обработки клиентского запроса стартует множество потоков, в каждом из этих потоков в threadLocal устанавливается ссылка на этот контекст (тоже прозрачным способом, используя наше расширение ThreadPoolExecutor) - и каждый поток складывает результаты работы в этот контекст. Так что слова про затычку мне не понятны. Постановка задачи у тебя - добавить одинаковую обработку для всех клиентских запросов - а ведь интерсепторы именно для этих целей и используются в jboss. И, кстати, реализованы именно через AOP |