Что такое WSDL, SOAP и REST

Что такое 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

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 не предусматривает этого, но подобные возможности могут быть добавлены в будущем. Поэтому не удивляйтесь если встретитесь с активными обсуждениями этой темы.

10 ответов

WSDL - это XML-документ, описывающий веб-службу. Это фактически означает язык определения веб-сервисов.

SOAP - это протокол на основе XML, который позволяет обмениваться информацией по определенному протоколу (например, HTTP или SMTP) между приложениями. Это означает простой протокол доступа к объектам и использует XML для его формата обмена сообщениями для передачи информации.

REST - это архитектурный стиль сетевых систем и выступает за передачу репрезентативного состояния. Это не стандарт сам, но использует такие стандарты, как HTTP, URL, XML и т.д.

Каждый раз, когда кто-то упоминает SOAP/WSDL, я думаю о объектах и ​​классах, определенных в xml...

"Вы используете SOAP так же, как и любой PHP-класс. Однако в этом случае класс не существует в локальной файловой системе приложений, а на удаленном узле, доступ к которому осуществляется через http."... "Если мы думаем использовать SOAP-сервис как еще один класс PHP, тогда документ WSDL является списком всех доступных методов и свойств класса".

И всякий раз, когда кто-то говорит о REST, я думаю о HTTP-командах (методах запроса), таких как POST, GET и DELETE

Пример: простыми словами, если у вас есть веб-сервис калькулятора.

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

SOAP: где, используя SOAP, вы фактически выполняете действия, такие как doDelete(), doSubtract(), doAdd(). Таким образом, SOAP и WSDL являются яблоками и апельсинами. Мы не должны сравнивать их. Они оба имеют свою собственную функциональность.

Почему мы используем SOAP и WSDL: для обмена независимыми данными на платформе.

РЕДАКТИРОВАТЬ: В обычной повседневной жизни:

WSDL: Когда мы идем в ресторан, мы видим пункты меню, это WSDL.

Прокси-классы: Теперь, после просмотра элементов меню, мы составляем наш разум (обрабатываем наш взгляд на порядок): Итак, в основном мы делаем классы Proxy на основе документа WSDL.

SOAP: Затем, когда мы фактически заказываем пищу на основе меню: подразумевается, что мы используем прокси-классы для вызова методов обслуживания, которые выполняются с использованием SOAP.:)

SOAP → SOAP (Простой прототип доступа к объектам) - это протокальный уровень приложения, созданный для взаимодействия машины с машиной. Протокол определяет стандартные правила. Все стороны, которые используют конкретный протокол, должны придерживаться правил протокола. Как и TCP, он разматывается на транспортном уровне. Протокол SOAP будет пониматься на уровне приложения (любое приложение, поддерживающее SOAP - Axis2,.Net).

WSDL → SOAP-сообщение состоит из SoapEnevelope- > SoapHeader и SoapBody. Он не определяет, какой будет формат сообщений? какие все транспорты (HTTP, JMS) поддерживаются? без этой информации. Для любого клиента, который хочет использовать конкретный веб-сервис для создания SOAP-сообщения, трудно. Даже если они это сделают, они не будут уверены, это будет работать все время. WSDL - это спасение. WSDL (язык описания веб-служб) определяет операции, форматы сообщений и данные о транспортировке для сообщения SOAP.

