![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
sandello |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 18.5.2005 Где: Пермь Репутация: нет Всего: 2 |
Есть JBossAS + EJB3. Есть бизнес логика, которая выполняется набором Session EJB на AS. Некоторые из этих бинов предоставляют «точку входа» в систему. Нужно сделать какой-то контекст, который будет один для всего стека вызовов, начиная с точки входа.
Другими словами при «дерганьи» за эту точку входа создается какой-то контекст, к которому можно получить доступ из любого метода. При совершении вызова другого бина этот контекст распространяется туда. Т.е. если в первом бине в контекст положить значение, то во втором его можно добыть. При этом значения не будут никак пересекаться со значениями из «паралелльного» контекста (другой вызов точки входа). Как можно решить такую задачу? Особенно в случае нескольких AS. Тривиальный вариант добавлять в этот контекст в качестве аргумента лучше не расматривать, интересно другое решение. -------------------- ![]() |
|||
|
||||
Maksym |
|
|||
![]() . ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1456 Регистрация: 19.8.2005 Где: Odessa, Black Sea Репутация: 24 Всего: 62 |
||||
|
||||
Stampede |
|
||||||
![]() Гносеолог ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 963 Регистрация: 25.4.2005 Где: Calgary, Alberta, Canada Репутация: 66 Всего: 144 |
Нет, не проканает, потому что:
sandello, для того, что ты пытаешься сделать, идеально подходит такая вешь как ThreadLocal. В двух словах, это такая конструкция, которая позволяет заводить экземпляр некой переменной таким образом, что она будет собственностью (доступной статическим образом) только этого треда. Если в качестве такой переменной использовать мап того или иного рода, то мы получим не что иное, как контекст потока. Код примерно такой:
Пользуемся этим так: Maksym, узнаешь нечто знакомое?
Фсе, телемаркет! Теперь при помощи этой конструкции можно в абсолютно любом месте кода прямо из воздуха получать все, что "наложили" в этот контекст ранее отработавшие методы. Примерно таким образом, например, реализован прозрачный (без явной передачи аргументов) доступ к текущей транзакции в JPA. Особенно хорошо понятие контекста потока ложится на идеологию SOA. Авторизация, например, превращается в сущий пустяк: в начале обработки аутентифицировал юзера, засунул его в контекст потока, и с этого момента и до конца обработки объект User у нас доступен любым алгоритмам авторизации доступа, где он может понадобиться. Аналогичным образом можно передавать через воздух локали, настройки, да и просто все что угодно. В общем, возможности ограничиваются только твоей фантазией ![]() Это сообщение отредактировал(а) Stampede - 18.9.2007, 18:26 -------------------- "If you want something done right, do it yourself" По секрету: выучить английский - реально! |
||||||
|
|||||||
Maksym |
|
|||
![]() . ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1456 Регистрация: 19.8.2005 Где: Odessa, Black Sea Репутация: 24 Всего: 62 |
||||
|
||||
sandello |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 18.5.2005 Где: Пермь Репутация: нет Всего: 2 |
Я честно говоря не знаю, как JBoss поднимает и хранит запущенные бины... Но есть подозрение, что никто не гарантирует одного потока... особенно, если идут вызовы между бинами. Какой-то из них может оказаться удаленным. Второе, после окончания обработки моего запроса поток не умирает и нужно позаботиться, что бы этот контекст очистить. Подозреваю, что задача в общем случае решения не имеет. Проще сделать руками - обеспечить передачу между бинами и складывание в ENV каждого бина. -------------------- ![]() |
|||
|
||||
mindflyer |
|
||||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 113 Регистрация: 20.10.2004 Где: Smolensk, Russia Репутация: 3 Всего: 4 |
В случае одного сервера задачу легко и удобно решить с помощью 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 |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 18.5.2005 Где: Пермь Репутация: нет Всего: 2 |
По смыслу задачи, threadLocal нужно чистить только при клиентском вызове. Поэтому на все SB нельзя. Только на те, что торчат интерфейсами наружу. Проблема будет для бинов, которые обрабатывают и внешние (контекста еще нет, нужно чистить/создавать), и внутренние (контекст чистить _нельзя_). Если нет передачи между вызовами, то контекст лепить вообще нет необходимости: штатный java:comp/env дает все что нужно (или я ошибаюсь?).
Можешь про это подробнее? Где почитать? Для меня сейчас главная проблема обеспечить передачу этого контекста между бинами, которые находятся на одном или нескольких узлах. Это сообщение отредактировал(а) sandello - 19.9.2007, 10:17 -------------------- ![]() |
|||
|
||||
mindflyer |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 113 Регистрация: 20.10.2004 Где: Smolensk, Russia Репутация: 3 Всего: 4 |
Пусть интерсептор и проверяет требуется ли создание контекста. Как в приведённом мною примере. Почитать можно на сайте JBoss про EJB3 и AOP. Точных ссылок не помню, да и бОльшую часть информации выяснял экспериментально. Там всё достаточно просто, возьми для примера один из интерсепторов прописанных в том файле, и напиши свой по аналогии. |
|||
|
||||
sandello |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 295 Регистрация: 18.5.2005 Где: Пермь Репутация: нет Всего: 2 |
Решение, честно говоря, выглядит как затычка, за которой надо очень хорошо присматривать.... Ибо может не сработать.
Думаю просто тупо добавить еще один аргумент в каждый бизнес метод бина. А остальное можно и аспектами доделать. -------------------- ![]() |
|||
|
||||
mindflyer |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 113 Регистрация: 20.10.2004 Где: Smolensk, Russia Репутация: 3 Всего: 4 |
А что именно не нравится? И почему может не сработать? У нас этот код написан полтора года назад, и с тех пор ни разу к нему не возвращались. Собственно, кроме меня в нашей команде никто и не знает как это работает - потому что никому и не нужно это знать, всё работает прозрачно и стабильно.
По-умолчанию, контекст создаётся для абсолютно всех вызовов EJB SB, в нём устанавливается id клиентского приложения, текущий пользователь, ряд дополнительных характеристик. Сам id приходит с клиента в invocation.getMetaData(). Этот id пишется в логи в каждую запись, создаваемую в рамках обработки запроса от клиента. Что, как ты сам заметил в соседней теме, очень удобно. Плюс есть ряд других контекстов, расширяющих дефолтовый, для обработки специфических запросов. Если тебя смущают интерсепторы, то можно просто создавать/уничтожать те же самые ThreadLocal контексты руками в точке входа запроса. Если таких точек немного, то и такой вариант прокатит. Но, ИМХО, вот это уже точно сложнее отслеживать, чем в предлагаемом мною решении. У нас есть один use-case, где жизненный цикл контекста контролируется явным образом в SFSB - но там такая специфика, что он должен жить именно всё время жизни SFSB. Да и там для обработки клиентского запроса стартует множество потоков, в каждом из этих потоков в threadLocal устанавливается ссылка на этот контекст (тоже прозрачным способом, используя наше расширение ThreadPoolExecutor) - и каждый поток складывает результаты работы в этот контекст. Так что слова про затычку мне не понятны. Постановка задачи у тебя - добавить одинаковую обработку для всех клиентских запросов - а ведь интерсепторы именно для этих целей и используются в jboss. И, кстати, реализованы именно через AOP ![]() |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |