IT • archiv

rus / eng | Логин | Комментарий к колонке | Печать | Почта | Клуб




Колонки


Введение в JMS

 
(Алексей Букавнев)

Предисловие

Данная статья предназначена, как это следует из названия, для первичного ознакомления с одной из ключевых технологий J2EE, Java Message Service (JMS).

К сожалению, устоявшейся русской терминологии J2EE не существует. Да и та неустоявшаяся, что существует, далека от идеала. Мне, например, очень не нравится, когда Session Beanназывают Сессионным Бином. Ну уж если он "Сессионный", то почему "Бин", а не "Зерно"?

По этой причине автор будет использовать англоязычную оригинальную терминологию. Тем более что за время своего проживания и работы в Штатах он, к сожалению, основательно подзабыл орфографию и пунктуацию русского языка.

Статья нисколько не претендует на полноту освещения темы – для этого существует достаточно большое количество литературы, в том числе и доступной online.

Недостатки традиционных распределенных систем

Традиционные распределенные системы, построенные на основе RMI, обладают рядом существенных недостатков. Назовем основные:

Клиент, сделав запрос, должен ждать ответа от сервера. Эта синхронность является основным недостатком традиционных систем в том случае, когда процесс обработки запроса занимает относительно большой промежуток времени. Примитивтые псевдо-асинхронные механизмы типа callback не в счет.

И клиент, и сервер должны быть стартованы в сети. Если клиент попытается сделать запрос к серверу, который не активен в данный момент, он получит сообщение об ошибке.

Невозможно перенести серверное приложение с одного хоста на другой в runtime.

Лучше дела обстоят с CORBA. Используя CORBA Event Service или его расширение CORBA Notification Service, вы можете осуществлять эффективное асинхронное взаимодействие внутри системы. Но есть одно "НО". Производители CORBA middleware, в том числе и два лидера (Borland и Iona), предоставляют лишь рудиментарный Event Service. Полноценный Event и Notification Services необходимо приобретать у third-party производителей. Например, великолепный продукт OpenFusion от Prism Technologies, в котором реализованы все CORBA-сервисы (за мой достаточно большой практический опыт разработки CORBA-систем мне доводилось работать лишь с четырьмя из них: Naming, Trading, Event, Notification). К тому же CORBA достаточна сложна и требует очень высокой квалификации разработчиков. Достаточно сказать, что с точки зрения CORBA-специалиста EJB является всего лишь Java-имплементацией CORBA Object Framework в спецификации CORBA 3 (к сожалению, еще не реализованной ни одним производителем).

Message-Oriented Middleware (MOM)

Выходом из данной ситуации может служить Messaging System. Существует множество определений этого термина. Например, следующий: Messaging System– это распределенная система, основанная на  асинхронном обмене сообщениями(messages) между компонентами системы.

Message-Oriented Middleware – это, грубо говоря, тот продукт, на основе которого и строится Messaging System. Примером может служить IBM MQSeries.

В отличие от традиционных систем,  в Messaging Systemприложения общаются не напрямую, а посредством MOM. Если один компонент системы хочет послать сообщение другому компоненту, он посылает данное сообщение MOM, а уж MOM затем пересылает его адресату.

Рис. 1

MOM позволяет избавиться от перечисленных в п.2 недостатков.

Приложение, пославшее сообщение, не должно ждать ответа, и может продолжать свою текущую деятельность.

Ни приложение, посылающее сообщение, ни адресат данного сообщения не обязаны бать активными в одно и то же время. Если адресат сообщения не активен, то MOM гарантирует, что сообщение будет доставлено как только адресат станет активным.

Компоненты системы не связаны напрямую друг с другом (decoupled), а потому возможно перенесение компонентов с одного хоста на другой в runtime без ущерба для работоспособности системы.

Модели обмена сообщениями

Существует две "основных" модели обмена сообщениями:

  • point-to-point
  • publish-subscribe (pub-sub)

Point-to-point модель применяется, когда одному или нескольким компонентам (так называемые senders) необходимо посать сообщение одному компоненту-адресату (receiver).