REST → REST (передача состояния представления) основана на транспорте. В отличие от SOAP, который нацелен на действия, REST больше относится к ресурсам. REST находит ресурсы с помощью URL-адреса (пример -http://{serverAddress}/employees/employeeNumber/12345) и зависит от транспортного протокола (с HTTP-GET, POST, PUT, DELETE,...) для действий для выполнения ресурсов. Служба REST находит ресурс на основе URL-адреса и выполняет действие на основе глагола действия транспорта. Это больше архитектурный стиль и условности.

SOAP означает простой (sic) протокол доступа к объектам. Он предназначался для того, чтобы делать удаленные вызовы процедур для удаленных объектов, отправляя XML через HTTP.

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

REST использует HTTP для отправки сообщений в службы.

SOAP - спецификация, REST - это стиль.

Вы не собираетесь "просто" понимать что-то сложное.

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

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

REST вообще не связан с WSDL.

Wikipedia говорит: "Язык описания веб-служб - это язык на основе XML, который предоставляет модель для описания веб-сервисов". Другими словами, WSDL относится к веб-службе, так как javadoc относится к библиотеке java.

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

Вообще сегодня есть стандартные протоколы обмена XML данными:

  • XML-RPC – вы передаете пакет и указываете, какой метод на сервере хотите вызвать.
  • REST - есть некие объекты на сервере. Каждый объект характеризуется каким-то идентификатором. У каждого элемента свой url. С любым элементов можно сделать: insert, delete, update, select. Вы просто посылаете нужный запрос на сервер (например, вставить такой-то элемент). Обмен клиент-сервер базируется либо на JSON, либо на XML.

Именно на RPC базируется SOAP (сервис ориентированная архитектура, набор слабосвязанных сервисов, взаимодействующих друг с другом). Главное достоинство RPC - небольшое количество сетевых ресурсов (точек входа) и много задействованных методов. Несмотря на это достоинство, у RPC - это устаревший протокол, у которого ряд недостатков:

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

Все эти недостатки были решены в XML Schema. Это промышленный стандарт описания XML документа. Т.е. это способ моделирования произвольных данных. XML схема может описывать модель (отношения между элементами и атрибутами, и их структура), типы данных (характеризует типы данных) и словарь (названия элементов и атрибутов).

Исходя из всех недостатков XML-RPC создали протокол SOAP.

SOAP (Simle Object Access Protocol) - протокол доступа к объекту (к точке входа). Сегодня это основной промышленный стандарт построения распределенных приложений.

Он представляет собой расширения языка XML-RPC. Т.е. он построен по принципу: 1 точка входа и любые методы. Сам протокол в плане транспорта (как передать данные) дает широкий выбор: SMTP, FTP, HTTP, MSMQ.

SOAP лежит в основе реализации XML веб-сервисов (XML веб служб). Недостаток SOAP - сложен в изучении.

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

XML схема

Задача схемы - описать структуру данных, т.е. что у нас есть. Все данные делятся на простые и сложные типы (скаляры и структуры). Простой тип (строка, число, boolean, дата) никогда внутри ничего содержать не будет. А структура (объект) может содержать свойства.

Основные операции SOAP

  • Не только простой обмен информацией клиент-сервер. Но и автоматическое распознавание сервера и поиск этого сервера, т.е. клиент может даже ничего не знать про сервер. Т.е. клиент сначала выполняет поиск сервера, найдет подходящие службы, поймет какие там методы, что на сервера есть, и произведет его вызов.
  • Сервер производит публикацию своей информации (расположение, какие методы поддерживает), чтобы клиент нашел этот сервер. Публикация происходит в UDDI каталог.

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

  • SOAP Envelope (конверт) - сюда входит все сообщение. Состоит из заголовка и тела.
  • SOAP Header (заголовок) - дополнительная информация (авторизация, например).
  • SOAP Body (тело) - само сообщение.
  • SOAP Fault (ошибка) - способ передачи ошибки от сервера к клиенту.

WSDL

WSDL (Web Services Description Language) - язык описания веб служб. Применяется в SOAP. Это некий докуент, который описывает все: какие пространства имен использовались, какие схемы данных использовались, какие типы сообщений сервер ждет от клиента, какие конверты к какому методу принадлежат, какие методы вообще есть, на какой адрес отправлять и т.д. Собственно, WSDL и есть веб сервис. Достаточно клиенту изучить содержимое этого документа, он уже знает о сервере все.

Любой сервер должен публиковать WSDL.

WSDL состоит из блоков:

  • Определение самой службы, т.е. точки входа, указывается порт.
  • Формат методов. Происходит привязка точки входа к операциям, т.е. какие методы поддерживает. Указывается тип вызова, способ передачи. Внутри каждого метода происходит объяснение - в каком виде передаются данные - в виде 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 с: ил.