Протокол SOAP. Simple Object Access Protocol (SOAP) - общее описание

  • 29.07.2019

SOAP (Simple Object Access Protocol) является стандартизированным протоколом передачи сообщений между клиентом и сервером. Обычно он используется совместно с HTTP(S), но может работать и с другими протоколами прикладного уровня (например, SMTP и FTP).
Тестирование SOAP с точки зрения техник тестирования ничем принципиально не отличается от работы с другими API, но для его проведения требуются предварительная подготовка (в плане теории протокола) и специальные инструменты для тестирования. В данной статье я хотела бы сформулировать небольшой чек-лист необходимых знаний и навыков, который будет одинаково полезен как тестировщику SOAP (зачастую не представляющему, «за что хвататься» после постановки задачи), так и менеджеру, вынужденному оценивать знания тестировщиков и разрабатывать планы по обучению.

Теоретическая база

Тот факт, что SOAP является протоколом, имеет большое значение для тестирования: нужно изучить сам протокол, «первичные» стандарты и протоколы, на которых он базируется, а также (по мере необходимости) существующие расширения.

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



Юля
Наташа
Напоминалка
Не забудь написать статью!

Более подробно про XML можно узнать на w3schools или codenet (по-русски) . Обязательно обратите внимание на описание namespaces (метод разрешения конфликтов при описании элементов в XML) – в SOAP их использование необходимо.

XSD
При работе всегда удобно иметь стандартизированное описание возможных XML-документов и проверять их на корректность заполнения. Для этого существует XML Schema Definition (или сокращенно XSD). Две главные фичи XSD для тестировщика – это описание типов данных и наложение ограничений на возможные значения. Например, элемент из предыдущего примера можно сделать необязательным для заполнения и ограничить его размер 255 символами с помощью XSD:

...







...

Расширения SOAP
В работе вам также могут встретиться различные «расширения» SOAP – стандарты типа WS-* . Одним из самых распространенных является WS-Security позволяющий работать с шифрованием и электронными подписями. Нередко вместе с ним применяется WS-Policy, с помощью которого можно управлять правами на использование вашего сервиса.

Пример использования WS-Security:


Alice
6S3P2EWNP3lQf+9VC3emNoT57oQ=
YF6j8V/CAqi+1nRsGLRbuZhi
2008-04-28T10:02:11Z

Все эти расширения – достаточно сложные конструкции, используемые далеко не в каждом SOAP-сервисе; их подробное изучение на начальном этапе освоения тестирования SOAP вряд ли будет актуально.

Инструменты

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

Редакторы XML / XSD
Хороший тестировщик начинает тестирование еще на стадии написания документации, поэтому для проверки схем удобно использовать специальные редакторы. Два самых известных – Oxygen (кроссплатформенный) и Altova (только для Windows); оба они являются платными. Это очень мощные программы, которыми активно пользуются аналитики при описании сервисов.

В моей практике полезными оказались три фичи редакторов: визуализация XSD, генерация XML на основе XSD и валидация XML по XSD.

1. Визуализация XSD нужна для наглядного представления схемы, позволяющего быстро вычленить обязательные элементы и атрибуты, а также существующие ограничения. Например, для запроса CheckTextRequest обязательным является элемент text, а необязательными – все три атрибута (при этом у атрибута options установлено значение по умолчанию – ноль).

Визуализация необходима в том случае, когда типов и ограничений в схеме много. Если вам нужна только она, и вы не хотите платить за специальные редакторы, то можно рассмотреть бесплатные альтернативы (например, JDeveloper).

2. Генерация XML на основе XSD полезна тогда, когда вы хотите увидеть корректный пример сообщения. Я пользуюсь ей для того, чтобы быстро поэкспериментировать с возможным заполнением сообщения и проверить нюансы работы ограничений.

3. После использования фичи из пункта 2 полезно провести валидацию XML по XSD – то есть проверить сообщение на корректность. Вместе фичи 2 и 3 позволяют отлавливать хитрые дефекты в XSD еще тогда, когда сам сервис находится в разработке.

Инструмент тестирования – SoapUI

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

Уровень 1 – умею отправлять запросы
Научитесь создавать проект на основе WSDL. SoapUI может сгенерировать все необходимые запросы для вас; вам останется лишь проверить правильность их заполнения и нажать кнопочку «Send». После выработки навыков создания корректных запросов вы должны овладеть искусством формирования некорректных запросов, вызывающих появление ошибок.

Уровень 2 – умею делать Test Suites и Test Cases
Начните делать мини-автотесты. Тест-комплекты и тест-кейсы позволяют создавать сценарии тестирования API, подготавливать данные для запросов и автоматически проверять полученный ответ на соответствие ожидаемому. На первых порах их можно использовать просто как коллекции запросов. Например, если вы завели дефект и хотите быстро проверить его после фикса, можно выделить отдельный тест-комплект конкретно под запросы-дефекты.

Уровень 3 – умею писать Assertions
После освоения тест-кейсов вам будет полезно научиться делать их автоматически проверяемыми. После этого вам уже не нужно будет искать «глазами» информацию об ответе: при наличии автоматической проверки кейсы будут помечаться зеленым (если проверка пройдена) или красным (если не пройдена). SoapUI предоставляет большой набор возможных проверок (assertions), но самые удобные и простые – это Contains и Not Contains. С их помощью можно проверить факт наличия конкретного текста в полученном ответе. Эти проверки также поддерживают поиск с помощью регулярных выражений.

Уровень 4 – использую XPath и/или XQuery в Assertions
Для тех, кто немного знаком с UI с помощью Selenium, язык XPath – знакомая вещь. Грубо говоря, XPath позволяет искать элементы в XML-документе. XQuery – похожая технология, которая может использовать XPath внутри себя; этот язык гораздо мощнее, он напоминает SQL. Оба эти языка можно использовать в Assertions. Проверки с их помощью получаются более прицельными и стабильными, поэтому ваши кейсы будут пользоваться большим доверием.

Уровень 5 – умею писать сложные тесты с помощью специальных шагов

В тест-кейсах может содержаться не только один запрос, но и несколько (к примеру, когда вы хотите эмулировать стандартный сценарий работы пользователя «создать сущность» → «экспортировать сущность»). Между запросами могут находиться другие специальные шаги, например:

  • Properties и Property Transfer (помогают переиспользовать данные и передавать их между запросами);
  • JDBC Request (используется для получения данных из базы данных);
  • Conditional Goto (позволяет сделать разветвления или циклы в тест-кейсе);
  • Run TestCase (помогает вынести какие-то типовые запросы в отдельные тест-кейсы и вызывать их там, где нужно).

Уровень 6 – использую скрипты на Groovy

SoapUI позволяет писать скрипты на Groovy в различных местах. Простейший случай – это генерация данных в самом запросе с помощью вставок ${=}. Я постоянно пользуюсь такими вставками:

  • ${=new Date().format(«yyyy-MM-dd’T’HH:mm:ss»)} – для вставки текущей даты и времени в необходимом формате;
  • ${=java.util.UUID.randomUUID()} – для вставки корректно сформированного случайного GUID.

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

Уровень 7 – использую MockServices
SoapUI на основе WSDL может генерировать Mock-объекты . Mock-объект – это простейшая симуляция сервиса. С помощью «моков» можно начать писать и отлаживать тест-кейсы еще до того, как сервис реально будет доступен для тестирования. Также их можно использовать в качестве «заглушек» для временно недоступных сервисов.

Уровень 8 – бог SoapUI
Вы знаете разницу между платной и бесплатной версиями SoapUI и используете SoapUI API в коде. Вы используете плагины и запускаете выполнение кейсов через командную строку и/или CI. Ваши тест-кейсы просты и легко поддерживаются. В общем, вы «съели собаку» на этом инструменте. Я бы с радостью пообщалась с тем, кто освоил SoapUI на таком уровне. Если вы являетесь таковым – отпишитесь в комментариях!

Тестирование с помощью языков программирования

Приведу пример того, как выглядит запрос к YandexSpeller API, выполненный с помощью groovy-wslite:

import wslite.soap.*
def client = new SOAPClient("http://speller.yandex.net/services/spellservice?WSDL")
def response = client.send(SOAPAction: "http://speller.yandex.net/services/spellservice/checkText") {
body {
CheckTextRequest("lang": "ru", "xmlns":"http://speller.yandex.net/services/spellservice") {
text("ошипка")
}
}
}
assert "ошибка" == response.CheckTextResponse.SpellResult.error.s.text()
assert "1" == [email protected]()

Насколько я знаю, высокоуровневых фреймворков (по типу Rest-assured) для тестирования SOAP пока не существует, но недавно появился интересный инструмент – karate . С его помощью можно описывать кейсы для тестирования SOAP и REST в виде сценариев по типу Cucumber / Gherkin . Для многих тестировщиков обращение к karate будет идеальным решением, ведь такие сценарии по сложности написания и поддержки кейсов будут лежать где-то посередине между использованием SoapUI и написанием собственного фреймворка для тестирования SOAP.

Заключение

Вряд ли вам когда-либо захочется тестировать SOAP просто так, для себя (как могло бы получиться с REST-ом). Это тяжеловесный протокол, который используется в серьезных корпоративных решениях. Но его тяжеловесность одновременно является подарком тестировщику: все используемые технологии стандартизированы, имеются качественные инструменты для работы. От тестировщика требуется лишь желание их изучить и использовать.

Давайте соберем воедино тот самый чек-лист необходимых навыков для тестировщика. Итак, если вы только начинаете тестировать SOAP сервисы, вам нужно знать и уметь использовать:

  • WSDL.
  • SOAP.
  • Редакторы XML / XSD (на уровне визуализации XSD).
  • SoapUI на уровне 1.

Как видите, основной упор приходится на изучение стандартов, в SoapUI достаточно просто уметь выполнять запросы. По мере погружения в тестирование SOAP перед вам будут возникать задачи, которые потребуют уже более серьезных навыков и знаний, но не стоит пытаться изучить всё и сразу. Гораздо важнее последовательность в повышении уровня сложности выполняемых задач. Следуя этой рекомендации, в один прекрасный момент вы поймете, что стали хорошим специалистом в этой области!

Как уже говорилось в предыдущей главе, Web-службы обмениваются информацией с клиентами и между собой, посылая сообщения на языке XML. Теги этой реализации XML, правила оформления документа XML и порядок обмена документами определены протоколом SOAP. Протокол SOAP создан в 1998 году командой разработчиков под руководством Дейва Винера (Dave Winer), работавшей в корпорации Microsoft и фирме Userland. Название протокола - "Простой протокол доступа к объектам" - отражает его первоначальное назначение - обращаться к методам удаленных объектов. Назначение протокола изменилось, сейчас это протокол всякого взаимодействия Web-служб и компонентов слабо связанных распределенных приложений. Он уже не совсем прост, да и об объектах он ничего не говорит. Многие разработчики предлагают назвать его "Service Oriented Architecture Protocol", оставив прежнее сокращение. Чтобы прекратить эти попытки, в спецификации SOAP 1.2 указано, что слово "SOAP" отныне никак не будет расшифровываться.

