Warsjava Eclipse Demo Camp 2008 - sesja o Comet, Bayeux i HTTP Publish-Subscribe - DEMO nr VI - integracja z JMS

Niniejszy wpis jest związany z prowadzoną przeze mnie sesją podczas Warsjava Eclipse Demo Camp 2008 w Warszawie. Więcej informacji: http://jdn.pl/node/1620

VI. DEMONSTRACJA nr VI - JMS handler

Ostatnia demonstracja dotyczy funkcjonalności JMS handler'a, czyli integracji mechanizmu HTTP Publish-Subscribe z JMS. Taka integracja jest korzystna w scenariuszach, w których potrzebne jest podniesienie poziomu niezawodności (klastrowanie), a także możliwość utrzymywania trwałych subskrypcji (czyli nawet, gdy klient Bayeux nie jest aktywnie podłączony do kanału HTTP, po podłączeniu otrzyma opublikowane w czasie jego "nieobecności" komunikaty z tego kanału). Trwałe subskrypcje wymagają przechowywania komunikatów przez podsystem JMS w wybranym zasobniku (plik lub baza danych). Oprócz tego, korzystając z integracji HTTP Pub-Sub z JMS można skorzystać ze wszelkich mechanizmów JMS, tak, aby wzbogacić sposób przetwarzania komunikatów.

Pierwszą czynnością jest skonfigurowanie JMS w WebLogic Server. Konieczne będzie utworzenie serwera JMS (obsługującego kolejki i tematy - ang. queue, topics). Po tym należy utworzyć moduł JMS, w którym będą zdefiniowane: JMS Connection Factory i JMS Topic. Do tego topic'u będą publikowane komunikaty trafiające do danego kanału HTTP. W następnym kroku zostanie stworzony prosty EJB typu Message-driven Bean, nasłuchujący na tym topic'u i - po pojawieniu się komunikatu JMS w tym topic'u - (znowu) wyświetlający zawartość tego komunikatu w konsoli serwera.

Zaczynamy od konfiguracji podsystemu JMS w WebLogic Server. W tym celu należy otworzyć webową konsolę administracyjną WLS: http://[hostname]:[port]/console (u mnie: http://localhost:7001/console). Pojawi się ekran logowania. Należy wprowadzić id i hasło administratora WLS (u mnie: weblogic / weblogic):

Wyświetli się konsola administracyjna WLS:

Należy z menu po lewej stronie wybrać opcję: Services -> Messaging -> JMS Servers. Wyświetli się ekran konfiguracji serwera JMS:

Za pomocą przycisku New, należy utworzyć nowy serwer JMS. Wyświetli się ekran konfiguracji serwera JMS. Podane tutaj wartości domyślne są OK, wystarczy więc nacisnąć przycisk Next:

Serwer JMS może być "przypięty" (ang. target) do dowolnej instancji WLS. Tutaj, będzie przypięty do instancji o nazwie AdminServer. W polu Target należy wybrać tę instancję, po czym nacisnąć przycisk Finish:

Wyświetli się lista wszystkich serwerów JMS:

Aby utworzyć moduł JMS (w którym będą zdefiniowane zasoby JMS, takie jak Connection Factory, kolejki, czy tematy), należy z menu po lewej stronie wybrać opcję JMS Modules. Wyświetli się lista wszystkich modułów. Należy nacisnąć przycisk New:

Wartości domyślne są OK, należy więc nacisnąć przycisk Next:

Definiowany moduł będzie "przypięty" (ang. target) - albo inaczej zainstalowany - w instancji WLS o nazwie "AdminServer". Na wyświetlonym ekranie, należy zaznaczyć AdminServer i nacisnąć przycisk Next:

Wyświetli się ekran, z pytaniem czy do modułu będą dodawane zasoby JMS. Ponieważ będą, to należy zaznaczyć opcję Would you like to add resources to this JMS system module ?, po czym nacisnąć Finish:

Wyświetli się ekran pokazujący dostępne w module zasoby. Aby utworzyć nowy zasób, należy nacisnąć przycisk New:

Zaczniemy od stworzenia JMS Connection Factory, więc należy zaznaczyć opcję Connection Factory i nacisnąć przycisk Next:

Na kolejnym ekranie, należy podać nazwę Connection Factory (w tym nazwę JNDI). W przykładzie, obie nazwy są takie same: myConnectionFactory. Po podaniu nazwy, należy nacisnąć przycisk Next:

Na kolejnym ekranie, należy potwierdzić instancję WLS, na której zostanie osadzony obiekt Connection Factory - poprzez naciśnięcie przycisku Finish:

Ponownie wyświetli się ekran z listą zasobów w module:

Drugim zasobem, który będzie utworzony, to JMS Topic. Należy zatem nacisnąć przycisk New, a na kolejnym ekranie zaznaczyć opcję Topic i nacisnąć przycisk Next:

Podobnie, jak wcześniej, należy podać nazwę zasobu (w tym, nazwę JNDI). W obu przypadkach będzie to: myTopic. Następnie należy nacisnąć przycisk Next:

Wyświetli się ekran przypisania zasobu JMS (tutaj topic'u) do konkretnego serwera JMS. Na tym ekranie, należy nacisnąć przycisk Create a New Subdeployment:

Należy podać nazwę nowej konfiguracji: myTopic, a następnie nacisnąć przycisk OK:

Należy się upewnić, że nowoutworzona konfiguracja została wybrana w polu Subdeployments. W sekcji Targets należy także zaznaczyć wcześniej utworzony serwer JMS JMSServer-0: Po tym, należy nacisnąć przycisk Finish

Ponownie wyświetli się ekran z listą wszystkich zasobów JMS w danym module:

Konfiguracja zasobów JMS zakończona. Należy wylogować się z konsoli administracyjnej (Log Out). Można wrócić do IDE i aplikacji HTTP Publish-Subscribe.

Aby skonfigurować JMS handler dla kanału - czyli zintegrować kanał HTTP z tematem JMS (ang. topic) - należy do pliku weblogic-pubsub.xml dodać definicję JMS handler'a:

<wlps:jms-handler-mapping>
         <wlps:jms-handler-name>myJMSHandler</wlps:jms-handler-name>
         <wlps:jms-handler>
                <wlps:jms-provider-url>t3://localhost:7001</wlps:jms-provider-url>
                <wlps:connection-factory-jndi-name>myConnectionFactory</wlps:connection-factory-jndi-name>
                <wlps:topic-jndi-name>myTopic</wlps:topic-jndi-name>
         </wlps:jms-handler>
</wlps:jms-handler-mapping>

W elemencie znajduje się adres instancji WLS, zawierającej serwer JMS (adres jest w formacie: t3://[hostname]:[port]).
W elemencie znajduje się nazwa JNDI utworzonej wcześniej JMS Connection Factory.
W elemencie znajduje się nazwa JNDI utworzonego wcześniej JMS Topic (do tego topic'u będą trafiać komunikaty publikowane do kanału).

Przypisanie konkretnego JMS handlera do konkretnego kanału odbywa się za pomocą elementu . Definicja kanału w całości:

<wlps:channel>
          <wlps:channel-pattern>/warsjava08/**</wlps:channel-pattern>
          <wlps:jms-handler-name>myJMSHandler</wlps:jms-handler-name>
          <wlps:message-filter>myFilter</wlps:message-filter>
</wlps:channel>

Ostatnim krokiem jest utworzenie MDB, nasłuchującego na zdefiniowanym wcześniej JMS topic'u. W tym celu należy w projekcie EJB warsjava2008ejb, utworzyć nową klasę o nazwie myMDB, implementującą interfejs javax.jms.MessageListener.

Poniżej znajduje się kod tej klasy, z przykładową implementacją:

package pl.waldekkot.ejbs;
 
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
 
import com.bea.httppubsub.bayeux.messages.DeliverEventMessage;
import com.bea.httppubsub.json.JSONObject;
 
@MessageDriven(	mappedName = "myTopic", 
                activationConfig = { @ActivationConfigProperty(
                                     propertyName = "destinationType", 
                                     propertyValue = "javax.jms.Topic") })
public class MyMDB implements MessageListener {
 
	@Override
	public void onMessage(Message msg) {
		System.out.println("MDB: Jest komunikat !");
 
		if (msg instanceof ObjectMessage) {
			try {
			    ObjectMessage msgObject = (ObjectMessage) msg;
			    JSONObject jsonObject = new JSONObject(((DeliverEventMessage) msgObject.getObject()).getPayLoad());
 
			    System.out.println("Komunikat: " + jsonObject.getString("komunikat"));
			    System.out.println("Liczba: " + jsonObject.getString("liczba"));
 
			} catch (JMSException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

Warto zwrócić uwagę na adnotację @MessageDriven i jej atrybuty:
- mappedName - odnosi się do nazwy JNDI utworzonego wcześniej topic'u
- activationConfig zawiera dodatkowe metadane, dotyczące typu zasobu JMS, na którym "nasłuchuje" ten EJB/MDB.

That's all folks - jeszcze raz dzięki za miłe słowa podczas Warsjava 2008 :-).