Модель основана на понятии message queue. Sendersпосылают сообщения в queue, а Receiver читает сообщения из queue.

Рис. 2

Часто говорят, что в point-to-point модели есть один и только один receiver. Однако это не совсем верно. Может существовать несколько receivers, присоединенных к одной и той же queue. Но MOMдоставит сообщение только одному из них. Какому именно – зависит от реализации. Некоторые MOM доставляют сообщение первому зарегистрированному receiver, в то время как существуют реализации, осуществляющие round-robin.

Publish-subscribe модель применима, когда одному или нескольким компонентам (publishers) необходимо послать сообщение одному или нескольким компонентам-адресатам (subscribers). Данная модель основана на понятии message topic.

Publishers посылают сообщения в topic, и все subscribersданного topic получают эти сообщения. 

Рис.3

Какую именно модель использовать – это зависит от того, какой вы видите вашу систему во-первых, и какой MOM-продукт вы используете во-вторых. Не все реализации поддерживают обе модели.

Pub-sub модель кажется более элегантной, и у разработчика может возникнуть желание строить все Messaging Systems на основе этой модели. Но следует знать, что многие pub-subсистемы не гарантируют доставку сообщений в том порядке, в каком они были посланы (в отличие от point-to-point, где queueреализует принцип first-in/first-out).  Задача сохранения порядка следования сообщений не тривиальна даже в случае одного topic. А уж если необходимо сохранение порядка доставки сообщений в случае множественных topics – то сложность возрастает экспоненциально. Поэтому в случае pub-sub модели следует по возможности избегать ситуаций, когда порядок следования сообщений важен (либо используя заголовки и раздел свойств сообщений для синхронизации – об этом будет сказано ниже).

Java Message Service (JMS)

Java Message Service (JMS) – это Java API (то есть набор интерфейсов и классов) для работы с Message-Oriented Middleware. Данный набор определен в пакете javax.jms в дереве пакетов J2EE.

JMS реализован во множестве MOM-продуктов, среди которых наиболее известны iPlanet Message Queue, IBM MQSeries,  Progress Software SonicMQ, Bea WebLogic Server, и, конечно, мой любимый Prism Technologies OpenFusion, который к тому же позволяет интегрировать J2EE и CORBA. Существуют и freeware имплементации.

JMS поддерживает обе "основных" модели обмена сообщениями. Однако спецификация не требует от производителя реализовывать обе модели. Впрочем, большинство JMS-продуктов на рынке реализуют как point-to-point, так и pub-sub.

Важно отметить, что обмен сообщениями в JMS может быть частью транзакции, а значит сообщение не будет потеряно в случае возникновения ошибки.

Далее мы рассмотрим использование "основных" моделей в случае JMS, но прежде следует ввести определенную в спецификации терминологию.

ConnectionFactory – это, как нетрудно догадаться из названия, обьект, ответственный за создание JMS Connection. Администратор МОМ создает данный обьект и связывает его с деревом JNDI, так что клиент JMS может получить доступ к ConnectionFactory используя стандартный JNDI lookup-механизм. В случае point-to-point модели используется javax.jms.QueueConnectionFactory, в случае pub-sub модели – javax.jms.TopicConnectionFactory.

Connection – абстрактное представление реального соединения между клиентом JMS и MOM. В случае point-to-point модели используется javax.jms.QueueConnection, в случае pub-sub модели – javax.jms.TopicConnection.

Session – обьект, создаваемый JMS Connection и используемый клиентами для посылки и принятия сообщений. В случае point-to-point используется javax.jms.QueueSession, в случае pub-sub – javax.jms.TopicSession. Фактически, это главная "рабочая лошадка" JMS.

Destination – это либо queue, либо topic – в зависимости от используемой модели: javax.jms.Queue или javax.jms.Topic. Как и ConnectionFactory, destination связывается с деревом JNDI.

MessageProducer – обьект, который, собственно, и посылает сообщения. В случае point-to-point модели это javax.jms.QueueSender, в случае pub-sub – javax.jms.TopicPublisher.

MessageConsumer – обьект, принимающий сообщения. В случае point-to-point модели это javax.jms.QueueReceiver, в случае pub-sub – javax.jms.TopicSubscriber.

