Использование ThreadLocal в корпоративном приложении

Если мое веб-приложение и приложение ejb находятся на одном компьютере (на одной JVM) и все вызовы ejb являются локальными вызовами, не создаст ли использование ThreadLocal каких-либо проблем при передаче информации из Интернета в ejb?

Любое обходное решение, если вызовы ejb удалены? Будет ли информация ThreadLocal доступна из веб-приложения в приложение ejb? Целесообразно ли использование ThreadLocal в таком сценарии?


person Snake Eye    schedule 26.04.2012    source источник


Ответы (7)


Для первого вопроса нет проблем, если вы удаляете переменные ThreadLocal в конце каждого вызова. Это важно, потому что контейнеры (сервлет или ejb) обычно используют пулы потоков и, следовательно, повторно используют потоки, это имеет два эффекта: один «вызов» может видеть информацию о потоке, поступающую от предыдущего вызова, и если вы удаляете приложение из контейнера без остановки JVM некоторые классы могут не подвергаться сборке мусора, поскольку на них по-прежнему ссылается поток контейнера. Поэтому поместите данные в threadlocal в блоке try/finally и удалите в части finally.

Вот сообщение, показывающее один из способов решения проблемы: ThreadLocal в веб-приложениях

Что касается второго вопроса, поскольку данные являются локальными для потоков, они не будут выполняться с удаленным вызовом, вам нужно добавить параметр в свои интерфейсы, извлечь локальные данные для потоков с одной стороны и воссоздать их с другой стороны...

person pgras    schedule 26.04.2012
comment
Спасибо. В основном я добавляю многоязычные возможности в существующее приложение ee без необходимости изменять большую часть кода. Я буду устанавливать информацию о языке в сеансе HTTP, а затем использовать эту информацию в сеансе HTTP для установки значения в «ThreadLocal». Поэтому нужно будет определить место в приложении (возможно, HTTPFilter), которое вызывается перед каждым запросом, и установить значение в `ThreadLocal' из HTTPSession. Это обеспечит его доступность в EJB, который в конечном итоге будет передан в качестве параметра базы данных. - person Snake Eye; 26.04.2012
comment
Это гарантирует, что даже если я не удалю его, он будет перезаписываться каждый раз. Спасибо за Ваш ответ. - person Snake Eye; 26.04.2012

При использовании EJB 3.1 вы можете передавать контекстную информацию в EJBContext с использованием его контекстных данных. Это всего лишь Map<String,Object>.

person SpaceTrucker    schedule 30.01.2013

ThreadLocal не следует использовать в контексте EJB. Нельзя гарантировать, что все вызовы методов EJB находятся в одном и том же потоке (конечно, так и должно быть).

В EJB используется другой подход, называемый TransactionSyncrhonizationRegistry. См. Объяснение/Использование для получения дополнительной информации.

person Soccertrash    schedule 03.05.2013

все вызовы ejb являются локальными вызовами, создаст ли использование ThreadLocal какие-либо проблемы, в то время как

Нет, вы сами ответили на свой вопрос. Поскольку вызовы являются локальными, они выполняются в контексте одного потока.

Любое обходное решение, если вызовы ejb удалены?

В случае удаленных вызовов контейнер Java EE будет запущен в другой JVM, он будет порождать свои собственные потоки для обработки входящего запроса RMI, удаленный контейнер Java EE не может знать о локальных переменных потока, которые были объявлены на Обратная сторона. Передайте его как объект параметра.

person Anton    schedule 26.04.2012

Это зависит от того, какую информацию вы передаете! Первый вопрос слишком общий. Я предлагаю прочитать JavaDoc, связанный с ThreadLocal здесь.

ThreadLocal живет на стороне сервера приложения и используется для того, чтобы обеспечить безопасность вызовов ваших объектов Thread.

person JeanValjean    schedule 26.04.2012
comment
Javadoc ThreadLocal будет недостаточно. Вы точно не знаете, как сервер будет управлять потоками, привязывать их к запросам и т.д. - person ymajoros; 13.08.2014

Для локальных вызовов ThreadLocal должен работать нормально, если все выполняется в одном потоке.

Для удаленных вызовов, которые потенциально могут выполняться на другом сервере, вам нужно будет придумать что-то еще. Либо передайте все значения в качестве параметров (что будет работать, но усложнит код), либо используйте что-то вроде распределенного кеша, например. Hazelcast, который будет функционировать как глобальный HashMap, к которому имеют доступ все узлы кластера.

person nwinkler    schedule 26.04.2012

ThreadLocal нельзя использовать со 100% уверенностью в веб-приложениях. У вас просто нет гарантии, что один поток будет использоваться для одного сеанса. С моей точки зрения, это может стать очень трудно найти дыру в безопасности!

ctx.getContextData() у меня не работает, всегда возвращает null!

Я также пробовал TransactionSynchronizationRegistry, но также получаю null.

Единственное, что сработало, это использование JAAS в качестве обходного пути. Но это не очень хорошее решение.

person lyuboe    schedule 03.03.2014