Właściwie powiedziałbym, że odsłuchiwanie JMS jest prawdopodobnie najlepszym powodem dla serwera aplikacji. Autonomiczny broker komunikatów nie naprawia problemu, ponieważ wciąż potrzebujesz komponentu, który nasłuchuje wiadomości. Najlepszym sposobem na to jest użycie MDB. Teoretycznie możesz użyć Springs MessageListenerContainer. Ma to jednak kilka wad, takich jak JMS, który obsługuje tylko blokowanie odczytów, dlatego też Spring musi rozpoczynać własne wątki, które jest całkowicie nieobsługiwane (nawet w Tomcata) i może przerwać transakcje, bezpieczeństwo, nazewnictwo (JNDI) i ładowanie klasy (co z kolei może się zepsuć remoting). Adapter zasobów JCA może wykonywać dowolne czynności, w tym wirowanie wątków za pośrednictwem WorkManager. Prawdopodobnie baza danych jest używana poza JMS (lub innym miejscem docelowym), w którym to momencie potrzebne są transakcje XA i JTA, czyli serwer aplikacji. Tak, możesz załączyć to do kontenera serwletów, ale w tym punkcie staje się on nie do odróżnienia od serwera aplikacji.
IMHO największym powodem przeciwko serwerom aplikacji jest to, że zajmuje lata po opublikowaniu specyfikacji (co z kolei trwa również lata), dopóki severs nie wdroży specyfikacji i wyeliminuje najgorsze błędy. Dopiero teraz, tuż przed publikacją EE 7, mamy do czynienia z serwerami EE 6, które nie są całkowicie przepełnione błędami. Staje się to komiczne do punktu, w którym niektórzy dostawcy nie naprawiają błędów w linii EE 6, ponieważ są już zajęci nadchodzącą linią EE 7.
Edit
Długie wyjaśnienie ostatniego akapitu:
Java EE w wielu miejscach powołuje się na to, co się nazywa informacje kontekstowe. Informacje, które nie są jawnie przekazywane jako argumenty z serwera/kontenera do aplikacji, ale niejawnie "tam". Na przykład bieżący użytkownik do kontroli bezpieczeństwa. Bieżąca transakcja lub połączenie. Obecna aplikacja do wyszukiwania klas, aby leniwie załadować kod lub deserializować obiekty. Lub bieżący komponent (serwlet, EJB, ...) do wykonywania wyszukiwań JNDI. Wszystkie te informacje znajdują się w lokalnych wątkach, które serwer/kontener ustawia przed wywołaniem komponentu (serwlet, EJB, ...). Jeśli utworzysz własne wątki, serwer/kontener nie będzie o nich wiedział, a wszystkie funkcje polegające na tych informacjach przestaną działać. Możesz tego uniknąć, po prostu nie używając żadnej z tych funkcji w wątkach, które spawnujesz.
Niektóre linki
http://www.oracle.com/technetwork/java/restrictions-142267.html#threads http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html#spring-4
Jeśli sprawdzamy specyfikacji Servlet 3.0 znajdziemy:
2.3.3.3 asynchroniczne przetwarzanie
Java Enterprise Edition, takie jak sekcja 15.2 .2, "Środowisko aplikacji internetowych" na stronie 15-174 i rozdział 15.3.1, "Propagowanie Secu Tożsamość rity w wywołaniach EJBTM "na stronie 15-176 są dostępne tylko dla wątków wykonujących początkowe żądanie lub gdy żądanie jest wysyłane do kontenera za pomocą metody AsyncContext.dispatch. Funkcje Java Enterprise Edition mogą być dostępne dla innych wątków działających bezpośrednio na obiekcie odpowiedzi za pomocą metody AsyncContext.start (Runnable).
Chodzi o asynchronicznego przetwarzania, ale te same ograniczenia dotyczą niestandardowych wątków.
publiczny początek nieważności (Runnable r) - ta metoda powoduje, że kontener wywołuje wątek, prawdopodobnie z zarządzanej puli wątków, aby uruchomić określony runnable. Kontener może propagować odpowiednie informacje kontekstowe do Runnable.
Ponownie, przetwarzanie asynchroniczne, ale te same ograniczenia dotyczą niestandardowych wątków. Zastosowanie Środowisko
15.2.2 Web
Ten rodzaj kontenera serwletów powinny wspierać ten problem, gdy wykonywane na wątków utworzonych przez autora, ale obecnie nie są do tego zobowiązane. Taki wymóg zostanie dodany w następnej wersji tej specyfikacji. Programiści ostrzegają, że w zależności od tej możliwości wątków tworzonych przez aplikacje nie jest zalecane, ponieważ nie są przenośne.
Nie przenośny oznacza, że może na jednym serwerze, ale nie w innym.
Gdy chcesz otrzymują wiadomości z JMS poza MDB można użyć cztery metody na javax.jms.MessageConsumer
:
#receiveNoWait()
co możliwe, aby ten w wątku pojemnika, nie blokuje, ale to jak wystającym . Jeśli nie ma komunikatu, po prostu zwraca null
. To nie jest zbyt dobrze dostosowane do słuchania wiadomości.
#receive(long)
można to zrobić w wątku kontenera, blokuje się. Zazwyczaj nie należy wykonywać blokowania w wątku kontenera. Znowu niezbyt dobrze nadaje się do słuchania wiadomości.
#receive()
, blokuje to prawdopodobnie w nieskończoność. Znowu niezbyt dobrze nadaje się do słuchania wiadomości.
#setMessageListener()
to jest to, co chcesz, twój oddzwani, gdy nadejdzie wiadomość. Jednak chyba, że biblioteka może podłączyć się do serwera aplikacji, nie będzie to wątek kontenera. Haki do serwera aplikacji są dostępne tylko przez JCA dla adapterów zasobów.
Tak, może zadziałać, ale nie jest gwarantowane i istnieje wiele rzeczy, które mogą się zepsuć.
'to jednak ma kilka wad jak JMS obsługuje tylko blokowanie czyta i dlatego Wiosna musi kręcić się swoje własne wątki, które jest całkowicie nieobsługiwane (nawet w Tomcat) i może złamać transakcji, bezpieczeństwo, nazywanie (JNDI) i ładowanie klasy (co z kolei może przerwać zdalne uruchamianie). "Czy możesz mi pokazać, gdzie to znalazłeś? Jestem pewien, że niektórzy ludzie używają Spring z niezależnym brokerem wiadomości bez App Server. Próbuję znaleźć, czy ktoś poruszył ten problem w dowolnym miejscu. Nie mówię, że się mylicie! :-) Próbuje uzyskać lepszy wgląd. –