В конце 1999 года разработка протокола была передана в консорциум W3C (http: //www.w3.org/ ).

В мае 2000 года консорциум выпустил свою версию SOAP 1.1. Послание, написанное по протоколу SOAP, оформляется документом XML, активно использующим пространства имен. Имена элементов XML версии SOAP 1.1 относятся к пространству имен с идентификатором http://schemas.xmlsoap.org/soap/envelope/.

Черновик второй версии SOAP 1.2 был выпущен в 2001 году, его пространство имен называлось в то время http://www.w3.org/2001/06/soap-envelope.

Заметьте, что именно идентификатор пространства имен, а не номер 1.1 или 1.2 определяет версию SOAP. Сервер не станет рассматривать SOAP- послание и вернет сообщение об ошибке если заметит

несоответствие пространства имен.

В то время как я пишу эти строки, версия SOAP 1.1 остается рабочей. Версия 1.2 никак не может выйти из подготовительной стадии, но уже используется, например, в SOAP::Lite, Apache SOAP 2.3, Apache Axis. Поэтому в этой главе я буду излагать версию 1.2, отмечая ее отличия от версии 1.1.

Спецификация рабочей версии SOAP всегда хранится по адресу http://www.w3.org/TR/SOAP/. Документы, лежащие по этому адресу, заменяются новыми при замене рабочей версии.

Черновая версия SOAP постоянно обновляется, при этом меняется идентификатор пространства имен. Новейший вариант черновой версии на время написания книги хранился по адресу http://www.w3.org/TR/soapl2-partl/, а пространство используемых ею имен называлось http://www.w3.org/2002/06/soap-envelope. Заметьте, что спецификация SOAP 12 состоит из двух частей: part 1 и part2. Вторая часть спецификации - приложение - содержит правила записи сложных типов данных. У спецификации есть еще одна часть partO - примеры посланий, составленных по правилам SOAP 1.2.

Структура SOAP-послания

Спецификация определяет SOAP-послание как документ XML, не содержащий объявление типа документа и инструкций по обработке. Корневой элемент этого документа XML называется . У элемента могут быть атрибуты определяющие пространства имен,

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

xmlns:env="http://www.w3.org/2002/06/soap-envelope">

< ! - Блоки заголовка ->

Элемент

, если он есть в послании, записывается первым в теле элемента . Кроме атрибутов xmlns, в нем может быть атрибут actor, указывающий адресом URI конкретный SOAP-сервер, которому предназначено послание.

Дело в том, что SOAP-послание может пройти через несколько SOAP- серверов или через несколько приложений на одном сервере. Эти приложения выполняют предварительную обработку блоков заголовка послания и передают его друг другу. Все эти серверы и/или приложения называются SOAP-узлами (SOAP nodes). Спецификация SOAP не определяет правила прохождения послания по цепочке серверов. Для этого разрабатываются другие протоколы, например, Microsoft WS-Routing.

Атрибут actor задает целевой SOAP-узел - тот, который расположен в конце цепочки и будет обрабатывать заголовок полностью. Значение

атрибута actor показывает, что обрабатывать заголовок будет первый же сервер, получивший Атрибут actor может встречаться в отдельных блоках заголовка, указывая узел- обработчик этого блока. После обработки блок удаляется из SOAP- послания.

В версии 1.2 атрибут actor заменен атрибутом role, потому что в этой версии SOAP каждый узел играет одну или несколько ролей. Спецификация пока определяет три роли SOAP-узла.

Роль http://^^.w3.org/2002/06/soap-envelope/role/ultimateReceiver играет конечный, целевой узел, который будет обрабатывать заголовок.

Роль http://www.w3.org/2002/06/soap-envelope/role/next играет промежуточный или целевой узел. Такой узел может играть и другие, дополнительные роли.

Роль http://www.w3.org/2002/06/soap-envelope/role/none не должен играть ни один SOAP-узел.

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

Значением атрибута role может быть любая строка URI, показывающая роль узла, которому предназначен данный блок заголовка. Значением по умолчанию для этого атрибута служит пустое значение, то есть, просто пара кавычек, или строка URI http://\vw\v.w3.org/2002/06/soap-envelope/rale/ultimateReceiver.

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

Еще один атрибут элемента

, называемый urnstUnderstand, принимает значения о или 1. Его значение по умолчанию равно о. Если атрибут mustunderstand равен 1, то SOAP-узел при обработке элемента обязательно должен учитывать его синтаксис, определенный в схеме документа, или совсем не обрабатывать послание. Это повышает точность обработки послания.

В версии SOAP 1.2 вместо цифры о надо писать слово false, а вместо цифры 1 писать слово true.

В тело заголовка

можно вложить произвольные элементы, ранее называвшиеся статьями (entries) заголовка. В версии 1.2 они называются блоками (blocks) заголовка. Их имена обязательно помечаются префиксами. В блоках заголовка могут встретиться атрибуты role или actor и mustunderstand. Их действие будет относиться только к данному блоку. Это позволяет обрабатывать отдельные блоки заголовка промежуточными SOAP- узлами, теми, чья роль совпадает с ролью, указанной атрибутом role. В листинге 3.1 приведен пример такого блока.

Листинг 3.1. Заголовок с одним блоком

xmlns:t="http://some.com/transaction" env:role=

"http://www.w3.org/2002/06/soap-envelope/role/ultimateReceiver" env:mustUnderstand="1">

Элементы, вложенные в блоки заголовка, уже не называются блоками. Они не могут содержать атрибуты role, actor И mustunderstand.

Элемент обязательно записывается сразу за элементом

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

Сообщение об ошибке

Если SOAP-сервер, обрабатывая поступившее к нему SOAP-послание, заметит ошибку, то он прекратит обработку и отправит клиенту SOAP- послание, в тело которого запишет один элемент с сообщением об ошибке.

В сообщении, записанном в теле элемента версии SOAP 1.1 выде

ляются четыре части, описанные следующими вложенными элементами.

Код ошибки - сообщение, показывающее тип ошибки. Оно предназначено для программы, обрабатывающей ошибки.

Описание ошибки - словесное описание типа ошибки, предназначенное для человека.

Место обнаружения ошибки - адрес URI сервера, заметившего ошибку. Полезно, когда послание проходит цепочку SOAP- узлов, для уточнения природы ошибки. Промежуточные SOAP-узлы обязательно записывают этот элемент, целевой SOAP-сервер не обязан это делать.

Детали ошибки - описывают ошибки, встреченные в теле послания, но не в его заголовке. Если при обработке тела ошибки не обнаружены, то этот элемент отсутствует.

Например:

xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">

env:MustUnderstand SOAP Must Understand Error

Версия SOAP 1.2 изменила содержание элемента Как описано в

пространстве имен http://www.w3.org/2002/06/soap-envelope, в него входят два обязательных элемента и три необязательных элемента.

Обязательные элементы.

Код ошибки . Он содержит обязательный вложенный элемент <:value> с кодом ошибки и необязательный вложенный элемент , содержащий, опять-таки, элемент с уточняющим кодом ошибки и элемент , и далее все повторяется рекурсивно.

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

Необязательные элементы.

? - адрес URI промежуточного SOAP-узла, заметившего ошибку.

? - роль SOAP-узла, заметившего ошибку.

? - описание ошибки, замеченной при обработке тела послания, но не заголовка.

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

Листинг 3.2. Сообщение об ошибке

xmlns:env="http://www.w3.org/2002/06/soap-envelope" xmlns:rpc=’http://www.w3.org/2002/06/soap-rpc’>

env:Sender

rpc:BadArgumentsc/env:Value>

Ptocessing ETror

xmlns:e="http://www.example.org/faults"> №me does not match 999

Типы ошибок

Список кодов ошибок постоянно меняется и расширяется. Версия 1.1 определяет четыре типа ошибок.

VersionMismatch - пространство имен неопознано. Может быть, оно устарело или его имя написано неправильно.

MustUnderstand - блок заголовка, помеченный атрибутом mustUnderstand со значением 1, не отвечает своему синтаксису, определенному в схеме документа.

Client - документ XML, содержащий послание, неправильно сформирован и по этой причине сервер не может его обработать. Клиенту следует изменить послание.

Server - сервер не может обработать правильно записанное послание по своим внутренним причинам.

Версия 1.2 определяет пять типов ошибок.

VersionMismatch - пространство имен неопознано. Может быть, оно устарело или его название написано неправильно, или в послании встретилось имя элемента XML, не определенное в этом пространстве имен. В заголовок ответа сервер записывает элемент , перечисляющий вложенными элементами правильные названия пространств имен, понимаемые сервером. Ответ сервера показан в листинге 3.3.

MustUnderstand - блок заголовка, помеченный атрибутом mustunderstand со значением true, не отвечает своему синтаксису, определенному в схеме документа. Сервер записывает в заголовок ответа элементы , атрибут qname которых содержит имя неправильного блока. Листинг 3.4 содержит пример ответа, который будет сделан сервером, если заголовок листинга 3.1 окажется неправильно записанным.

DataEncodingUnknown - в послании встретились непонятные данные, может быть, они записаны в неизвестной кодировке.

Sender - документ XML, содержащий послание, неправильно сформирован и по этой причине сервер не может его обработать. Клиенту следует изменить послание.

Receiver - сервер не может обработать правильно записанное послание по своим внутренним причинам, например, отсутствует нужный XML- парсер.

Сервер может добавить к этим типам ошибок какие-то свои типы. Обычно

они детализируют стандартные типы, и сообщения о них появляются в элементах , как было показано выше в листинге 3.2.

? Листинг 3.3. Ответ сервера с сообщением об ошибке типа VersionMismatch

xmlns:env="http://www.w3.org/2002/06/soap-envelope">

xmlns:upg="http://www.w3.org/2002/06/soap-upgrade">

xmlns:nsl="http://www.w3.org/2002/06/soap-envelope"/>

xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/"/>

env:VersionMismatch

Version Mismatch

ЛистонгЗ.4. Ответ сервера с сообщением об ошибке типа MustUnderstand

xmlns:t=’http://some.com/transaction’ />

env:MustUnderstand

One or more mandatory headers not understood

Литература:

Хабибуллин И. Ш. Разработка Web-служб средствами Java. - СПб.: БХВ-Петербург, 2003. - 400 с: ил.

Заголовок топика – это действительно вопрос, т.к. я сам не знаю, что это и впервые попробую поработать с этим в рамках настоящей статьи. Единственное, что могу гарантировать, что код, представленный ниже, будет работать, однако мои фразы будут лишь предположениями и догадками о том, как я сам все это понимаю. Итак, поехали…

Введение

Начать надо с того, для чего создавалась концепция веб-сервисов. К моменту появления этого понятия в мире уже существовали технологии, позволяющие приложениям взаимодействовать на расстоянии, где одна программа могла вызвать какой-нибудь метод в другой программе, которая при этом могла быть запущена на компьютере, расположенном в другом городе или даже стране. Все этого сокращенно называется RPC (Remote Procedure Calling – удаленный вызов процедур). В качестве примеров можно привести технологии CORBA, а для Java – RMI (Remote Method Invoking – удаленный вызов методов). И все вроде в них хорошо, особенно в CORBA, т.к. с ней можно работать на любом языке программирования, но чего-то все же не хватало. Полагаю, что минусом CORBA является то, что она работает через какие-то свои сетевые протоколы вместо простого HTTP, который пролезет через любой firewall. Идея веб-сервиса заключалась в создании такого RPC, который будет засовываться в HTTP пакеты. Так началась разработка стандарта. Какие у этого стандарта базовые понятия:
  1. SOAP . Прежде чем вызвать удаленную процедуру, нужно этот вызов описать в XML файле формата SOAP. SOAP – это просто одна из многочисленных XML разметок, которая используется в веб-сервисах. Все, что мы хотим куда-то отправить через HTTP, сначала превращается в XML описание SOAP, потом засовывается в HTTP пакет и посылается на другой компьютер в сети по TCP/IP.
  2. WSDL . Есть веб-сервис, т.е. программа, методы которой можно удаленно вызывать. Но стандарт требует, чтобы к этой программе прилагалось описание, в котором сказано, что «да, вы не ошиблись – это действительно веб-сервис и можно у него вызвать такие-то такие-то методы». Такое описание представляется еще одним файлом XML, который имеет другой формат, а именно WSDL. Т.е. WSDL – это просто XML файл описания веб-сервиса и больше ничего.
Почему так кратко спросите вы? А по подробней нельзя? Наверное можно, но для этого придется обратиться к таким книгам как Машнин Т. «Web-сервисы Java». Там на протяжении первых 200 страниц идет подробнейшее описание каждого тега стандартов SOAP и WSDL. Стоит ли это делать? На мой взгляд нет, т.к. все это на Java создается автоматически, а вам нужно лишь написать содержимое методов, которые предполагается удалено вызывать. Так вот, в Java появился такой API, как JAX-RPC. Если кто не знает, когда говорят, что в Java есть такой-то API, это означает, что есть пакет с набором классов, которые инкапсулируют рассматриваемую технологию. JAX-RPC долго развивался от версии к версии и в конечном итоге превратился в JAX-WS. WS, очевидно, означает WebService и можно подумать, что это простое переименование RPC в популярное нынче словечко. Это не так, т.к. теперь веб-сервисы отошли от первоначальной задумки и позволяют не просто вызывать удаленные методы, но и просто посылать сообщения-документы в формате SOAP. Зачем это нужно я пока не знаю, вряд ли ответ здесь будет «на всякий случай, вдруг понадобится». Сам бы хотел узнать от более опытных товарищей. Ну и последнее, далее появился еще JAX-RS для так называемых RESTful веб-сервисов, но это тема отдельной статьи. На этом введение можно заканчивать, т.к. далее мы будем учиться работать с JAX-WS.

Общий подход

В веб-сервисах всегда есть клиент и сервер. Сервер – это и есть наш веб-сервис и иногда его называют endpoint (типа как, конечная точка, куда доходят SOAP сообщения от клиента). Нам нужно сделать следующее:
  1. Описать интерфейс нашего веб-сервиса
  2. Реализовать этот интерфейс
  3. Запустить наш веб-сервис
  4. Написать клиента и удаленно вызвать нужный метод веб-сервиса
Запуск веб-сервиса можно производить разными способами: либо описать класс с методом main и запустить веб-сервис непосредственно, как сервер, либо задеплоить его на сервер типа Tomcat или любой другой. Во втором случае мы сами не запускаем новый сервер и не открываем еще один порт на компьютере, а просто говорим контейнеру сервлетов Tomcat, что «мы написали тут классы веб-сервиса, опубликуй их, пожалуйста, чтобы все, кто к тебе обратиться, могли нашим веб-сервисом воспользоваться». В независимости от способа запуска веб-сервиса, клиент у нас будет один и тот же.

Сервер

Запустим IDEA и создадим новый проект Create New Project . Укажем имя HelloWebService и нажмем кнопку Next , далее кнопку Finish . В папке src создадим пакет ru.javarush.ws . В этом пакете создадим интерфейс HelloWebService: package ru. javarush. ws; // это аннотации, т.е. способ отметить наши классы и методы, // как связанные с веб-сервисной технологией import javax. jws. WebMethod; import javax. jws. WebService; import javax. jws. soap. SOAPBinding; // говорим, что наш интерфейс будет работать как веб-сервис @WebService // говорим, что веб-сервис будет использоваться для вызова методов @SOAPBinding (style = SOAPBinding. Style. RPC) public interface HelloWebService { // говорим, что этот метод можно вызывать удаленно @WebMethod public String getHelloString (String name) ; } В этом коде классы WebService и WebMethod являются так называемыми аннотациям и ничего не делают, кроме как помечают наш интерфейс и его метод, как веб-сервис. Это же относится и к классу SOAPBinding . Разница лишь в том, что SOAPBinding – это аннотация с параметрами. В данном случае используется параметр style со значением, говорящим, что веб-сервис будет работать не через сообщения-документы, а как классический RPC, т.е. для вызова метода. Давайте реализуем логику нашего интерфейса и создадим в нашем пакете класс HelloWebServiceImpl . Кстати, замечу, что окончание класса на Impl – это соглашение в Java, по которому так обозначают реализацию интерфейсов (Impl – от слова implementation, т.е. реализация). Это не требование и вы вольны назвать класс как хотите, но правила хорошего тона того требуют: package ru. javarush. ws; // таже аннотация, что и при описании интерфейса, import javax. jws. WebService; // но здесь используется с параметром endpointInterface, // указывающим полное имя класса интерфейса нашего веб-сервиса @WebService (endpointInterface = "ru.javarush.ws.HelloWebService" ) public class HelloWebServiceImpl implements HelloWebService { @Override public String getHelloString (String name) { // просто возвращаем приветствие return "Hello, " + name + "!" ; } } Запустим наш веб-сервис как самостоятельный сервер, т.е. без участия всяких Tomcat и серверов приложений (это тема отдельного разговора). Для этого в структуре проекта в папке src создадим пакет ru.javarush.endpoint , а в нем создадим класс HelloWebServicePublisher с методом main: package ru. javarush. endpoint; // класс, для запуска веб-сервера с веб-сервисами import javax. xml. ws. Endpoint; // класс нашего веб-сервиса import ru. javarush. ws. HelloWebServiceImpl; public class HelloWebServicePublisher { public static void main (String. . . args) { // запускаем веб-сервер на порту 1986 // и по адресу, указанному в первом аргументе, // запускаем веб-сервис, передаваемый во втором аргументе Endpoint. publish ("http://localhost:1986/wss/hello" , new HelloWebServiceImpl () ) ; } } Теперь запустим этот класс, нажав Shift+F10 . В консоли ничего не появится, но сервер запущен. В этом можно убедиться набрав в браузере строку http://localhost:1986/wss/hello?wsdl . Открывшаяся страница, с одной стороны, доказывает, что у нас на компьютере (localhost) запустился веб-сервер (http://) на порту 1986, а, с другой стороны, показывает WSDL описание нашего веб-сервиса. Если вы остановите приложение, то описание станет недоступно, как и сам веб-сервис, поэтому делать этого не будем, а перейдем к написанию клиента.

Клиент

В папке проекта src создадим пакет ru.javarush.client , а в нем класс HelloWebServiceClient с методом main: package ru. javarush. client; // нужно, чтобы получить wsdl описание и через него // дотянуться до самого веб-сервиса import java. net. URL; // такой эксепшн возникнет при работе с объектом URL import java. net. MalformedURLException; // классы, чтобы пропарсить xml-ку c wsdl описанием // и дотянуться до тега service в нем import javax. xml. namespace. QName; import javax. xml. ws. Service; // интерфейс нашего веб-сервиса (нам больше и нужно) import ru. javarush. ws. HelloWebService; public class HelloWebServiceClient { public static void main (String args) throws MalformedURLException { // создаем ссылку на wsdl описание URL url = new URL ("http://localhost:1986/wss/hello?wsdl" ) ; // Параметры следующего конструктора смотрим в самом первом теге WSDL описания - definitions // 1-ый аргумент смотрим в атрибуте targetNamespace // 2-ой аргумент смотрим в атрибуте name QName qname = new QName ("http://ws.сайт/" , "HelloWebServiceImplService" ) ; // Теперь мы можем дотянуться до тега service в wsdl описании, Service service = Service. create (url, qname) ; // а далее и до вложенного в него тега port, чтобы // получить ссылку на удаленный от нас объект веб-сервиса HelloWebService hello = service. getPort (HelloWebService. class ) ; // Ура! Теперь можно вызывать удаленный метод System. out. println (hello. getHelloString ("JavaRush" ) ) ; } } Максимум комментариев по коду я дал в листинге. Добавить мне нечего, поэтому запускаем (Shift+F10). Мы должны в консоли увидеть текст: Hello, JavaRush! Если не увидели, то видимо забыли запустить веб-сервис.

Заключение

В данном топике был представлен краткий экскурс в веб-сервисы. Еще раз скажу, что многое из того, что я написал – это мои догадки по поводу того, как это работает, и поэтому мне не стоит сильно доверять. Буду признателен, если знающие люди меня поправят, ведь тогда я чему-нибудь научусь. UPD.

Brett McLaughlin Перевод Илья Чекменев

SOAP - это простой протокол доступа к объектам (Simple Object Access Protocol). Если вы никогда прежде о нем не слышали, то должно быть вы живете в какой-нибудь глуши, вдали от цивилизации. Он стал последним писком моды в web программировании, и неотъемлемой частью web сервисов, которые с таким фанатизмом используются в web разработках последнего поколения. Если вы слышали о.NET, детище Microsoft, или peer-to-peer "революции", то вы слышали о технологиях, которые основаны на использовании SOAP (даже если вы не знаете что это такое). Существует не одна, а две реализации SOAP, от Apache и от Microsoft, которой посвящены тысячи страниц на их сайте технической поддержки MSDN (http://msdn.microsoft.com/).

В этой статье я расскажу вам что такое SOAP и почему он является такой важной частью в процессе развития парадигмы web программирования. Это поможет вам опустить фундаментальные основы и сразу приступить непосредственно к работе с инструментарием SOAP. Затем я дам беглый обзор существующих SOAP проектов и углубляюсь в реализацию от Apache. Эта статья не претендует на воссоздание полной картины SOAP, в моей книге "Java & XML, 2-я редакция " восполнено множество пробелов. Ответы на многие из вопросов, возникших после прочтения этой статьи вы найдете в книге.

Вступление

Для начала нужно разобраться в том, что же такое SOAP. Вы можете прочитать полное (и весьма длинное) заключение W3C по адресу http://www.w3.org/TR/SOAP . Затем, разобравшись и отбросив всю шелуху, вы поймете что SOAP это всего лишь протокол. Это простой протокол (для его использования, нет необходимости в написании нового), основанный на идее, что в некоторый момент в распределенной архитектуре возникает необходимость обмена информацией. Кроме того, для систем, в которых существует вероятность перегрузок и затруднений при обработке процессов, этот протокол весьма выгоден тем, что он легковесен и требует минимального количества ресурсов. Наконец, он позволяет осуществлять все операции через HTTP, что дает возможность обойти стороной такие хитрые штуки как firewall и уберечься от прослушивания при помощи сокетов немыслимого числа портов. Главное чтобы вы осознали это, а все остальное - детали.

Разумеется, вы хотели бы знать эти детали, и я не обойду их вниманием. В спецификации SOAP существует три базовых компонента: конверт SOAP (SOAP envelope), набор правил шифровки и средства взаимодействия между запросом и ответом. Давайте думать о сообщении SOAP как об обычном письме. Вы еще помните эти древние штуки в конвертах с почтовой маркой и адресом, записанном на лицевой стороне? Такая аналогия поможет более наглядно представить себе концепцию SOAP как "конверт". Рисунок 12-1 изображает SOAP процессы в форме этой аналогии.

Рисунок 12-1. Процесс сообщений SOAP

Запомните эту картинку и давайте рассмотрим три компонента спецификации SOAP. Я коротко расскажу о каждом из них, приводя примеры, наиболее полно представляющие эту концепцию. Эти три ключевые компонента делают SOAP столь важным и значимым. Обработка ошибок, поддержка различных шифровок, сериализация параметров, и тот факт, что SOAP работает через HTTP в большинстве случаев делают его привлекательнее прочих решений для распределенных протоколов. SOAP обеспечивает высокую степень взаимодействия с другими приложениями, которые я рассмотрел более подробно в своей книге. А сейчас я хочу сосредоточиться на основных элементах SOAP.

Конверт

Конверт SOAP аналогичен конверту обычного письма. Он содержит информацию о письме, которое будет шифровано в основном разделе SOAP, включая данные о получателе и отправителе, а также информация о самом сообщении. Например, заголовок конверта SOAP может указывать на то, как должно обрабатываться сообщение. Прежде чем приложение начнет обработку сообщения, оно анализирует информацию о сообщении, включая информацию о том, сможет ли оно вообще обработать это сообщение. В отличие от ситуации со стандартными XML-RPC вызовами (припоминаете? XML-RPC сообщения, шифровка и прочее, все объединяется в единый XML фрагмент), с SOAP текущая обработка происходит для того, чтобы узнать что-то о сообщении. Типичное SOAP сообщение может также включать стиль шифровки, которая поможет получателю в обработке сообщения. Пример 12-1 демонстрирует конверт SOAP, который завершается указанием кодировки.

Пример 12-1: Конверт SOAP

Soapbox http://www-106.ibm.com/developerworks/library/x-soapbx1.html

Как вы видите, шифровка задана внутри конверта, что позволяет приложению определить (используя значение атрибута encodingStyle ), сможет ли оно прочитать входящее сообщение, расположенное в элементе Body . Убедитесь в правильности пространства имен (namespace) конверта SOAP, или серверы SOAP, которые получат ваше сообщение, выдадут сообщение об ошибке из-за несоответствия версий, и вы не сможете взаимодействовать с ними.

Шифровка

Второй важный элемент SOAP - это возможность шифровки пользовательских типов данных. В RPC (и XML-RPC) шифровка может выполняться лишь для заранее определенных типов данных, которые поддерживаются в скачанном вами XML-RPC инструментарии. Шифровка других типов данных требует от вас самостоятельной модификации RPC сервера и клиента. С SOAP схема XML может быть довольно легко использована для указания новых типов данных (при помощи структуры complexType , рассмотренной во 2-й главе моей книги), и эти новые типы могут быть представлены в XML как часть основного раздела SOAP. Благодаря интеграции со схемой XML, вы можете шифровать любой тип данных в SOAP сообщении, логически описав его в схеме XML.

Вызов

Лучший способ понять как работает вызов SOAP - это сравнить его с чем-нибудь, что вам знакомо, например с XML-RPC. Если вы помните, XML-RPC вызов выглядит подобно фрагменту кода, представленному в Примере 12-2 .

Пример 12-2. Вызов в XML-RPC

// Указание используемого обработчика (парсера) XML XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser"); // Указание сервера, к которому выполняется подключение XmlRpcClient client = new XmlRpcClient("http://rpc.middleearth.com"); // Создание параметров Vector params = new Vector(); params.addElement(flightNumber); params.addElement(numSeats); params.addElement(creditCardType); params.addElement(creditCardNum); // Запрос Boolean boughtTickets = (Boolean)client.execute("ticketCounter.buyTickets", params); // Обработка ответа

Я создал простейшую программу для заказа авиабилетов. Теперь взгляните на Пример 12-3 , который демонстрирует вызов в SOAP.

Пример 12-3. Вызов в SOAP

// Создание параметров Vector params = new Vector(); params.addElement(new Parameter("flightNumber", Integer.class, flightNumber, null)); params.addElement(new Parameter("numSeats", Integer.class, numSeats, null)); params.addElement(new Parameter("creditCardType", String.class, creditCardType, null)); params.addElement(new Parameter("creditCardNumber", Long.class, creditCardNum, null)); // Создание объекта Call Call call = new Call(); call.setTargetObjectURI("urn:xmltoday-airline-tickets"); call.setMethodName("buyTickets"); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); call.setParams(params); // Вызов Response res = call.invoke(new URL("http://rpc.middleearth.com"), ""); // Обработка ответа

Как вы видите, собственно вызов, представленный объектом Call , резидентен в памяти. Он позволяет вам задать цель вызова, метод вызова, стиль шифровки, параметры, и многие другие параметры, не представленное в этом примере. Это более гибкий механизм, чем метод XML-RPC, позволяющий вам явно задавать набор различных параметров, которые косвенно определяются в XML-RPC. Далее в этой статье вы узнаете больше о процессе вызова, в том числе вы узнаете как SOAP обрабатывает неверные запросы, иерархию ошибок и, разумеется, возвращаемые результаты вызова.

После такого краткого введения вы уже знаете достаточно, чтобы заинтересоваться этой забавной штукой. А теперь позвольте мне представить вам реализацию SOAP, которую я собираюсь использовать. Я объясню причины по которым остановил свой выбор именно на ней и рассмотрю некоторые примеры кода.

Настройка

Теперь, когда вы познакомились с основами концепции, настало время для самой интересной части: программирования. Для этого вам потребуется удобный проект или продукт, найти который проще чем может показаться на первый взгляд. Если вам нужен Java проект, предоставляющий возможности SOAP, то его не надо долго искать. Существует две группы продуктов: коммерческие и бесплатные. Как и в своей книге, я буду избегать упоминания коммерческих продуктов. Это вовсе не потому что они плохи (даже наоборот, некоторые из них прекрасны), а потому что я хотел бы чтобы любой читатель мог попробовать любой из приведенных примеров. Это связано с доступностью, которой многие коммерческие продукты не обладают. Вы должны заплатить за их использование, или временно использовать их в течении ограниченного периода времени после скачивания.

Таким образом мы плавно подошли к проектам с открытым источником (open source). Из этой области я могу назвать лишь один продукт: Apache SOAP. Он расположен по адресу http://xml.apache.org/soap и предоставляет инструментарий SOAP для Java. На момент написания книги вышла версия 2.2, которую вы можете скачать с web сайта Apache. Именно эту версию я и буду использовать в примерах для этой статьи.

Другие альтернативы

Прежде чем перейти к инсталляции и настройке Apache SOAP я отвечу на несколько вопросов, которые могли закрасться в ваш разум. По-моему я достаточно ясно объяснил причины по которым не использую коммерческие продукты. Тем не менее, вы можете подумать о некоторых других проектах с открытым источником или родственных им, которые вам хотелось бы использовать, и вы удивлены что я их никак не прокомментировал.

Как насчет IBM SOAP4J?

Первым в списке альтернатив значится реализация от IBM: SOAP4J. Работа IBM легла в основу проекта Apache SOAP, также как IBM XML4J переросла в то, что теперь известно как проект XML парсера Apache Xerces. Предполагается что реализация от IBM будет переработана, объединившись с Apache SOAP. Примерно то же случилось с IBM"овским XML4J: теперь он лишь обеспечивает пакетирование в Xerces. Это только лишь подчеркивает тенденции - крупные производители зачастую поддерживают и используют OpenSource проекты, в данном случае оба проекта (Apache и IBM) используют одну и ту же кодовую базу.

Разве Microsoft вне игры?

Разумеется нет. Microsoft и его реализация SOAP, равно как и все направление.NET (более подробно рассмотренное в моей книге), весьма значительны. В действительности я хотел уделить большую часть времени детальному рассмотрению реализации SOAP от Microsoft, но она поддерживает только COM объекты иже с ними и не поддерживает Java. Ввиду этих причин подобное описание не могло войти в статью про Java и XML. Тем не менее, Microsoft (несмотря на все претензии, которые мы, как разработчики, имеем к этой компании) проделала важную работу в сфере web сервисов, и вы совершите ошибку если без раздумий ее отвергнете, руководствуясь лишь голыми эмоциями. Если у вас есть необходимость работать с COM или компонентами Visual Basic, я настоятельно рекомендую вам попробовать использовать инструментарий Microsoft SOAP, доступный по адресу http://msdn.microsoft.com/library/default.asp?url=/nhp/Default.asp?contentid=28000523 наряду с множеством других ресурсов SOAP.

Что такое Axis?

Те из вас, кто следит за деятельностью Apache, должно быть слышали об Apache Axis. Axis это инструментарий SOAP следующего поколения, разрабатываемый также под эгидой Apache XML. За SOAP (спецификацией, а не специфической реализацией), стремительно и радикально развивающейся в последнее время, следить весьма трудно. Попытаться создать версию SOAP, полностью соответствующую текущим требованиям, изменяющимся в ходе развития, также довольно сложно. В результате, текущая версия Apache SOAP предлагает некое решение, ограниченное его конструкцией. Решив что не стоит пытаться полностью перепроектировать существующий инструмент, разработчики Apache приступили к созданию проекта на базе нового кода. Так родился Axis. Название SOAP также претерпело изменение, сначала из SOAP превратившись в XP, а затем в XMLP. Затем из имени нового SOAP было исключено название спецификации и родилось название "Axis". Но сейчас похоже что W3C вновь возвращается к названию спецификации SOAP (версии 1.2 или 2.0), так что все еще может поменяться и путаницы будет еще больше!

Думайте об IBM SOAP4J как об архитектуре?1 инструментария SOAP. А об Apache SOAP (рассматриваемой в этой статье), как об архитектуре?2. А Axis представляет собой архитектуру?3, архитектуру нового поколения. Этот проект использует SAX, тогда как Apache SOAP базируется на DOM. Кроме того, Axis, в отличие от Apache SOAP, предоставляет более дружественный подход при взаимодействии с пользователем. После перечисления этих достоинств вы наверное придете в недоумение, почему я не выбрал в качестве предмета изучения Axis. Просто это было бы несколько преждевременно. В настоящее время готовится к выходу лишь версия 0.51 Axis. Это еще не бета, и даже не альфа версия. Я с удовольствием мог бы расписывать новые возможности Axis, но у вас не было бы никаких шансов убедить ваше руководство в возможности использования программного обеспечения с открытым источником версии ниже альфы для нужд вашей сверх важной системы. Поэтому я решил сфокусироваться на чем-то, что вы реально можете использовать уже сегодня - Apache SOAP. Я думаю что к моменту выхода финальной версии Apache Axis, я обновлю этот материал в следующем издании своей книги. А до тех пор давайте сосредоточимся на решении, которое уже доступно.

Установка

Возможны две формы установки SOAP. Первая - это запуск клиента SOAP, используя SOAP API для связи с сервером, который может принимать сообщения SOAP. Второй способ - запуск сервера SOAP, который может получать сообщения от клиента SOAP. В этом разделе я описал обе процедуры.

Клиент

Для использования клиента SOAP вам необходимо сначала скачать Apache SOAP, доступный на http://xml.apache.org/dist/soap . Я скачал версию 2.2 в бинарном формате (из подкаталога version-2.2 ). Затем вы должны разархивировать содержимое архива в директорию на вашем компьютере. В моем случае это была директория javaxml2 (c:\javaxml2 на моем компьютере с Windows, /javaxml2 на моем компьютере с Mac OS X). В результате файлы разархивировались в /javaxml2/soap-2_2 . Вам также потребуется скачать пакет JavaMail, доступный на сервере Sun http://java.sun.com/products/javamail/ . Он потребуется для поддержки протокола передачи SMTP, используемого в Apache SOAP. Затем скачайте Java Beans Activation Framework (JAF), также доступный на сервере Sun http://java.sun.com/products/beans/glasgow/jaf.html . Исходя из предположения что у вас уже установлен и готов к использованию Xerces или другой XML парсер.

Примечание: Убедитесь в том, что ваш XML парсер JAXP-совместимый и корректно использует пространство имен. Скорее всего ваш парсер удовлетворяет этим требованиям.Если у вас возникли проблемы, лучше вернуться к использованию Xerces.

Примечание: Используйте последние версии Xerces. Версия 1.4 и выше подойдет. Существует ряд ошибок при работе с SOAP и Xerces 1.3(.1), поэтому я советую не использовать такое сочетание.

Разархивируйте JavaMail и JAF пакеты, а затем включите их jar файлы в ваш classpath, а также библиотеку soap.jar . Каждый из этих jar файлов должен находиться либо в корневом каталоге соответствующей программы, или в подкаталоге /lib . По завершении ваша переменная classpath должна выглядеть примерно следующим образом:

$ echo $CLASSPATH /javaxml2/soap-2_2/lib/soap.jar:/javaxml2/lib/xerces.jar: /javaxml2/javamail-1.2/mail.jar:/javaxml2/jaf-1.0.1/activation.jar

Для Windows она будет выглядеть так:

c:\>echo %CLASSPATH% c:\javaxml2\soap-2_2\lib\soap.jar;c:\javaxml2\lib\xerces.jar; c:\javaxml2\javamail-1.2\mail.jar;c:\javaxml2\jaf-1.0.1\activation.jar

И, наконец, добавьте директорию javaxml2/soap-2_2/ в ваш classpath для запуска примеров SOAP. Я описал настройку для нескольких примеров, приведенных в этой главе.

Сервер

Чтобы создать SOAP-совместимый набор серверных компонент вам для начала потребуется движок сервлета. Как и в предыдущих главах, в качестве примера для этой главы я использовал Apache Tomcat (доступный на http://jakarta.apache.org/). Вам потребуется добавить все необходимое клиенту в classpath сервера. Самый простой способ сделать это - сбросить soap.jar , activation.jar и mail.jar , а также ваш парсер, в каталог библиотек вашего движка сервлетов. Для Tomcat это каталог /lib, в котором содержатся библиотеки для автоматической загрузки. Если вы хотите обеспечить поддержку скриптов (которые не обсуждаются в этой главе, но есть в примерах Apache SOAP), вам нужно поместить bsf.jar (доступный на http://oss.software.ibm.com/developerworks/projects/bsf) и js.jar (доступный на http://www.mozilla.org/rhino/) в тот же каталог.

Примечание: Если вы используете Xerces c Tomcat, вам нужно будет повторить фокус, который я описывал в главе 10. Переименуйте parser.jar в z_parser.jar , а jaxp.jar в z_jaxp.jar , чтобы убедиться в том, что xerces.jar и включенная версия JAXP загружается перед каким-либо другим парсером или реализацией JAXP.

Затем перезагрузите ваш движок сервлетов, после чего вы будете готовы к написанию серверных компонент SOAP.

Сервлет маршрутизатора и клиент администратора

Помимо основных операций, Apache SOAP включает сервлет маршрутизатора, а также клиент администратора. Даже если вы не собираетесь их использовать, я рекомендую вам установить их, чтобы протестировать правильность установки SOAP. Этот процесс зависит от того, какой движок сервлетов вы используете, поэтому я ограничусь описанием процесса установки для Tomcat. Инструкции по установке для некоторых других движков сервлетов вы найдете на http://xml.apache.org/soap/docs/index.html .

Установка под Tomcat очень проста: просто возьмите файл soap.war из директории soap-2_2/webapps и сбросьте его в директорию $TOMCAT_HOME/webapps - и все! Чтобы проверить установку укажите в броузере адрес http://localhost:8080/soap/servlet/rpcrouter . Вы должны получить ответ, наподобие указанного на рис.12-2 .

Рисунок 12-2. Сервлет RPC маршрутизатора

Несмотря на то что сообщение похоже на сообщение об ошибке, оно свидетельствует о том что все работает правильно. Вы должны получить такой же отклик, указав в броузере адрес клиента администратора: http://localhost:8080/soap/servlet/messagerouter .

В завершение тестирования сервера и клиента, убедитесь в том, что вы полностью следовали всем инструкциям. Затем запустите следующий класс Java, как это показано ниже, для поддержки URL вашего сервлета для сервлета маршрутизатора RPC:

C:\>java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter list Deployed Services:

Вы должны получить пустой список сервисов, как это показано выше. Если вы получите какие-либо сообщения, ознакомьтесь с длинным перечнем возможных ошибок, доступным на http://xml.apache.org/soap/docs/trouble/index.html . Это наиболее полный перечень проблем, с которыми вы могли столкнуться. Если вы получили пустой список, это значит что настройка завершена и вы готовы начать рассмотрение примеров, приведенных в этой главе.

Приступим

Существует три основных этапа в написании любых систем на базе SOAP. Перечислив, я коротко остановлюсь на каждой из них:

  • Выбор между SOAP-RPC и SOAP сообщениями;
  • Написание или получение доступа к SOAP сервису;
  • Написание или получение доступа к SOAP клиенту.

Первым этапом является выбор, будете ли вы использовать SOAP для RPC вызовов (при которых удаленная процедура выполняется на сервере), или сообщения (когда клиент просто посылает фрагменты информации серверу). Я подробно рассматриваю эти процессы далее. После того как вы приняли это решение, вам потребуется получить доступ или создать собственный сервис. Разумеется, поскольку все мы - профессионалы в Java, в этой главе рассказывается о том как создать свой собственный. И, наконец, вам нужно написать клиента для этого сервиса, вот и все дела!

RPC или Messaging?

Ваша первая задача не имеет отношения к программированию и носит скорее дизайнерский характер. Вам нужно выбрать, будете ли вы использовать сервис RPC или сообщения. Будем считать что с RPC вы близко познакомились (например, прочитав одну из глав моей книги). Клиент выполняет удаленную процедуру на сервере, а затем получает отклик. При таком сценарии, SOAP выступает в роли XML-RPC системы с расширенными возможностями, обеспечивающей лучшую обработку ошибок и передачу сложных типов данных по сети. Вы уже знакомы с этой концепцией, и, поскольку в SOAP проще писать именно RPC системы, я начну с них. В этой статье описывается создание RPC сервиса, RPC клиента, и запуск системы в действие.

Другой стиль работы SOAP основан на обмене сообщениями. Вместо выполнения удаленных процедур, он используется только для обмена информацией. Как вы можете догадаться, это мощный инструмент, не требующий знания клиентом отдельных методов какого-либо сервера. Он также делает моделирование удаленных систем более изолированным, позволяя использовать пакеты данных (пакеты в фигуральном смысле, а не в сетевом) для передачи другим системам. При этом другим системам не обязательно знать об операциях, которые совершались с этими данными. Такой стиль сложнее чем RPC программирование, поэтому я не буду риводить его здесь. Вы найдете его в моей книге, наряду с другими деталями бизнес-бизнес взаимодействия. А для начала познакомьтесь с SOAP-RPC программированием.

Как и большинство дизайнерских проблем, принятие этого решения зависит только от вас. Проанализируйте ваше приложение и постарайтесь определить для чего вам нужно использовать SOAP. Если у вас есть сервер и набор клиентов, которые выполняют специфические бизнес функции по запросу, то вам более подходит RPC. В сложных системах, в которых обмен данными - нечто более чем просто выполнение специфических бизнес функций по запросу, гораздо предпочтительней использование сообщений SOAP.

RPC сервис

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

Фрагменты кода

Я начну с рассмотрения фрагментов кода для сервера. Эти фрагменты представляют собой классы с методами, выполняемыми для RPC клиентов . В качестве примеров я использовал код из своей книги. Вместо того, чтобы использовать простые классы, я выбрал более сложный пример чтобы как можно наглядней продемонстрировать возможности SOAP. Итак, в качестве примера я использовал класс CD. Сначала определяем элемент map для каждого нестандартного типа параметров. Для атрибута encodingStyle , по крайней мере в Apache SOAP 2.2. вы должны указать значение http://schemas.xmlsoap.org/soap/encoding/ . На данный момент это единственная поддерживаемая кодировка. Вам нужно указать пространство имен для типа, определяемого пользователем, а затем имя класса с префиксом пространства имен для этого типа. В нашем случае для этих целей я использовал выдуманное пространство имен и простой префикс "x ". Затем, используя атрибут javaType , задал реальное имя Java класса (для этого случая - javaxml2.CD ). И, наконец, куралесил с атрибутами java2XMLClassName и xml2JavaClassName . С их помощью задается класс, конвертируемый из Java в XML и наоборот. Я использовал потрясающе удобный класс BeanSerializer, также входящий в комплект поставки Apache SOAP. Если ваш пользовательский параметр в формате JavaBean, этот сериализатор и десериализатор избавит вас от необходимости писать свой собственный. Вам нужен класс с конструктором по умолчанию (вспомните, для класса CD я задал простой, без каких-либо параметров, конструктор), и публикация всех данных этого класса при помощи методов setXXX и getXXX . Поскольку класс CD прекрасно удовлетворяет всем этим требованиям, BeanSerializer работает идеально.

Примечание: То, что класс CD соответствует требованиям BeanSerializer . не имеет большого значения. Большинство классов легко приводятся к этому формату. Поэтому я советую избегать написания собственных сериализаторов и десериализаторов. Это лишняя головная боль (ничего сложного, но слишком кропотливо) и рекомендую вам сэкономить силы и использовать в своих пользовательских параметрах конвертацию бинов. Во многих случаях преобразования бинов требуют лишь наличия в вашем классе конструктора по умолчанию (без параметров).

Теперь повторно воссоздадим jar файл и переразместим наш сервис:

(gandalf)/javaxml2/Ch12$ java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter xml/CDCatalogDD.xml

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

Теперь осталось модифицировать клиент для использования новых классов и методов. Пример 12-10 содержит модифицированную версию клиентского класса CDAdder . Изменения, внесенные в предыдущую версию, выделены.

Пример 12-10: Обновленный класс CDAdder

package javaxml2; import java.net.URL; import java.util.Vector; import org.apache.soap.Constants; import org.apache.soap.Fault; import org.apache.soap.SOAPException; import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.encoding.soapenc.BeanSerializer; import org.apache.soap.rpc.Call; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Response; import org.apache.soap.util.xml.QName; public class CDAdder { public void add(URL url, String title, String artist, String label) throws SOAPException { System.out.println("Добавление CD с названием "" + title + "" исполнителя "" + artist + "" студии " + label); CD cd = new CD(title, artist, label); // Создание объекта вызова Call Call call = new Call(); call.setSOAPMappingRegistry(registry); call.setTargetObjectURI("urn:cd-catalog"); call.setMethodName("addCD"); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); // Установка параметров Vector params = new Vector(); params.addElement(new Parameter("cd", CD.class, cd, null)); call.setParams(params); // Обработка Invoke вызова Response response; response = call.invoke(url, ""); if (!response.generatedFault()) { System.out.println("Добавление CD успешно завершено."); } else { Fault fault = response.getFault(); System.out.println(Ошибка: " + fault.getFaultString()); } } public static void main(String args) { if (args.length != 4) { System.out.println("Шаблон: java javaxml2.CDAdder " + "\"[Заголовок CD]\" \"[Имя исполнителя]\" \"[Студия CD]\""); return; } try { // URL SOAP сервера, к которому осуществляется подключение URL url = new URL(args); // Get values for new CD String title = args; String artist = args; String label = args; // Add the CD CDAdder adder = new CDAdder(); adder.add(url, title, artist, label); } catch (Exception e) { e.printStackTrace(); } } }

Единственное по-настоящему интересное изменение связано с отображением класса CD :

// Отображение этого типа, чтобы его можно было использовать с SOAP SOAPMappingRegistry registry = new SOAPMappingRegistry(); BeanSerializer serializer = new BeanSerializer(); registry.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("urn:cd-catalog-demo", "cd"), CD.class, serializer, serializer);

Вот каким образом пользовательский параметр может быть кодирован и передан по сети. Я уже рассказывал каким образом класс BeanSerializer может быть использован для обработки параметров в формате JavaBean, например таких как класс CD . Для их указания серверу я использовал дискриптор размещения, несмотря на это теперь мне нужно сообщить клиенту, что нужно использовать этот сериализатор и десериализатор. Эту функцию и выполняет класс SOAPMappingRegistry . Метод mapTypes() берет зашифрованную строку (и вновь для этого лучше использовать константу NS_URI_SOAP_ENC ), и информацию о типе параметра, для которого должна использоваться специальная сериализация. Сначала указывается QName. Вот почему в дискрипторе размещения было использовано странное пространство имен. Вам нужно указать здесь тот же URN, а также локальное имя элемента (для этого примера "CD"), затем Java объект Class класса, который будет сериализован (CD.class ) и, наконец, экземпляр класса для сериализации и десериализации. Для этого примера в обоих случаях будет фигурировать экземпляр BeanSerializer . После того как все эти настройки будут внесены в реестр, сообщите об этом объекту Call при помощи метода setSOAPMapping-Registry() .

Вы можете запустить этот класс, как было показано раньше, добавив CD, и все должно работать как положено:

C:\javaxml2\build>java javaxml2.CDAdder http://localhost:8080/soap/servlet/rpcrouter "Tony Rice" "Manzanita" "Sugar Hill" Добавление CD с заголовком "Tony Rice" исполнителя "Manzanita" студии Sugar Hill Успешное добавление CD.

Я оставил модификацию класса CDLister для вас. Все производится по тому же шаблону. Чтобы проверить себя можете обратиться к файлам с примерами к моей книге, которые уже содержат эти обновленные классы.

Примечание: Вы можете решить что, поскольку класс CDLister напрямую не взаимодействует с объектом CD (возвращаемое методом list() значение имеет тип Hashtable ), то вам не нужно вносить каких-либо изменений. Тем не менее, возвращаемый класс Hashtable содержит экземпляры объекта CD . Если SOAP не знает как десериализовать их, клиент выдаст сообщение об ошибке. В этом случае для решения проблемы вы должны указать в объекте Call экземпляр SOAPMappingRegistry .

Эффективная обработка ошибок

Теперь, когда вы познакомились с пользовательскими объектами, сделали RPC вызовы и прочее, позвольте мне рассказать о менее увлекательной теме: обработке ошибок. При любой сетевой транзакции может произойти множество сбоев. Не запускается сервис, ошибка в работе сервера, не удается найти объект, отсутствуют классы и множество прочих проблем. До сих пор я просто использовал метод fault.getString() для генерации сообщений об ошибках. Но этот метод не всегда может оказаться полезным. Чтобы увидеть его в действии, снимите комментарий в конструкторе CDCatalog :

public CDCatalog() { //catalog = new Hashtable(); // Создание каталога addCD(new CD("Nickel Creek", "Nickel Creek", "Sugar Hill")); addCD(new CD("Let it Fall", "Sean Watkins", "Sugar Hill")); addCD(new CD("Aerial Boundaries", "Michael Hedges", "Windham Hill")); addCD(new CD("Taproot", "Michael Hedges", "Windham Hill")); }

Перекомпилируйте его, перезапустите движок сервлета и переразместите его. В результате этого возникнет исключительная ситуация NullPointerException при попытке конструктора класса добавить CD в неинициализированный Hashtable . При запуске клиента появится сообщение об ошибке, но оно будет не очень информативным:

(gandalf)/javaxml2/build$ java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcrouter Просмотр текущего каталога CD. Ошибка: Не удается разрешить целевой объект(Unable to resolve target object): null

Это совсем не та информация, которая может помочь при обнаружении и исправлении ошибки. Тем не менее фреймуорк исправно справляется с обработкой ошибок. Вы помните DOMFaultListener , который вы задавали как значение элемента faultListener ? Настал его час вступить в игру. Возвращаемый в случае ошибки объект Fault содержит DOM (объектную модель документа) org.w3c.dom.Element с детальной информацией об ошибке. Сначала добавьте в исходный код выражение для импортирования java.util.Iterator :

import java.net.URL; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Vector; import org.apache.soap.Constants; import org.apache.soap.Fault; import org.apache.soap.SOAPException; import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.encoding.soapenc.BeanSerializer; import org.apache.soap.rpc.Call; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Response; import org.apache.soap.util.xml.QName;

Теперь внесем изменения для обработки ошибок в методе list():

if (!response.generatedFault()) { Parameter returnValue = response.getReturnValue(); Hashtable catalog = (Hashtable)returnValue.getValue(); Enumeration e = catalog.keys(); while (e.hasMoreElements()) { String title = (String)e.nextElement(); CD cd = (CD)catalog.get(title); System.out.println(" "" + cd.getTitle() + "" исполнителя " + cd.getArtist() + " студии " + cd.getLabel()); } } else { Fault fault = response.getFault(); System.out.println("Ошибка: " + fault.getFaultString()); Vector entries = fault.getDetailEntries(); for (Iterator i = entries.iterator(); i.hasNext();) { org.w3c.dom.Element entry = (org.w3c.dom.Element)i.next(); System.out.println(entry.getFirstChild().getNodeValue()); } }

Используя метод getDetailEntries() вы получаете доступ к поддерживаемым сервисом SOAP и сервером с необработанным данным, с информацией о проблеме. Код повторно обрабатывает их (как правило существует только один элемент, но он требует пристального внимания) и перехватывает DOM Element , содержащийся в каждой записи. По сути дела, вот XML с которым вы работаете:

SOAP-ENV:Server.BadTargetObjectURI Не удается разрешить целевой объект: null Вот то, чего мы хотим!

Иными словами, объект Fault предоставляет вам доступ к части конверта SOAP, которая содержит ошибки. Кроме того, Apache SOAP обеспечивает трассировку стека Java в случае возникновения ошибок, предоставляющую детализованную информацию, необходимую для их исправления. Перехватив элемент stackTrace и распечатав значение узла Text из этого элемента ваш клиент может распечатать трассировку стека сервера. Скомпилировав эти изменения и перезапустив клиент вы получите следующий результат:

C:\javaxml2\build>java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcr outer Просмотр текущего каталога CD. Ошибка: Не удается разрешить целевой объект: null java.lang.NullPointerException в javaxml2.CDCatalog.addCD(CDCatalog.java:24) в javaxml2.CDCatalog.(CDCatalog.java:14) в java.lang.Class.newInstance0(Native Method) в java.lang.Class.newInstance(Class.java:237)

Это немногим лучше, но по крайней мере вы можете видеть лакомную информацию о том, что возникла исключительная ситуация NullPointerException и даже узнать номера строк в классах сервера, в которых возникла эта проблема. Результат этих последних изменений позволил вам получить наглядное представление о проблеме обработки ошибок. Теперь вы должны проверить на наличие ошибок классы вашего сервера. Да, чуть не забыл, перед этим не забудьте обратно изменить ваш класс CDCatalog , чтобы избавиться от намеренно внесенных нами для наглядности ошибок!

  1. Ведется множество разговоров относительно запуска SOAP через другие протоколы, например SMTP (или даже Jabber). Пока стандарт SOAP не предусматривает этого, но подобные возможности могут быть добавлены в будущем. Поэтому не удивляйтесь если встретитесь с активными обсуждениями этой темы.

Что такое SOAP?

SOAP расшифровывается как Simple Object Access Protocol (Простой Протокол Доступа к Объектам). Надеюсь по прочтении статьи вам останется только недоумевать: "Что за странное название?"

SOAP в теперешней его форме – это метод удаленного вызова (RPC, Remote procedure Call) по сети. (Да, он также используется для передачи документов в виде XML, но мы это пока опустим).

Давайте разбираться. Представьте, что у вас есть сервис, который возвращает биржевую котировку (stock quote) для заданного тикера (stock symbol). Он посылает данные на сайт Nasdaq и формирует на основе возвращенного HTML нужный результат. Дальше, чтобы позволить другим разработчикам использовать его внутри своих приложений, вы делаете из этого сервиса компонент, который через Интернет находит информацию о котировках. Работает он отлично, пока в один прекрасный день Nasdaq не меняет разметку своих страниц. Вам приходится пересмотреть всю логику работы компонента и разослать обновления всем разработчикам, использующим его. А им в свою очередь необходимо разослать обновления всем своим пользователям. Если это происходит на более-менее постоянной основе, вы можете нажить немало врагов среди коллег-разработчиков. А с программистами, как известно, шутки плохи. Вы же не хотите завтра доставать фотографию любимого кота из офисного шредера, правда?

Что же делать? Посмотрим... все, что вам нужно, это предоставить одну функцию, которая будет принимать на вход тикер (типа string) и возвращать биржевую котировку (типа float или double). Так не проще ли было бы просто позволить вашим разработчикам каким-то образом вызвать эту функцию через Интернет? Отлично! Тоже мне новость, есть же COM и Corba, и Java, которые этим занимаются уже годами... что правда – то правда, но эти методы не без изъяна. Удаленная настройка COM не тривиальна. Кроме того, нужно открыть столько портов в брандмауэре, что на системного администратора пива не напасешься. Да, и придется забыть о пользователях всех операционных систем кроме Windows. Но ведь позьзователи Linux тоже иногда интересуются биржей.

Хотя, похоже, что не все потеряно для пользователей Linux, если они используют DCOM, больше здесь: http://www.idevresource.com/com/library/res/articles/comonlinux.asp.

На счет Corba и Java я много сказать не могу, так что в качестве упражнения предлагаю читателям найти минусы в этих подходах.

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

О чем эта статья

Это первая из серии статей о SOAP, которые мы пишем в Agni Software. В этой статье я постараюсь дать вам представление о том, что такое SOAP и как написать приложение, общающееся с SOAP сервером.

Soap и XML

Если вам SOAP пока еще кажется простым, добавим XML. Теперь вместо имени функции и параметров мы получаем довольно сложный XML-конверт, как будто созданный для того, чтобы сбить вас с толку. Но не спешите пугаться. Дальше – больше, и вам нужно увидеть всю картину, чтобы оценить всю сложность SOAP.
Если вы не знаете, что такое XML, для начала прочтите мою статью об XML здесь: http://www.agnisoft.com/white_papers/xml_delphi.asp.

Все SOAP пакеты имеют XML формат. Что это значит? Посмотрим. Взгляните на эту функцию (Pascal):
function GetStockQuote(Symbol: string) : double; Выглядит отлично, но проблема в том, что это – Pascal. Какая польза от этого простого определения для Java-разработчика? Или для кого-то, кто работает с VB? Нам нужно что-то, что будет понятно всем, даже VB-программистам. Так дайте им XML, содержащий одну и ту же инфрмацию (параметры, значения биржевых котировок и т.д.). Вы создаете SOAP пакет, который по сути является вызовом вашей функции, обернутый в XML, чтобы любое приложения на любой платформе могло его понять. Теперь посмотрим, как выглядит наш SOAP вызов:
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">


IBM


Информативно, правда? SOAP упрощается на глазах. Ладно, шутки в сторону. Теперь я постараюсь объяснить вам, как разобраться в этом SOAP вызове.

Расшифровка тегов

Первый тег, который бросается в глаза – это . Этот тег – внешняя оболочка SOAP пакета, содержащая несколько объявлений пространств имен, которые нас особо не интересуют, но очень важны для любого языка программирования или парсера. Пространства имен определяются для того, чтобы последующие префиксы, такие как "SOAP-ENV:" или "xsd:" воспринимались парсером.

Следующий тег – . (Мы пропустили тег, не представленный здесь – . Его нет в этом конкретном примере, но если вы хотите почитать о нем больше, обратитесь к спецификации SOAP здесь: http://www.w3.org/TR/SOAP/). Тег собственно и содержит SOAP вызов.

Следующий тег в списке – . Имя тега, GetStockQuote и есть вызываемая функция. Согласно терминологии SOAP, это называется операцией. Таким образом GetStockQuote – операция, которая должна быть выполнена. ns1 – это пространство имен, указывающее на urn:xmethods-quotes в нашем случае.

Лирическое отступление на счет пространств имен: Пространство имен дает возможность квалифицировать XML тег. Нельзя, к примеру, иметь две переменные с одинаковым именем в одной процедуре, но если они в двух разных процедурах, проблем не возникает. Таким образом процедура – это пространство имен, так как все имена в ней уникальны. Точно так же XML теги имеют свою область видимости внутри пространств имен, так что имея пространство имен и имя тега, можно однозначно его идентифицировать. Мы определим пространство имен как URI, чтобы отличать наш NS1 от подражателей. В приведенном выше примере NS1 – это алиас, указывающий на urn:xmethods-quotes.

Обратите внимание также на атрибут encodingStyle – этот атрибут определяет каким образом сериализуется SOAP вызов.

Внутри тега содержатся параметры. В нашем простейшем случаи у нас есть только один параметр – тег . Обратите внимание на эту строку возле тега:
xsi:type="xsd:string"
Приблизительно так в XML и определяются типы. (Обратите внимание на то, как хитро я использовал слово "приблизительно", делая обобщение о технологии, которая может измениться как только статья будет опубликована). Что конкретно это означает: тип, определенный в пространстве имен xsi, который, как вы заметили, определен в теге – xsd:string. А это в свою очередь string, определенный в пространстве имен xsd, опять-таки, определенном ранее. (Уверен, юристы бы от этого всего просто млели).

Внутри тега указано "IBM". Это – значение параметра symbol функции GetStockQuote.

Ну и в конце, как порядочные люди, мы закрыли все теги.

Вот и разобрались с SOAP пакетом, определяющим вызов к SOAP серверу. А SOAP сервер с помощью XML парсеров, красной кнопки и космической станции "МИР" декодирует этот вызов и определяет, что вам нужна биржевая котировка. Он тут же находит нужную котировку и возвращает вам ее в таком виде:
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>


34.5


После разворачивания SOAP конверта, срывания ленточек и шуршания оберткой, мы узнаем, что цена акции IBM – 34.5.

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

Таким образом мы знаем, чего ожидает SOAP сервер и что он вернет. Так КАК же отправить эту информацию? Использовать можно любой транспорт. Самым освещенным является HTTP. Я не стану вдаваться в подробности HTTP, для тех, кто не знает – это то, что использует ваш браузер, чтобы общаться с сайтами, на которые вы заходите.

Нужный HTTP запрос будт выглядеть приблизительно так:
POST /StockQuote HTTP/1.1
Host: www.stockquoteserver.com

Content-Length: nnnn
SOAPAction: "Some-URI"

The soap request packet here... Единственное, что еще стоит отметить – это заголовок SOAPAction. Этот заголовок указывает на цель запроса и является обязательным. Каждый SOAP сервер может иметь неограниченное количество функций и может использовать заголовок SOAPAction чтобы определить какую функцию вызывают. Брандмауэры и мультиплексоры также могут фильтровать контент на основании этого заголовка.

SOAP ответ от HTTP сервера будет выглядеть следующим образом:
HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn

Soap Response packet here... Почему HTTP? Во-первых, сетевым администраторам не придется открывать уйму отдельных портов для SOAP вызовов... веб-сервер может спокойно обрабатывать вызовы, т.к. 80-й порт обычно открыт для всех для приема входящих запросов. Еще одним преимуществом является расширяемость веб-серверов с помощью CGI, ISAPI и других нативных модулей. Эта расширяемость позволяет написать модуль, обрабатывающий SOAP запросы не задевая другого веб-контента.

Вот и все

Надеюсь, эта статья помогла пролить немного света на SOAP. Если вы еще здесь и хотите почитать больше на эту тему, посетите сайт авторов: http://www.agnisoft.com/soap