Message– сообщение. О типах сообщений будет сказано ниже.

Использование Point - to - Point модели в JMS

Итак, приступим к созданию простейших sender и receiver.

// Используем JMS и JNDI пакеты
import javax.jms.*;
import javax.naming.*;
public class SimpleSender{
public static void main(String args[]){
try {

//Сначала найдем сервис JNDI
Contect ctx = new InitialContext();
      //Теперь найдем ConnectionFactory с помощью JNDI
     //Имя, с которым зарегистрирован
// стандартный ConnectionFactory в дереве
     // JNDIзависит от реализации –
// например, в случае WebLogic Server это
     // weblogic.jms.ConnectionFactory
     QueueConnectionFactory qcf =
(QueueConnectionFactory)ctx.lookup(
"MyConnectionFactory");

    //А теперь создадим Connection
     QueueConnection con = qcf.createQueueConnection();
     //Создадим Session со следующими свойствами:
     //а)посылка сообщений не является частью транзакции
    //б)подтверждение о получении сообщения осуществляет JMS   
    //автоматически
    QueueSession session =
con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
 
     //Найдем Destination с помощью JNDI. Если еще не существует
     // (не зарегистрирована в JNDI) – создадим и зарегистрируем
      Queue queue = null;
     try{
      queue = (Queue)ctx.lookup("MyQueue");
     }catch(NameNotFoundException nnfe){
       queue = session.createQueue("MyQueue");
      ctx.bind("MyQueue",queue);
    }

//Простейшее текстовое сообщение
TextMessage textMessage =
session.createTextMessage();

      //Создадим Producer
     QueueSender sender =
session.createSender(queue);

     //Активизируем Connection
     con.start(); 
     //Теперь мы готовы посылать сообщения
    //Будем посылать наше сообщение каждую секунду
     //или тот интервал, который указан в первом аргументе
      long sendInterval;
    try{
      sendInterval = Long.parseLong(args[0]);
     }catch(Exception rae){
     sendInterval = 1000;
     }

      //Пошлем, например, тысячу сообщений
     for(int i=0;i<1000;i++){
      //Создадим простейшее текстовое сообщение
       textMessage.setText("Hi! It's my message number "+i);
       //И пошлем его
sender.send(textMessage);
        try{
Thread.sleep(sendInterval);
     }catch(Exception se){
         System.out.println("Got an exception "+se.getMessage());
     }
     }

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

Sender создан. Приступим к созданию receiver.

Существует два пути получения сообщений. Первый – синхронное затребование сообщений из queue, используя метод receive() интерфейса javax.jms.QueueReceiver. Второй – асинхронное получение сообщений как только они становятся доступны – используя интерфейс javax.jms.MessageListener.

Многие шаги в создании receiverаналогичны таковым для sender – эту часть оставим без комментариев.

Первый пример receiver – с использованием receive().

import javax.jms.*;
import javax.naming.*;
public class SyncReceiver {
  public static void main(String[] args) {
    try{
      Context ctx = new InitialContext();
      QueueConnectionFactory qcf =
(QueueConnectionFactory)ctx.lookup("MyConnectionFactory");
      QueueConnection con = qcf.createQueueConnection();
      QueueSession session =
con.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
      Queue queue = null;
      try{
        queue = (Queue)ctx.lookup("MyQueue");
      }catch(NameNotFoundException nnfe){
       queue = session.createQueue("MyQueue");
        ctx.bind("MyQueue", queue);
      }

      // Создадим Consumer
      QueueReceiver receiver = session.createReceiver(queue);
      // Активизируем Connection
      con.start();
//Мы готовы принимать сообщения
      for(;;){
//Обратите внимание на использование метода receive()
TextMessage textMessage = (TextMessage)receiver.receive();
        System.out.println("Got a message :"+textMessage.getText());
      }
    }catch(Exception e){
e.printStackTrace();
    }
  }
}

Следующий пример – асинхронное получение сообщений с использованием интерфейса MessageListener.

import javax.jms.*;
import javax.naming.*;

//Обратите внимание, что класс реализует интерфей MessageListener
public class AsyncReceiver implements MessageListener{
  public AsyncReceiver(){

  }

//Метод onMessage интерфейса MessageListener будет вызван
//Consumer'ом для обработки поступившего сообщения
public void onMessage(Message message){
    try{
      TextMessage textMessage = (TextMessage)message;
      System.out.println("Got a message : "+textMessage.getText());
    }catch(JMSException jmse){
      jmse.printStackTrace();
    }
  }
  public static void main(String[] args) {
    try{
      Context ctx = new InitialContext();
      QueueConnectionFactory qcf =
(QueueConnectionFactory)ctx.lookup( "MyConnectionFactory");
      QueueConnection con = qcf.createQueueConnection();
      QueueSession session =
con.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
      Queue queue = null;
      try{
        queue = (Queue)ctx.lookup("MyQueue");
       }catch(NameNotFoundException nnfe){
        queue = session.createQueue("MyQueue");
        ctx.bind("MyQueue", queue);
      }
      QueueReceiver receiver = session.createReceiver(queue);
      con.start();
      AsyncReceiver async = new AcyncReceiver();

//Зарегистрировать новый AsyncReceiver обьект как
      //MessageListener дляreceiver
      receiver.setMessageListener(async);
     //А далее - делать что-либо, не ожидая сообщения.
      //Сообщение будет обработано, как только придет.
      //Для примера будем эмулировать бурную деятельность –
     //"спать"!
      Thread.sleep(100000000);
    }catch(Exception e){
e.printStackTrace();
    }
  }
}

Как видно из примеров, JMS API достаточно прост. В следующем разделе будет представлена pub-sub модель. Изменив point-to-point код всего в нескольких местах, Вы получите работающее pub-sub приложение.

Использование Pub-Sub модели в JMS

Pub-Sub publisher :


import javax.jms.*;
import javax.naming.*;

public class SimplePublisher {
  public static void main(String[] args) {
    try{
      Context ctx = new InitialContext();

      //Найдем ConnectionFactory
      //В случае pub-sub это TopicConnectionFactory
      TopicConnectionFactory tcf =
(TopicConnectionFactory)ctx.lookup("MyTopicFactory");

//Создадим TopicConnection
      TopicConnection con = tcf.createTopicConnection();
//И затем TopicSession
TopicSession session =
con.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);

//Найдем topic в дереве JNDI
      //или создадим новый
      Topic topic = null;
try{
         topic = (Topic)ctx.lookup("MyTopic");
      }catch(NameNotFoundException nnfe){
        topic = session.createTopic("MyTopic");
        ctx.bind("MyTopic",topic);
      }           
      TextMessage textMessage = session.createTextMessage();

      //Producer, в данном случае TopicPublisher
      TopicPublisher publisher = session.createPublisher(topic);
      con.start();
      long sendInterval;
      try{
        sendInterval = Long.parseLong(args[0]);
      }catch(Exception rae){
         sendInterval = 1000;
      }
      for(int i=0;i<1000;i++){
        textMessage.setText("My topic message number"+i);

        //Посылаем сообщение
        publisher.publish(textMessage);
        try{
          Thread.sleep(sendInterval); 
        }catch(Exception ie){
          ie.printStackTrace();
        }
      }       
    }catch(Exception e){
e.printStackTrace();
    }
  }
}

Как видите, изменения в коде незначительны.

Pub-Sub subscriber:

Как и в случае point-to-point, существует два способа получения сообщения: синхронный, с использованием метода receive() интерфейса TopicSubscriber, либо асинхронный, с использованием интерфейса MessageListener.

Приведу лишь список необходимых изменений в обоих случаях. Итак, в синхронном варианте, получив (либо создав) Topic, создайте  consumer:

TopicSubscriber subscriber = session.createSubscriber(topic);

После активизации connection, вы можете получать сообщения:

TextMessage textMessage = (TextMessage)subscriber.receive();

В случае асинхронного получения сообщений, как и прежде, реализуйте метод onMessage интерфейса MessageListener, и зарегистрируйте новый Listener с помощью метода setMessageListener интерфейса TopicSubscriber.

Запустив несколько subscribers, вы увидите, что все они получают сообщения, посланные publishers.

Говоря о pub-sub модели, важно отметить следующее. В отличие от point-to-point случая, где сообщение, посланное в queue, остается там до тех пор, пока receiver не получит это сообщение, pub-sub по умолчанию такой возможностью (durability) не обладает. Иными словами, сообщения, посланные в topic будут доставлены только тем subscribers, которые активны – то есть доступны на данный момент.

Но не отчаивайтесь! Выход, конечно же есть! Все, что вам нужно сделать – создать durable subscriber:

TopicSubscriber subscriber =
session.createDurableSubscriber(topic,"MySubscriberName");

Второй аргумент метода – это уникальное имя данного subscriber.

Теперь можно быть уверенным, что сообщения, посланные в topic, данный subscriber получит, даже если он не активен в момент посылки сообщения – когда станет активным.

Типы сообщений

В JMX определены следующие стандартные типы сообщений:

StreamMessage – сообщение, содержащее сериализованный поток обьектов

MapMessage – сообщение, содержащее пары "ключ-значение"

TextMessage – сообщение, содержащее строку

ObjectMessage– сообщение, содержащее сериализованный обьект

ByteMessage – сообщение, содержащее поток байтов

Кроме того, некоторые имплементации (например, OpenFusion и WebLogic) предоставляют еще один "почти стандартный" тип:

XMLMessage – расширение TextMessage, используется для доставки XMLсообщений

Все типы сообщений являются подклассами javax.jms.Message.

Заголовки и разделы свойств сообщений

Сообщения соостоят из трех частей: заголовка сообщения, раздела свойств и собственно тела сообщения.

Заголовок сообщения содержит дополнительную информацию, которую разработчик может использовать в своем приложении. JMS предоставляет get и set методы для каждого поля заголовка. Некоторые из них устанавливаютя  автоматически, другие могут быть использованы разработчиком приложения.

JMSDestination – содержит имя destination, в который посылается сообщение.

JMSDeliveryMode – определяет, является ли сообщение сохраняемым или нет. Если оно сохраняемо, то будет сохранено MOM в базе данных (или в файле), а потому оно переживет "гибель" системы, в отличие от несохраняемого сообщения.

JMSExpiration – определяет, когда сообщение устареет и будет удалено из системы. По умолчанию сообщение не устаревает никогда.

JMSPriority – как и следует из названия, определяет приоритет сообщения (от 0 до 9). По умолчанию равно 4.

JMSMessageID – уникальный идентификатор сообщения

JMSTimestamp – содержит информацию, когда именно MOM приняла сообщение от producer.

JMSCorrelationID – может быть использовано разработчиком для согласования сообщений: например, если вы хотите переслать ряд сообщений, обьединенных в одну логическую группу (такую как набор товаров в заказе, при этом в каждое сообщение о товаре вы можете добавить в данное поле заголовка номер заказа).

JMSReplyTo – может быть использовано разработчиком для того, чтобы consumer знал, кому (то есть в какой destination) при желании отсылать ответ.

JMSType – поле может быть использовано разработчиком для того, чтобы дать приложению информацию, как обращаться с данным сообщением. Тип здесь понимается как application-specific type, а не тот, что использован выше в разделе "типы сообщений".

JMSRedelivered – устанавливается, если сообщение не было доставлено с первой попытки – например, в случае, когда consumer не подтвердил получение сообщения (если он должен был подтвердить, конечно)

Раздел свойств содержит пары "ключ-значение", которые могут быть использованы для пересылки определенных данных между producer и consumer. В качестве значений могут быть использованы примитивные типы (boolean, byte, float, double, short, int, long), а так же строки (java.lang.String).

Устанавливаются и читаются они с помощью соответствующих set и getметодов. Например, для установки integer-свойства с ключом "MyProperty"  и значением равным 100:

textMessage.setIntProperty("MyProperty", 100);

Для чтения:

int value = textMessage.getIntProperty("MyProperty");

Доставка сообщений

Сообщение может быть сохраняемым или несохраняемым. Если сообщение сохраняемо, то MOM сохранит его в базе данных или файле. Такое сообщение переживет "гибель" MOM. Какой тип сообщения выбрать – зависит от того, что вы ожидаете от своей Messaging System: большей надежности (в случае сохраняемых сообщений), либо большей производительности (в случае несохраняемых).

Вы можете установить режим доставки сообщения в момент его посылки(по умолчанию режим будет таким, каким его установил администратор при создании ConnectionFactory). Например:

textMessage.setText("It's my message");
sender.send(textMessage, DeliveryMode.NON_PERSISTENT,
messagePriority, messageTimeToLive);

Подтверждение получения сообщения

JMS поддерживает три "основных" модели подтверждения получения сообщения.

AUTO_ACKNOWLEDGE – в случае синхронного получения сообщений, подтверждение получения будет произведено автоматически, когда метод receive() возвратит значение не вызвав никакой исключительной ситуации. В случае асинхронного получения сообщений, подтверждение получения будет произведено, когда метод onMessage() вернет значение.

DUPS_OK_ACKNOWLEDGE – работа по подтверждению получения сообщения перекладывается на Session. Сообщения будут вновь доставлены в случае возникновения ошибки или "гибели" системы.

CLIENT_ACKNOWLEDGE – клиент должен вызвать метод acknowledge() интерфейса javax.jms.Message для того, чтобы явно подтвердить получение сообщения. При вызове данного метода будет подтверждено получение текущего и всех предидущих полученных сообщений.

Какой тип подтверждения сообщения выбрать – опять-таки решать вам на основе анализа требований к вашей системе.

AUTO_ACKNOWLEDGE – самый простой тип. Там где не требуется очень высокая производительность – этот тип вполне уместен.

DUPS_OK_ACKNOWLEDGE используйте там, где нужна высокая производительность, однако помните, что минус в данном случае – все неподтвержденные сообщения будут передоставлены вновь.

CLIENT_ACKNOWLEDGE – дает разработчику полный контроль над подтверждением получения сообщения.

Посылка сообщений как часть транзакции

Очень часто возникает необходимость посылать сообщения в контексте транзакции. Например, получив сообщение из queue 1, consumerпосылает это сообщение в другую queue 2. В этот момент происходит исключительная ситуация. И Вы, естественно, хотите, чтобы система вернулась в первоначальное состояние, то есть сообщение вновь оказалось в queue 1.

Одно из главных преимуществ JMS в том, что посылка сообщения может быть частью транзакции.

Существует два подхода в использовании транзакций совместно с JMS. Один применим только внутри JMS, другой может быть использован для включения не только JMS но и, например, JDBC - запроса, в состав той же транзакции.

Первый подход заключается в использовании transacted sessions. Как этого добиться? Очень просто – поставить флаг transacted при создании Вашей session в значение true:

Session session = con.createQueueSession(
true,Session.AUTO_ACKNOWLEDGE);

Важно отменить, что в случае transacted session второй аргумент – тип подтверждения получения – хоть и присутствует, но игнорируется JMS. И подтверждение получения будет произведено, когда транзакция будет завершена методом commit() обьекта session, который должен быть вызван клиентом, получающим сообщение. Интерфейс javax.jms.Session  включает два метода: commit() для подтверждения транзакции и rollback() для отката к первоначальному состоянию.

В данном случае используется chained transaction model. Что это означает? Только то, что в случае успешного завершения транзакции, JMSавтоматически создает новую транзакцию.

И producer, и consumer могут использовать transacted session.

Когда producer использует transacted session, посланные сообщения накапливаются в буфере до тех пор, пока producer не вызовет либо commit(), либо rollback(). В случае вызова commit(), сообщения будут доступны для доставки, в случае вызова rollback(), JMS"очистит" буфер.

В случае, когда consumer использует transacted session, этот sessionконтролирует подтверждение доставки сообщения. В случае вызова commit() производится подтверждение получения сообщений в контексте данной транзакции, в случае вызова rollback() JMS вернет все сообщения в соответствующий destination.

Второй подход заключается в использовании JTA-транзакций совместно с JMS.  Этот подход позволяет разработчику включать в единую транзакцию как посылку сообщений, так и запрос к базе данных или EJB.

Достигается это стандартным способом – использованием javax.transaction.UserTransaction. Например,

UserTransaction myTransaction =
(UserTransaction)ctx.lookup("MyUserTransaction");
myTransaction.begin();
sender.send(textMessage);
myStatement.executeUpdate(
"INSERT INTO testTable VALUES (100,'BILL')");
myTransaction.commit();

При этом важно отметить, что JTA не может быть использован совместно с transacted session. Либо пироги, либо пряники. Если Вы попытаетесь совместить несовместимое, то увидите, что transacted session будет игнорировать вызовы commit() или rollback() интерфейса UserTransaction.

Как и в случае transacted session, тип подтверждения получения сообщения будет игнорироваться.

Когда будет вызван метод commit(), все посланные сообщения будут доступны для доставки. Будет произведено подтверждение для всех полученых сообщений.

Message-Driven Beans

Несколько слов о новом типе EJB в спецификации 2.0.

Новая спецификация EJB 2.0 (реализованная на данный момент только в Weblogic 6.x и, кажется, JBoss 2.x), вводит 3 революционных изменения по онтошению к EJB 1.1

  • Новая модель CMP
  • Появление local interfaces – а значит, резко повышенная производительность
  • И, наконец, интеграция с JMS посредством введения нового типа EJB – Message Driven Beans.

В предыдущей спецификации, при необходимости интергрировать JMS и EJB приходилось идти на различные ухищрения (Weblogic 5.1 для облегчения страданий разработчиков даже предоставлял для этой цели Startup класс). Вызвано это тем, что доступ непосредственно к EJB имеет только контейнер, для клиента же единственный выход – remote interface.

Message Driven Bean (MDB) – это долгожданный плод любви EJB и JMS.

Главная отличительная черта MDB – это то, что клиент не общается с ним посредством remote interface (ни Object-, ни Home-интерфейса MDB не имеет). Единственный способ общения – посылка сообщений. MDB – это просто MessageListener, и ничего больше: класс реализует javax.ejb.MessageDrivenBean и javax.jms.MessageListener. Первый из этих интерфейсов имеет всего два метода:

setMessageDrivenContext и ejbRemove. Второй интерфейс вообще куцый – как Вы помните, он имеет лишь один метод onMessage. Спецификация требует также создания метода ejbCreate без параметров.

Раз клиент не общается непосредственно с MDB, то он его и не создает.  Контейнер сам решит, когда и сколько ему требуется MDB для обработки сообщений из данного destination.

Главный недостаток MDB – он может принимать сообщения только из одного destination.

Заключение

В заключение приведу несколько ссылок на доступные в сети ресурсы по данной тематике.

http://java.sun.com/products/jms/

http://www.jguru.com/ faq/home.jsp?topic=JMS

http://www.theserverside.com/ home/index.jsp

http://www.devx.com/upload/free/features/ javapro/2001/01jan01/ jm0101/jm0101.asp

http://www.devx.com/upload/free/features/ entdev/2000/06jun00/rg0006/rg0006.asp

http://www.prismtechnologies.com/English/ Downloads/DownloadsFrame.html

http://e-docs.bea.com/wls/ docs61/jms/index.html

http://jboss.org

http://www-4.ibm.com/ software/ts/mqseries/api/mqjava.html

http://www.iplanet.com/products/ iplanet_message_queue/home_message_queue.html

http://www.sonicsoftware.com/

http://www.talarian.com/ products/jms/index.shtml

http://www.fiorano.com/ products/products.htm

http://openjms.exolab.org/

http://www.objectweb.org/joram/

Об авторе
Алексей Букавнев, Lead Software Engineer-Consultant in NOKIA Mobile Phones, Mobile Software Unit (ex Middleware and Applications development Group), Irving, TX, USA
EXT-Aleksey.Bukavnev@nokia.com




Справка | Условия Copyright © 1999 — 2010, IT • archiv.
В начало | Логин | Комментарий к колонке | Поиск | Почта