Содержание


Совет

Отправка и получение сообщений SOAP с помощью SAAJ

Программный интерфейс для Java позволяет автоматизировать множество шагов, необходимых при ручном создании и отправке сообщений

Comments

Серия контента:

Этот контент является частью # из серии # статей: Совет

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Совет

Следите за выходом новых статей этой серии.

Возможность отправки и получения сообщения в стандартном формате, распознаваемом всеми взаимодействующими системами, лежит в основе технологии Web-сервисов. Как правило, этим форматом является SOAP. Сообщения SOAP можно создавать и отправлять вручную, но многие из необходимых шагов, например установка соединения или отправка сообщения, могут быть выполнены автоматически с помощью SAAJ (SOAP with Attachments API for Java) – API, появившегося в результате работы над программным интерфейсом для передачи сообщений XML (Java API for XML Messaging - JAXM). В данной статье рассматривается последовательность действий по созданию и отправке синхронных сообщений SOAP.

Весь процесс состоит из пяти шагов:

  1. создание соединения SOAP;
  2. создание сообщения SOAP;
  3. формирование сообщения;
  4. отправка сообщения;
  5. получение ответа.

SAAJ поставляется в составе пакета для разработки Web-сервисов Java (Java Web Services Developer Pack 1.2, см. Ресурсы). В пакет включены также Web-сервер Tomcat, благодаря которому вы можете развернуть собственный Web-сервис, и демонстрационные приложения.

Установка

Установка и конфигурирование Java Web Services Developer Pack 1.2 не представляет трудностей, если вы собираетесь отправлять сообщения через Web-сервер Tomcat. Если же подобно тому, как это делается в данной статье, вы хотите отправлять сообщения через отдельное приложение, то потребуются некоторые дополнительные действия.

  1. Скачайте JWSDP 1.2 по адресу: http://java.sun.com/webservices/downloads/webservicespack.html.
  2. Установите его согласно инструкциям.
  3. Если вы используете Java 1.4, то вам следует переопределить классы, относящиеся к XML, которые входят в поставку JWSDP 1.2. Создайте следующую директорию:
    <JAVA_HOME>/jre/lib/endorsed
    и скопируйте в нее все файлы из:
    <JWSDP_HOME>/jaxp/lib/endorsed
    (переменные окружения JAVA_HOME и JWSDP_HOME указывают на директории установки Java и JWSDP соответственно).
  4. Добавьте следующие файлы в classpath:
    • <JWSDP_HOME>/saaj/lib/saaj-api.jar
    • <JWSDP_HOME>/saaj/lib/saaj-impl.jar
    • <JWSDP_HOME>/jwsdp-shared/lib/commons-logging.jar
    • <JWSDP_HOME>/jwsdp-shared/lib/mail.jar
    • <JWSDP_HOME>/jwsdp-shared/lib/activation.jar
    • <JWSDP_HOME>/jaxp/lib/endorsed/dom.jar
    • <JWSDP_HOME>/jaxp/lib/endorsed/xercesImpl.jar
    • <JWSDP_HOME>/jaxp/lib/endorsed/sax.jar
    • <JWSDP_HOME>/jaxp/lib/endorsed/xalan.jar

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

Структура сообщения SOAP

Начнем с рассмотрения структуры самих сообщений. В общем случае SOAP-сообщение состоит из оболочки, разделенной на две главные части: заголовок и само сообщение. Несмотря на то, что использование этих частей остается на усмотрение конкретного приложения, сообщения должны иметь определенную XML-структуру, подобную показанной в листинге 1.

Листинг 1. Пример сообщения SOAP
<SOAP-ENV:Envelope 
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/1999/XMLSchema"> 
    <SOAP-ENV:Header />
    <SOAP-ENV:Body> 
        <ns1:getPrice xmlns:ns1="urn:xmethods-BNPriceCheck" 
             SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
                  <isbn xsi:type="xsd:string">0672324229</isbn> 
        </ns1:getPrice> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope>

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

Обратите внимание на структуру сообщения. Оболочка (элемент Envelope) содержит элементы Header и Body, причем все три принадлежат пространству имен http://schemas.xmlsoap.org/soap/envelope/. Приложение отправляет сообщения, используя объект SOAPConnection.

Установка соединения и создание сообщения

Первым шагом является создание экземпляра класса соединения и установка самого соединения (листинг 2).

Листинг 2. Создание соединения
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPConnection;

public class SOAPTip {
    
   public static void main(String args[]) {
        
      try {
      
         //Сначала создаем соединение
         SOAPConnectionFactory soapConnFactory = 
                            SOAPConnectionFactory.newInstance();
         SOAPConnection connection = 
                             soapConnFactory.createConnection();
         


         //Закрываем соединение            
         connection.close();
            
        } catch(Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

Приложение может отправлять сообщения SOAP непосредственно через класс SOAPConnection, который теперь включен в пакет SAAJ, или с использованием провайдера сообщений, являющегося частью пакета JAXM. Объект SOAPConnection создается с помощью фабрики.

Фабрика также используется для создания самого сообщения (листинг 3).

Листинг 3. Создание сообщения
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPBody;

public class SOAPTip {
    
   public static void main(String args[]) {
        
      try {
     
         //Сначала создаем соединение
         SOAPConnectionFactory soapConnFactory = 
                            SOAPConnectionFactory.newInstance();
         SOAPConnection connection = 
                             soapConnFactory.createConnection();
         
         //Затем создаем сообщение
         MessageFactory messageFactory = MessageFactory.newInstance();
         SOAPMessage message = messageFactory.createMessage();
         
         //Создаем объекты, представляющие различные компоненты сообщения        
         SOAPPart soapPart =     message.getSOAPPart();
         SOAPEnvelope envelope = soapPart.getEnvelope();
         SOAPBody body =         envelope.getBody();


         //Закрываем соединение
         connection.close();
            
        } catch(Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

Сначала с помощью объекта MessageFactory создается собственно сообщение. В этот момент оно уже включает в себя разделы envelope и header, но они пока пусты. Объект SOAPPart содержит envelope, в который, в свою очередь, включено тело сообщения. Далее объявляются переменные, содержащие все необходимые ссылки, в частности, SOAPBody.

Далее необходимо заполнить данными тело сообщения (объект SOAPBody), как показано в листинге 4.

Листинг 4. Формирование тела сообщения
...
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;

public class SOAPTip {
    
   public static void main(String args[]) {
        
      try {
...
         //Создание объектов, представляющих собой части сообщения 
         SOAPPart soapPart =     message.getSOAPPart();
         SOAPEnvelope envelope = soapPart.getEnvelope();
         SOAPBody body =         envelope.getBody();

        //Формирование тела сообщения
        //Создание главного элемента с учетом пространства имен
        SOAPElement bodyElement = 
                  body.addChildElement(envelope.createName("getPrice" , 
                                                                "ns1", 
                                          "urn:xmethods-BNPriceCheck"));
        //Добавление содержимого
        bodyElement.addChildElement("isbn").addTextNode("0672324229");

        //Сохранение сообщения
        message.saveChanges();


        //Проверка созданного сообщения
        System.out.println("\nREQUEST:\n");
        message.writeTo(System.out);
        System.out.println();


         //Закрытие соединения
         connection.close();
            
        } catch(Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

Тело сообщения SOAP представляет собой обыкновенный XML-элемент, в который можно помещать вложенные элементы, такие как getPrice. Далее можно добавить элемент isbn и соответствующий ему текст. Все делается так же, как и в случае любого элемента DOM.

SAAJ также позволяет напрямую создать объект SOAPPart-сообщения из внешнего файла. Например, если XML-содержимое сообщения, приведенного в листинге 1, содержится в файле prepped.msg, то к нему можно обратиться вместо ручного создания сообщения (листинг 5).

Листинг 5. Создание сообщения из внешнего файла
...
import javax.xml.soap.SOAPElement;

import java.io.FileInputStream;
import javax.xml.transform.stream.StreamSource;

public class SOAPTip {
    
   public static void main(String args[]) {
...
         //Создание объектов, представляющих различные части сообщения      
         SOAPPart soapPart =     message.getSOAPPart();
         SOAPEnvelope envelope = soapPart.getEnvelope();
         SOAPBody body =         envelope.getBody();

         //Формирование сообщения
        StreamSource preppedMsgSrc = new StreamSource( 
                 new FileInputStream("prepped.msg"));
        soapPart.setContent(preppedMsgSrc);

         //Сохранение сообщения
         message.saveChanges();
...
    }
}

Класс StreamSource обычно используется при преобразованиях XSL, но в данном случае с его помощью просто открывается файловый поток ввода FileInputStream. В результате у нас получилось готовое к отправке сообщение.

Отправка сообщения

При работе с синхронными сообщениями SOAP, отправка и получение ответа выполняются за один шаг (листинг 6).

Листинг 6. Отправка сообщения
...
public class SOAPTip {
    
   public static void main(String args[]) {
        
...
         //Проверка созданного сообщения
         System.out.println("\nREQUEST:\n");
         message.writeTo(System.out);
         System.out.println();

        //Отправка сообщения и получение ответа
            
        //Установка адресата
        String destination = 
            "http://services.xmethods.net:80/soap/servlet/rpcrouter";
        //Отправка
        SOAPMessage reply = connection.call(message, destination);

         //Закрытие соединения
         connection.close();         
...
    }
}

Сообщение отправляется в момент вызова метода call(), который принимает в качестве аргументов само сообщение и адрес назначения. В качестве ответа метод возвращает другой объект SOAPMessage. В более ранних версиях JAXM адрес назначения должен был быть экземпляром класса Endpoint или URLEndpoint, но в текущей версии адресом может быть объект любого типа. В данном примере используется Web-сервис под названием "Узнай цену на книгу" ("Book price checker"), размещенный на сервере XMethods и возвращающий цену на книгу, ISBN которой содержится в запросе.

Метод call() блокирует выполнение программы до момента получения ответа в виде объекта SOAPMessage.

Ответ

Полученный объект типа SOAPMessage, ссылка на который хранится в переменной reply, также является сообщением SOAP, и его структура идентична отправленному сообщению. Как и любое XML-сообщение, его можно трансформировать с помощью XSLT. SOAP позволяет выполнить XSLT-преобразование напрямую, как показано в листинге 7.

Листинг 7. Чтение полученного ответа
...
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.Source;

import javax.xml.transform.stream.StreamResult;

public class SOAPTip {
    
   public static void main(String args[]) {
        
      try {
      
...
         //Отправка сообщения
         SOAPMessage reply = connection.call(message, destination);

        //Проверка полученного ответа
        System.out.println("\nRESPONSE:\n");
        //Создание XSLT-процессора
        TransformerFactory transformerFactory = 
                           TransformerFactory.newInstance();
        Transformer transformer = 
                        transformerFactory.newTransformer();
        //Получение содержимого ответа
        Source sourceContent = reply.getSOAPPart().getContent();
        //Задание выходного потока для результата преобразования
        StreamResult result = new StreamResult(System.out);
        transformer.transform(sourceContent, result);
        System.out.println();

         //Закрытие соединения
         connection.close();
...            
     }
}

Сначала, как и всегда при использовании XSLT, необходимо создать объект Transformer. В данном случае нам просто надо вывести содержимое сообщения, поэтому таблица стилей не используется. Под содержимым понимается SOAP-часть сообщения, а не все сообщение, в котором могут еще содержаться вложения. Перед обработкой можно также разделить оболочку и тело сообщения. Содержимое выводится в System.out (см. рисунок 1), но в принципе результат трансформирования может выводиться в любой доступный поток вывода. Само преобразование происходит обычным образом.

Рисунок 1. Запрос и ответ в SOAP
Request and response
Request and response

Следующие шаги

В нашем простом примере сообщение просто выводится в стандартный поток вывода, но с таким же успехом можно было получить нужную информацию из документа XML. Кроме того, хотя в данной статье демонстрируется синхронная отправка и получение сообщений, интерфейс JAXM, который можно скачать отдельно, позволяет использовать провайдер сообщений, обеспечивающий асинхронную доставку с помощью объекта ProviderConnection вместо SOAPConnection. Провайдер хранит сообщение, пока оно не будет успешно доставлено.

JAXM также поддерживает работу с профилями, которые облегчают создание специализированных сообщений SOAP, таких как SOAP-RP или ebXML.


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


Похожие темы


Комментарии

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML, SOA и web-сервисы
ArticleID=388221
ArticleTitle=Совет: Отправка и получение сообщений SOAP с помощью SAAJ
publish-date=05082009