На самом деле, я бы сказал, что прослушивание JMS, вероятно, является лучшей причиной для сервера приложений. Автономный брокер сообщений не устраняет проблему, так как вам по-прежнему нужен компонент, который прослушивает сообщения. Лучший способ сделать это - использовать MDB. В теории вы можете использовать Springs MessageListenerContainer. Однако у этого есть несколько недостатков, таких как JMS, только поддерживает блокирование чтения, а Spring поэтому необходимо развернуть свои собственные потоки, которые полностью не поддерживаются (даже в Tomcat) и могут прерывать транзакции, безопасность, именование (JNDI) и загрузку классов (что, в свою очередь, может сломаться Remoting). Адаптер ресурсов JCA может делать все, что захочет, включая разворот потоков через WorkManager. Вероятно, база данных используется помимо JMS (или другого адресата), в этот момент вам нужны XA-транзакции и JTA, другими словами сервер приложений. Да, вы можете исправить это в контейнере сервлетов, но эта точка становится неотличимой от сервера приложений.
IMHO самая большая причина для серверов приложений заключается в том, что требуется много лет после публикации спецификации (которая также требует много лет), пока severs не реализуют спецификацию и не сгладили худшие ошибки. Только сейчас, прямо перед публикацией EE 7, мы начинаем появляться серверы EE 6, которые не полностью пронизаны ошибками. Это становится смешно, когда некоторые производители больше не исправляют ошибки в своей линии EE 6, потому что они уже заняты предстоящей линией EE 7.
Редактировать
Задолго объяснение последнего пункта:
Java EE во многих местах полагается на то, что называется контекстной информацией. Информация, которая явно не передается в качестве аргумента от сервера/контейнера к приложению, но неявно «там». Например, текущий пользователь для проверки безопасности. Текущая транзакция или соединение. Текущее приложение для поиска классов для ленивой загрузки кода или десериализации объектов. Или текущий компонент (сервлет, EJB, ...) для просмотра JNDI. Вся эта информация находится в локаторах потоков, которые сервер/контейнер устанавливает перед вызовом компонента (сервлет, EJB, ...). Если вы создаете свои собственные потоки, сервер/контейнер не знает о них, и все функции, основанные на этой информации, больше не работают. Вы можете избежать этого, просто не используя какие-либо из этих функций в нити, которые вы создаете.
Некоторые ссылки
http://www.oracle.com/technetwork/java/restrictions-142267.html#threads http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html#spring-4
Если проверить спецификацию Servlet 3.0 мы находим:
2.3.3.3 Асинхронная обработка
Java Enterprise Edition такие функции, как раздел 15.2 .2, «Окружающая среда веб-приложений» на стр. 15-174 и Раздел 15.3.1, «Распространение Secu rity Identity в вызовах EJBTM »на странице 15-176 доступны только для потоков, выполняющих первоначальный запрос, или когда запрос отправляется в контейнер через метод AsyncContext.dispatch. Функции Java Enterprise Edition могут быть доступны для других потоков, работающих непосредственно с объектом ответа с помощью метода AsyncContext.start (Runnable).
Речь идет об асинхронной обработке, но для пользовательских потоков применяются те же ограничения.
public void start (Runnable r) - Этот метод заставляет контейнер отправлять поток, возможно из пула управляемых потоков, для запуска указанного Runnable. Контейнер может распространять соответствующую контекстуальную информацию на Runnable.
Опять же, асинхронная обработка, но те же ограничения применяются к пользовательским потокам.
15.2.2 Web Application Environment
Этот тип контейнера сервлетов должен поддерживать такое поведение, когда выполняются на нитях, созданных разработчиком, но в настоящее время не требуется, чтобы сделать это. Такое требование будет добавлено в следующей версии этой спецификации. Разработчики предупреждаются, что в зависимости от этой возможности для создаваемых пользователем потоков не рекомендуется, так как она не переносима.
Non-portable означает, что он может находиться на одном сервере, но не в другом.
Если вы хотите сделать прием сообщений с JMS вне из MDB вы можете использовать четыре метода на javax.jms.MessageConsumer
:
#receiveNoWait()
вы можете на это в контейнере потока, он не блокирует, но это как выглядывает , Если сообщение отсутствует, оно просто возвращает null
. Это не очень хорошо подходит для прослушивания сообщений.
#receive(long)
вы можете это сделать в потоке контейнера, он блокирует. Обычно вам не нужно блокировать ожидания в потоке контейнера. Снова не очень хорошо подходит для прослушивания сообщений.
#receive()
, этот блок возможно бесконечно. Снова не очень хорошо подходит для прослушивания сообщений.
#setMessageListener()
Это то, что вы хотите, получите обратный вызов, когда поступит сообщение. Однако, если библиотека не может подключиться к серверу приложений, это не будет потоком контейнера. Крючки на сервере приложений доступны только через JCA для адаптеров ресурсов.
Да, это может сработать, но это не гарантируется, и есть много вещей, которые могут сломаться.
'Однако это имеет ряд недостатков, как JMS поддерживает только блокировка чтения и поэтому Spring нужно раскручивать свои собственные темы, которые полностью поддерживаются (даже в Tomcat) и могут сломаться транзакции, безопасность, именования (JNDI) и загрузки классов (что, в свою очередь, может сломать удаленный доступ). «Можете ли вы показать мне, где вы это нашли? Я уверен, что некоторые люди используют Spring с независимым брокером сообщений без App Server. Попытка найти, если кто-нибудь поднял эту проблему в любом месте. Не сказать, что ты ошибаешься! :-) Попытка получить больше информации. –