Содержание


Работа с асинхронными сообщениями с помощью Web-сервисов

В распределённой компьютерной среде существует множество моделей для обмена сообщениями. Основная идея этих моделей различается по степени, до которой две системы синхронизируются. С одной стороны, это синхронная модель, в которой система посылает сообщение и ждёт ответа. С другой стороны, это асинхронная модель, в которой система посылает сообщение и продолжает обработку (обмен сообщениями по принципу "выстрелил-и-забыл" (Fire-and-forget)). Отправка сообщения не всегда требует от обеих систем готовности к работе в одно и то же время. Пользователям асинхронной системы сообщений не нужно ждать ответа от получателя, так как они могут положиться на инфраструктуру работы с сообщениями, которая обеспечивает доставку. Асинхронная работа с сообщениями -- это стратегия выбора для слабосвязанной Сервисно-ориентированной архитектуры (SOA), так как она преодолевает свойственные ей ограничения при дистанционном общении, такие как латентность и ненадёжность.

Ядром системы асинхронного обмена сообщениями является межплатформенное (связующее) ПО, ориентированное на обмен сообщениями (Message-oriented middleware - MOM), такое как IBM MQSeries® Рассмотрим, как оно работает: для отправки сообщения Система A размещает сообщение в MOM с помощью прикладных программных интерфейсов (API), выставленных MOM. Система Б, которая хочет получить сообщение, может получить сообщение от MOM с помощью интерфейсов API, выставленных MOM. Если у вас отсутствуют библиотеки MOM для использования MOM-интерфейса API с вашей стороны, можно использовать общий (generic) Web-сервис, который предложит метод размещения сообщений в MOM. Системе, которая хочет посылать сообщения, потребуется клиент Web-сервиса. Этот клиент будет вызван, когда система захочет послать сообщение, он вызовет Web-сервис, и сообщение будет размещено в MOM при помощи Web-сервиса.

Как конфигурировать WebSphere Application Server, версия 6, для обмена сообщениями по умолчанию

Для того, чтобы показать главную идею этой статьи, нам нужно задать конфигурацию WebSphere Application Server, версия 6 (далее по тексту WAS). Чтобы задать конфигурацию WAS, выполните следующие действия:

  • Создайте шину
  • Создайте абонента (member) шины
  • Создайте адрес назначения
  • Создайте мастер соединений JMS
  • Создайте очередь JMS
  • Создайте спецификацию для активации JMS

Более подробную информацию о том, как выполнить эти действия, вы можете найти в статье "Применение управляемых сообщениями bean-компонентов и JMS-приложений в Шине Интеграции Сервисов", в разделе Ресурсы.

Использование Web-сервисов для передачи сообщений в MOM

Web-сервис применит метод, который при вызове поставит сообщение в очередь. Чтобы продемонстрировать это, мы будем использовать текстовое сообщение, хотя Web-сервис может быть создан для любого типа JMS-сообщений. За получением информации о том, как написать Java Web-сервис, обращайтесь к справочнику "WebSphere версии 6: Руководство по разработке и размещению Web-сервисов", который указан в разделе Ресурсы. Листинг 1 показывает метод размещения сообщения (putMessage) на примере Web-сервиса, использованного для тестирования кода этой статьи.

Листинг 1. Метод размещения сообщения: putMessage
                public void putMessage(String message){
 try {
	Properties prop = new Properties();
	prop.put(InitialContext.INITIAL_CONTEXT_FACTORY,
		"com.ibm.websphere.naming.WsnInitialContextFactory");
	prop.put(InitialContext.PROVIDER_URL,
		"corbaloc:iiop:localhost:2809");
	InitialContext context = new InitialContext(prop);
			
	    //Do the lookup for Queue connection factory.	
	QueueConnectionFactory 
	  factory =(QueueConnectionFactory)context.lookup("JMS/MyQueue_CF");
			
		//Do the lookup for Queue. 	
	Destination queue = (Destination) context.lookup("JMS/queue");
			
		//Create connection and start it.	
	Connection connection = factory.createConnection();
	connection.start();
	System.out.println("connection created");
			
		//Create session and message producer.	
	Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
	MessageProducer producer=session.createProducer(queue);
	System.out.println("producer created");
	System.out.println(producer.getDestination().toString());
			
		//Prepare the text message.	
	TextMessage msg=session.createTextMessage();
	msg.setText(message);
			
	    //Send the message.	
		producer.send( msg);
	    System.out.println("sent message: "+msg.getText());
		        
   } catch (Exception e) {
	e.printStackTrace();
  }
}

Метод putMessage ищет мастера соединений (Connection Factory), объекты JMS, адрес назначения в JNDI. Затем он создаёт соединение, сессию и, наконец, автора сообщения для адреса назначения JMS и ставит текстовое сообщение в очередь.

Конфигурирование базы данных

Конфигурация базы данных требуется для автоматического вызова клиента Web-сервиса. Это можно сделать несколькими способами. Например, вы можете написать Триггер и Триггер, вызывающий пользовательскую функцию, или написать Триггер и Триггер, вызывающий Java-хранимую процедуру. Для примера, мы используем Триггер, комбинацию Java-хранимой процедуры и базу данных DB2. Выполните следующие действия для конфигурации своей базы данных.

Создайте пример таблицы

Выполните следующую SQL-команду для примера таблицы:

Листинг 2. SQL для создания примера таблицы
CREATE TABLE customer 
(
	pkey INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START 
        WITH 1, INCREMENT BY 1, NO CACHE ) PRIMARY KEY,
	fname		VARCHAR(20),
	lname		VARCHAR(20),
	ccode		VARCHAR(10)
);

Создайте Java-хранимую процедуру (SP)

Эта Java-хранимая процедура (Java SP) является ключом к пониманию основной идеи этой статьи. Класс Java, который будет запущен при вызове Java SP, будет содержать код для запуска Web-сервиса. Задайте следующую SQL-команду для создания Java SP.

Листинг 3. SQL для создания Java SP
                CREATE PROCEDURE MyPROCEDURE ( IN var0 INTEGER,IN var1 VARCHAR(20) )
    SPECIFIC SQL060622110835012
    DYNAMIC RESULT SETS 1
    NOT DETERMINISTIC
    LANGUAGE Java
    EXTERNAL NAME 'MyPROCEDURE.invokeWS'
    FENCED
    THREADSAFE
    PARAMETER STYLE JAVA

Данный ниже код листинга показывает класс Java MyPROCEDURE. Этот класс содержит метод под названием invokeWS. Этот метод принимает три параметра, первичный ключ, действия, произведенные с таблицей (создать, обновить, удалить) и результирующее множество. Я в этом методе использовал интерфейс Axis API для написания кода клиента Web-сервиса. Для компиляции и запуска этого класса убедитесь в том, что файлы Axis jar находятся в директории классов.

Листинг 4. Java-класс для Java SP
import java.sql.*;
import java.io.FileOutputStream;
import java.io.PrintStream;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.Service;
import javax.xml.rpc.Call;
import javax.xml.rpc.ParameterMode;
import javax.xml.namespace.QName;

