410013796724260
• Webmoney
R335386147728
Z369087728698
Отправка и чтение JMS сообщенийВ предыдущей статье был рассмотрен пример отправки и получения JMS сообщений в WEB приложении с контейнером JBoss. В качестве провайдера обслуживания очередей javax.jms.Queue был использован HornetQ, интегрированный в контейнер. Данная статья продолжает рассмотрение вопроса отправки и получения JMS сообщений из Java приложения; в качестве провайдера очередей MQ (Message Queue) будет использоваться Websphere MQ. Websphere MQ не является предметом описания статьи. Данное программное обеспечение играет вспомогательную роль и ему будет отведено минимальное внимание. Если Вы не знакомы с Websphere MQ, но желаете освоить данное ПО или работу с JMS сообщениями, то можете установить пробную 90-дневную trial версию с официального сайта IBM. Данного времени вполне достаточно для освоения технологии работы с JMS-сообщениями. Для работы с JMS сообщениями создадим три класса :
Отличия двух последних классов JmsBrowser и JmsConsumer связаны с тем, что если первый будет только читать сообщения из очереди, то второй класс будет читать сообщения вместе с их удалением из очереди. В классы включим методы main, чтобы можно было бы не на словах, а на деле увидеть отправку и получение JMS сообщений. Кроме этого, JMS сообщение будет выведено в консоль, чтобы наглядно представить значимые атрибуты класса javax.jms.Message. При разработке классов упростим себе жизнь и используем один из основных принципов ООП наследование. Для этого разработаем базовый класс JmsBase, в котором определим настройки канала подключения javax.jms.Connection, а классы издателя и просмоторщиков будут наследовать JmsBase. В результате бизнес-логика будет разделена на две части : родитель будет отвечать за подключение к провайдеру JMS очередей, а наследники будут реализовывать определенные им функции. Листинг базового модуля JmsBaseБазовый класс JmsBase, как было отмечено выше, отвечает за подключение к провайдеру Websphere MQ. Создадим в JmsBase метод подключения createConnection и абстрактный класс doAction, обязательный для определения в наследниках. В качестве параметров подключения используются наименование и порт компьютера (host, port), наименования менеджера очередей (queueManagerName) и очередь (queueName). Подключение javax.jms.Connection настраивается на менеджера очередей 'host1/qm1' и очередь 'queue1'. В конструкторе класса создается подключение javax.jms.Connection и вызывается метод doAction. Таким образом, в наследниках потребуется только соответствующим образом реализовать предначертанные им функции. На скриншоте представлен фрагмент интерфейса приложения MQExplorer с открытым окном просмотра сообщений очереди. MQExplorer включен в дистрибутив Websphere MQ.
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.Connection;
import javax.jms.JMSException;
import com.ibm.msg.client.wmq.WMQConstants;
import com.ibm.msg.client.jms.JmsFactoryFactory;
import com.ibm.msg.client.jms.JmsConnectionFactory;
public abstract class JmsBase
{
private String host = "localhost" ;
private int port = 1414 ;
private String channel = "SYSTEM.DEF.SVRCONN";
private String queueManagerName = "host1/qm1" ;
private String queueName = "queue1" ;
private boolean clientTransport = false ;
protected Session session = null;
protected Queue destination = null;
protected Connection connection = null;
// статус выполнения приложения
protected static int status = 1;
protected abstract void doAction();
//---------------------------------------------------------------
private void createConnection()
{
JmsFactoryFactory ff;
JmsConnectionFactory cf;
try {
ff = JmsFactoryFactory.getInstance(
WMQConstants.WMQ_PROVIDER);
cf = ff.createConnectionFactory();
// Set the properties
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, host );
cf.setIntProperty (WMQConstants.WMQ_PORT , port );
cf.setStringProperty(WMQConstants.WMQ_CHANNEL , channel);
if (clientTransport) {
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE,
WMQConstants.WMQ_CM_CLIENT);
} else {
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE,
WMQConstants.WMQ_CM_BINDINGS);
}
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER,
queueManagerName);
connection = cf.createConnection();
} catch (JMSException jmsex) {
recordFailure(jmsex);
}
}
//---------------------------------------------------------------
public JmsBase()
{
try {
createConnection();
session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(queueName);
// Старт подключения
connection.start();
// Выполнение действий
doAction();
}
catch (JMSException jmsex) {
recordFailure(jmsex);
} finally {
try {
if (session != null)
session.close();
if (connection != null)
connection.close();
} catch (JMSException jmsex) {
System.err.println("" + jmsex.getMessage());
recordFailure(jmsex);
}
}
}
//---------------------------------------------------------------
protected void recordFailure(Exception ex)
{
// ...
}
//---------------------------------------------------------------
protected void processJMSException(JMSException jmse)
{
// ...
}
}
Код процедур обработки исключений на странице не приводится. Желающие могут скачать рабочие примеры. Листинг издателя сообщений JmsProducerКласс издателя JMS сообщений наследует все свойства родителя JmsBase и определяет процедуру doAction(), в которой выполняется отправка сообщений провайдеру Websphere MQ. В конструкторе класса выполняется подключение к провайдеру MQ, после чего в процедуре doAction() формируется список сообщений messages и создается издатель сообщений producer типа MessageProducer. Для создания MessageProducer используется метод createProducer объекта сессии javax.jms.Session с параметром очереди destination (javax.jms.Queue). Если издатель создан, т.е. имеется канал связи и исключений не было, то в цикле вызывается метод send (TextMessage) для отправки двух сообщений.
import javax.jms.TextMessage;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
public class JmsProducer extends JmsBase
{
private MessageProducer producer = null;
public JmsProducer()
{
super();
try {
if (producer != null)
producer.close();
} catch (JMSException jmse) {
recordFailure(jmse);
}
}
@Override
protected void doAction()
{
// Создание текстовых сообщений
String[] messages = new String[2];
messages[0] = "Good day";
messages[1] = "Hello, world!";
String TEMPL = "Cообщение #%d отправлено";
try {
producer = session.createProducer(destination);
System.out.println("Отправка JMS сообщений\n");
TextMessage message = null;
for (int i = 0; i < messages.length; i++) {
message = session.createTextMessage(messages[i]);
producer.send(message);
System.out.println(String.format(TEMPL, (i + 1)));
}
} catch (JMSException e) {
status = -2;
recordFailure(e);
}
}
public static void main(String[] args)
{
new JmsProducer();
System.exit(status);
}
}
Класс издателя сообщений JmsProducer включает метод main, позволяющий протестировать отправку JMS сообщений. В результате работы класса в консоль будет выведена следующая информация об отправке сообщений. Отправка JMS сообщений Cообщение #1 отправлено Cообщение #2 отправлено На следующем скриншоте представлено окно просмотра сообщений в приложении MQExplorer : в дереве объектов слева выделены Очереди менеджера 'host1/qm1', в панели данных справа выделена очередь 'queue1'. Их перекрывает окно Просмотра сообщений в очереди, в котором отображены отправленные сообщения.
Листинг просмоторщика сообщений JmsBrowserКласс просмоторщика JMS сообщений JmsBrowser наследует все свойства родителя JmsBase и определяет процедуру doAction(). В конструкторе класса выполняется подключение к провайдеру MQ, после чего в процедуре doAction() создается объект просмотра сообщений browser типа QueueBrowser и выполняется чтение сообщений messages. Сообщения выводятся в консоль и выполнение процедуры завершается. Все тривиально просто и прозрачно.
import javax.jms.Message;
import javax.jms.JMSException;
import javax.jms.QueueBrowser;
import java.util.Enumeration;
public class JmsBrowser extends JmsBase
{
private QueueBrowser browser = null;
public JmsBrowser()
{
super();
try {
if (browser != null)
browser.close();
} catch (JMSException jmsex) {
recordFailure(jmsex);
}
}
@Override
protected void doAction()
{
try {
browser = session.createBrowser(destination);
// Чтение сообщений
Enumeration<?> messages = browser.getEnumeration();
int count = 0;
Message message;
// Просмотр сообщений
System.out.println("Просмотр JMS сообщений : ");
while (messages.hasMoreElements()) {
message = (Message) messages.nextElement();
System.out.println("\nСообщение " + (++count) + " :");
System.out.println(message);
}
System.out.println("\nПросмотр JMS сообщений завершен\n");
} catch (JMSException e) {
e.printStackTrace();
}
}
public static void main(String[] args)
{
new JmsBrowser ();
System.exit(status);
}
}
Класс включает метод main, позволяющий протестировать чтение JMS сообщений. В результате выполнения класса в консоль будут выведены два сообщения, отправленные из JmsProducer. Вы можете оценить количество атрибутов JMS сообщения. В последней строке представлен текст сообщения.
Просмотр JMS сообщений :
Сообщение 1 :
JMSMessage class: jms_text
JMSType: null
JMSDeliveryMode: 1
JMSDeliveryDelay: 0
JMSDeliveryTime: 0
JMSExpiration: 0
JMSPriority: 0
JMSMessageID: ID:414d5120686f7374312f716d31202020cf428c5922ed5a02
JMSTimestamp: 1502364406670
JMSCorrelationID: null
JMSDestination: null
JMSReplyTo: null
JMSRedelivered: false
JMSXAppID: \IBM\MQ\bin64\MQExplorer.exe
JMSXDeliveryCount: 1
JMSXUserID: Serg
JMS_IBM_Character_Set: UTF-8
JMS_IBM_Encoding: 546
JMS_IBM_Format: MQSTR
JMS_IBM_MsgType: 8
JMS_IBM_PutApplType: 11
JMS_IBM_PutDate: 20170810
JMS_IBM_PutTime: 11264667
Good day
Сообщение 2 :
JMSMessage class: jms_text
JMSType: null
JMSDeliveryMode: 1
JMSDeliveryDelay: 0
JMSDeliveryTime: 0
JMSExpiration: 0
JMSPriority: 0
JMSMessageID: ID:414d5120686f7374312f716d31202020cf428c5922ed5b02
JMSTimestamp: 1502364423160
JMSCorrelationID: null
JMSDestination: null
JMSReplyTo: null
JMSRedelivered: false
JMSXAppID: \IBM\MQ\bin64\MQExplorer.exe
JMSXDeliveryCount: 1
JMSXUserID: Serg
JMS_IBM_Character_Set: UTF-8
JMS_IBM_Encoding: 546
JMS_IBM_Format: MQSTR
JMS_IBM_MsgType: 8
JMS_IBM_PutApplType: 11
JMS_IBM_PutDate: 20170810
JMS_IBM_PutTime: 11270316
Hello, world!
Просмотр JMS сообщений завершен
Листинг просмоторщика сообщений JmsConsumerКласс просмоторщика JMS сообщений JmsConsumer также, как и предыдущие классы, наследует все свойства родителя JmsBase и определяет процедуру doAction(). В конструкторе класса также выполняется подключение к провайдеру MQ, после чего в процедуре doAction() создается объект чтения сообщений consumer типа MessageConsumer. Для чтения сообщений используется метод receive, который читает сообщение из очереди с удалением. В качестве параметра методу передается время ожидания в милисекундах. Сообщения выводятся в консоль и выполнение процедуры завершается по истечении установленного в timeout времени.
import javax.jms.Message;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
public class JmsConsumer extends JmsBase
{
private final int timeout = 30000;
private MessageConsumer consumer = null;
@Override
protected void doAction()
{
Message message;
try {
consumer = session.createConsumer(destination);
do {
message = consumer.receive(timeout);
if (message != null)
System.out.println("\nСообщение :\n" + message);
} while (message != null);
} catch (JMSException e) {
e.printStackTrace();
}
System.out.println("\nПросмотр JMS сообщений завершен\n");
}
public JmsConsumer()
{
super();
try {
if (consumer != null)
consumer.close();
} catch (JMSException jmsex) {
recordFailure(jmsex);
}
}
public static void main(String[] args)
{
new JmsConsumer();
System.exit(status);
}
}
В результате выполнения JmsConsumer в консоли будут также представлены JMS сообщения, как и в предыдущем JmsBrowser. Если Вы имеете доступ к провайдеру JMS очередей, то можете убедиться, что сообщения из очереди удалены. Скачать примерыИсходные коды рассмотренных классов в виде проекта Eclipse можно скачать здесь (7.42 Мб). Дистрибутив рабочий и включает весь необходимый набор библиотек. Пример WEB-приложения отправки и чтения JMS-сообщений из контейнера JBoss представлен здесь. |
