2011-08-04 11 views
29

Próbuję utworzyć autonomiczną aplikację JMS do odczytu i zapisu do kolejki w MQSeries. Mój szef poprosił mnie o użycie czystego java JMS (nie ibm.mq lib), aby to zrobić.Jak używać Java JMS z MQseries

Oto informacje, które potrzebne do nawiązania połączenia JMS:

mq.hostname=10.10.10.10 
    mq.channel=API.CLIENTCHL 
    mq.queueManager=MQPETAPI 
    mq.port=1422 

Czy wiesz jak to zrobić, albo masz jakiś link, który nauczy mnie, aby to zrobić.

+1

Czy bieg kodu wewnątrz WebSphere Application Server, a następnie łączy się z WebSphere MQ do wiadomości, czy jest samodzielny aplikacja i chce się połączyć z WebSphere MQ dla przesyłanie wiadomości? –

Odpowiedz

46

problem tutaj jest wymóg, że „Mój szef poprosił mnie, aby używać czystych JMS java (nie ibm.mq lib), aby to zrobić.” JMS jest specyfikacją, a każda implementacja musi być zgodna z interfejsem API i semantyką, ale może wykonywać dowolne czynności na niskim poziomie. Zawsze należy korzystać z klas implementacji dostarczonych przez dostawcę transportu. Dlatego jeśli używasz produktu WebSphere MQ jako transportu, musisz użyć klas JMS produktu IBM MQ, aby napisać aplikację JMS.

To powiedziawszy, jeśli będziesz trzymać się czystych wywołań API JMS, będziesz mógł podłączyć wszystkie klasy dostawców transportu.Zazwyczaj ma to na celu spełnienie wymagań wymienionych w oryginalnym poście.

Jest to artykuł opisujący dokładnie to, czego szukasz nie nazywa Running a standalone Java application on WebSphere MQ V6.0 Używa tylko API JMS i używa JNDI w lokalnym systemie plików (pliki .bindings). Wymieniając klasy IBM JMS na innego dostawcę i wykorzystując narzędzia JNDI, można podłączyć dowolny transport JMS bez zmiany kodu za pomocą tego podejścia.

Jeśli chcesz zrobić to samo bez JNDI, spójrz na przykładowe programy dostarczone z instalacją klienta MQ, w której uzyskałeś klasy Java. W systemie UNIX/Linux są one w /opt/mqm/samp, a na Windowsie są w install_dir/tools/jms/samples. Próbka SimpleRequestor.java ma następujący kod dla inicjowania swoją fabrykę połączeń bez JNDI:

try { 
    // Create a connection factory 
    JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER); 
    JmsConnectionFactory cf = ff.createConnectionFactory(); 

    // Set the properties 
    cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, "localhost"); 
    cf.setIntProperty(WMQConstants.WMQ_PORT, 1414); 
    cf.setStringProperty(WMQConstants.WMQ_CHANNEL, "SYSTEM.DEF.SVRCONN"); 
    cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT); 
    cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, "QM1"); 

Ponieważ takie podejście nie używa JNDI, które są wymagane do pisania kodu, który nie jest w transporcie różnych dostawców transportowych. Jest to specyfikacja produktu IBM WebSphere MQ.

Jeśli przyjąłeś słoiki MQ skądś i nie masz pełnej instalacji (a więc nie masz próbek), możesz pobrać go jako SupportPac MQC7. Pobieranie jest bezpłatne. Zasadniczo należy używać najnowszego klienta, nawet z menedżerem kolejek na poziomie podstawowym. Oczywiście nie można uzyskać funkcjonalności V7 z wersji V6 QMgr, ale implementacja JMS w kliencie V7 jest znacznie ulepszona, nawet w przypadku funkcji V6. Jeśli z jakiegoś powodu naprawdę musisz użyć klienta V6, możesz pobrać go jako SupportPacMQC6. Niezależnie od używanej wersji klienta, upewnij się, że korzystasz z odpowiedniego centrum informacyjnego.

V6 Infocenter
V7 Infocenter

Wreszcie strona docelowa z indeksem dla wszystkich SupportPacs jest here.

+1

"Dlatego jeśli używasz WebSphere MQ jako transportu, musisz użyć klas JMS IBM MQ, aby napisać aplikację JMS." Wierzę, że jest to prawdą tylko wtedy, gdy pracujesz bezpośrednio z MQ. Jeśli jesteś wyodrębniany za pośrednictwem kontenera, takiego jak WebSphere Application Server, możesz faktycznie napisać kod "czystego JMS", ponieważ kontener aplikacji dba o to, abyś pracował z MQ tak samo, jakbyś pracował z implementacją SIBus. Wszystko, co musisz zrobić, to upewnić się, że Twoje kolejki MQ są zdefiniowane jako JMS "Kolejki" i że masz QueueConnectionFactory (z interfejsem tak, jakby był to ConnectionFactory). –

+2

To interesujący taniec semantyczny.Klasy JMS dostawcy usług transportowych * znajdują się * w zmiennej CLASSPATH w ten czy w inny sposób. W tym przykładzie serwer JEE udostępnia kontener, w którym są dostępne biblioteki JMS produktu IBM MQ. Ale tak czy inaczej, aplikacja nadal używa tych konkretnych klas * i może uzyskać dostęp do swoich specyficznych dla dostawcy metod *. Nie jest tak, że serwer JEE w jakiś sposób ukrywa implementację dostawcy z aplikacji, więc wydaje mi się to bezsensownym rozróżnieniem. OP również określił autonomiczną aplikację JMS, więc i tak nie ma w tym scenariuszu żadnego kontenera JEE. –

+0

Dziękuję wszystkim, którzy poświęcili czas na moje pytanie. Specjalnie dla T.Rob – David

0