public class MyPROCEDURE
{
  public static void invokeWS ( int var0, String var1, ResultSet[] rs1 )
  throws SQLException, Exception
   {
      try{
	  //create service factory
	    
	    ServiceFactory factory = ServiceFactory.newInstance();
   // define qnames
	    
	   String targetNamespace = "http://asyncmessage.ibm.com";
	   QName serviceName = new QName(targetNamespace,"AsynchronousMessageWSService");
	   QName portName = new QName(targetNamespace,"AsynchronousMessageWS");
	   QName operationName = new QName(targetNamespace,"putMessage");
	    
  // create service
	    Service service = factory.createService(serviceName);
	    
  // create call
	  Call call = service.createCall();
	    
  // set port and operation name
	  call.setPortTypeName(portName);
	  call.setOperationName(operationName);
	    
  // add parameters
	  call.addParameter("message", 
	  new QName(targetNamespace,"string"),ParameterMode.IN);
	  call.setReturnType(new QName("",""));
	    
  // set end point address
	   call.setTargetEndpointAddress("http://localhost:9080/AsyncMessagingSamples
	    /service/AsynchronousMessageWS");
	           
  // invoke the remote web service
	    call.invoke(new Object[]
	    { "Message from DB2: a row with primary key"+var0+" is "+var1+"d"});
	          
       }catch(Exception e)
     {
        try{
                	      
          FileOutputStream fout=new FileOutputStream("errors.txt");
           e.printStackTrace(new PrintStream(fout));
                              
		}catch(Exception e1){}
      }
   }
}

Создайте триггеры в примере таблицы

В примере программы мы создали три триггера в таблице пользователя для вставки, обновления и удаления. Это используется, например, всякий раз, когда в таблицу пользователя вставляется строка, происходит обновление или удаление. Если что-то из этого происходит, Триггеры будут выполнены. Затем эти Триггеры вызовут Java SP, которая в свою очередь запустит метод invokeWS. Выполните следующую SQL-команду для создания Триггеров. Посмотрим, как это работает:

Листинг 5. SQL для создания Триггеров в примере таблицы
                //Trigger for row insertion
	CREATE TRIGGER event_create 
	AFTER INSERT ON CUSTOMER REFERENCING NEW AS N  
	FOR EACH ROW MODE DB2SQL 
	call MYPROCEDURE(N.pkey,'create');

//Trigger for row updation
	REATE TRIGGER event_udpate 
	AFTER UPDATE ON CUSTOMER REFERENCING NEW AS N  
    FOR EACH ROW MODE DB2SQL 
	call MYPROCEDURE(N.pkey,'update');

//Trigger for row deletion 
	CREATE TRIGGER event_delete 
	AFTER DELETE ON CUSTOMER REFERENCING OLD AS O
	FOR EACH ROW MODE DB2SQL 
	call MYPROCEDURE(N.pkey,'delete');

Создание MDB

Для завершения сценария нам нужно создать управляемый сообщениями bean-компонент (MDB). Этот компонент будет присоединяться к очереди, в которую наша Web-сервиса будет помещать сообщения. Более подробную информацию о том, как задать конфигурацию MDB, вы можете найти в статье "Применение управляемых сообщениями bean-компонентов и JMS-приложений в Шине Сервиса Интеграции (Service Integration Bus)", которая находится в разделе Ресурсы. Листинг 6 отображает фрагменты из файла ibm-ejb-jar-bnd.xmi и метода onMessage из примера MDB, использованного для этой статьи.

Примечание: некоторые части файла ibm-ejb-jar-bnd.xmi были сокращены для лёгкости прочтения, а важные характеристики были выделены полужирным шрифтом.

Листинг 6. Фрагменты из onMessage и файла ibm-ejb-jar-bnd.xmi
               .........................................................
<ejbBindings.....
	 activationSpecJndiName="eis/MyQueue_activation_spec" destinationJndiName="JMS/queue" >
	..........................................................
	<resRefBindings.........  jndiName="JMS/MyQueue_CF" >
	..........................................................
	<resRefBindings.....  jndiName="JMS/queue" >
	...........................................................
</ejbBindings>
		
		
public void onMessage (javax.jms.Message msg)
	{
           try {		
                 System.out.println("***********************************");
		 System.out.println("***********************************");
                 System.out.println("***"+((TextMessage)msg).getText()+"***");
		 System.out.println("***********************************");
		 System.out.println("***********************************");
               } catch (JMSException e) 
                       {
			 // TODO Auto-generated catch block
			    e.printStackTrace();
		   	}
	}

Соединение всего вместе

Мы закончили требуемую установку. Разверните Web-сервис в WebSphere Application Server. Теперь всякий раз, когда мы будем создавать, обновлять или удалять строку в таблице пользователя, будет записываться сообщение в файл SystemOut.log в папке WebSphere Application Server, с помощью компонентов MDB. Если вы создадите в таблице пользователя строку с помощью первичного ключа 100, сообщение будет выглядеть как "Сообщение от DB2: строка с первичным ключом 100 создана".

Заключение

В этой статье мы узнали, как можно облегчить асинхронный обмен сообщениями через HTTP с помощью Web-сервисов. Главное преимущество этого метода заключается в том, что эта платформа и язык независимы, что даёт вам свободу выбора – от написания JMS-клиентов до отправки сообщений в MOM.

Примечание автора

Автор хотел бы поблагодарить Кришнакумар Балахандар (Krishnakumar Balachandar (KK)) (WebSphere Community Edition/Geronimo L3 Support Lead), Шишир Нарейн (Shishir Narain) (разработчика WebSphere Partner Gateway) и Шаджи Вайдян (Shaji Vaidyan) (WebSphere Adapter для JDBC, Поддержка и Разработка) за их замечания и комментарии по этой статье.


Ресурсы для скачивания


Похожие темы

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=SOA и web-сервисы
ArticleID=169717
ArticleTitle=Работа с асинхронными сообщениями с помощью Web-сервисов
publish-date=08252006