Jest to dość powszechne. Here to tylko niektóre przykłady.

+0

Thnaks. Jak mogę umieścić (nazwa hosta, kanał, port, queueManager) w połączeniu obj? – David

+0

@David: Nie możesz. JMS wymaga do tego celu JNDI. –

+1

@ Cosmic.osmo - Zobacz inne odpowiedzi na przykładach, jak ustawić właściwości obiektu CF bez JNDI. JMS pozostawia to dostawcy usług transportowych, aby dokładnie określić, jakie właściwości ustawić i jakie wartości użyć. Specyfikacja JMS nie zezwala na to ani nie egzekwuje w żaden sposób, że musi się to odbywać za pośrednictwem JNDI. –

2

Zazwyczaj z JMS definiowałeś QueueConnectionFactory w swoim kontenerze za pomocą dowolnego mechanizmu konfiguracji, który udostępnia, a następnie dodajesz go do rejestru JNDI kontenera. Każdy kontener miałby własne metody (np. Tomcat lub WebSphere).

Jeśli chcesz zrezygnować z JNDI, możesz bezpośrednio utworzyć instancję o numerze com.ibm.mq.jms.MQQueueConnectionFactory i ustawić na niej nazwę hosta, port, kolejkę menedżera i właściwości kanału. Następnie możesz użyć tego obiektu tak, jakbyś wykonał instancję javax.jms.QueueConnectionFactory od momentu jego implementacji.

8

Jeśli nie przeszkadza pisanie kodu WMQ specyficzne wtedy można zrobić

MQConnectionFactory cf = new MQConnectionFactory(); 
cf.setHostName(HOSTNAME); 
cf.setPort(PORT); 
cf.setChannel(CHANNEL); 
cf.setQueueManager(QMNAME); 
cf.setTransportType(WMQConstants.WMQ_CM_CLIENT); 

następnie zwykłe zasoby JMS

Connection c = cf.createConnection(); 
Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE); 
Queue q = s.createQueue("myQueue"); // replace with real queue name 
MessageProducer p = s.createProducer(q); 

i wreszcie utworzyć i wysłać wiadomość

Message m = s.createTextMessage("Hello, World!); 
p.send(m); 

(wpisałem to z góry mojej głowy, więc nie mogę wykluczyć literówki, ale jest to zasadniczo poprawne). Jeśli naprawdę powinieneś używać "czystego JMS" - tzn. Bez obiektów specyficznych dla dostawcy - musisz powiązać obiekt MQConnectionFactory w JNDI (spójrz na narzędzie JMSAdmin, jest ono w dokumentach), a następnie sprawdź je z aplikacji, tj

InitialContext ic = new InitialContext(); // or as appropraite 
ConnectionFactory cf = (ConnectionFactory)ic.lookup("myMQfactory"); // replace with JNDI name 
8

Kompletna (synchroniczna) samodzielna aplikacja JMS z funkcją TextMessage.
Jest to specyfikacja produktu IBM WebSphere MQ.

import javax.jms.DeliveryMode; 
import javax.jms.JMSException; 
import javax.jms.Message; 
import javax.jms.Queue; 
import javax.jms.QueueConnection; 
import javax.jms.QueueReceiver; 
import javax.jms.QueueSender; 
import javax.jms.QueueSession; 
import javax.jms.Session; 
import javax.jms.TextMessage; 

import com.ibm.mq.jms.JMSC; 
import com.ibm.mq.jms.MQQueueConnectionFactory; 

public class JMSApplicationStandAlone { 
    public static void main(String[] args) { 
     try { 
      /*MQ Configuration*/ 
      MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory(); 
      mqQueueConnectionFactory.setHostName("localhost"); 
      mqQueueConnectionFactory.setChannel("MQ.CHANNEL");//communications link 
      mqQueueConnectionFactory.setPort(1416); 
      mqQueueConnectionFactory.setQueueManager("QUEUE.MGR");//service provider 
      mqQueueConnectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP); 

      /*Create Connection */ 
      QueueConnection queueConnection = mqQueueConnectionFactory.createQueueConnection(); 
      queueConnection.start(); 

      /*Create session */ 
      QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); 

      /*Create response queue */ 
      Queue queue = queueSession.createQueue("QUEUE.RESPONSE"); 


      /*Create text message */ 
      TextMessage textMessage = queueSession.createTextMessage("put some message here"); 
      textMessage.setJMSReplyTo(queue); 
      textMessage.setJMSType("mcd://xmlns");//message type 
      textMessage.setJMSExpiration(2*1000);//message expiration 
      textMessage.setJMSDeliveryMode(DeliveryMode.PERSISTENT); //message delivery mode either persistent or non-persistemnt 

      /*Create sender queue */ 
      QueueSender queueSender = queueSession.createSender(queueSession.createQueue("QUEUE.REQEST")); 
      queueSender.setTimeToLive(2*1000); 
      queueSender.send(textMessage); 

      /*After sending a message we get message id */ 
      System.out.println("after sending a message we get message id "+ textMessage.getJMSMessageID()); 
      String jmsCorrelationID = " JMSCorrelationID = '" + textMessage.getJMSMessageID() + "'"; 


      /*Within the session we have to create queue reciver */ 
      QueueReceiver queueReceiver = queueSession.createReceiver(queue,jmsCorrelationID); 


      /*Receive the message from*/ 
      Message message = queueReceiver.receive(60*1000); 
      String responseMsg = ((TextMessage) message).getText(); 

      queueSender.close(); 
      queueReceiver.close(); 
      queueSession.close(); 
      queueConnection.close(); 


     } catch (JMSException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Uwaga: Wymień wartości konfiguracja

+0

Dzięki. Pomogło mi to, gdy próbowałem kawałka kodu łączącego się z IBM MQ. –