|
Спецификация языка WSDL 1.11Константин Александров, 9 декабря 2012
1. ВведениеПоскольку транспортные протоколы и форматы сообщений были стандартизованы web-сообществом, появилась возможность и необходимость описания взаимодействия систем в структурированном виде. Для решения этой задачи предназначен WSDL — язык на базе XML, который описывает службу как набор конечных точек, способных обмениваться сообщениями. WSDL служит для документирования и комплексного определения деталей взаимодействия распределенных систем в виде, удобном для машинной обработки. WSDL определяет службу [service]2, как набор конечных точек [endpoint], или портов [port]. При этом специфичные параметры реализации — формат данных, настройки транспортного протокола — отделены от определения абстрактных сообщений [message], операций [operation] и типов портов [port type], что позволяет переиспользовать эти определения. Конкретный тип порта с указанным протоколом передачи и форматом сообщений образует связывание [binding], ассоциация связывания с конкретным сетевым адресом образует порт, а множество портов образует службу. Отсюда для описания службы в WSDL используются следующие сущности:
Эти элементы будут детально описаны в следующем разделе. Важно отметить, что WSDL не вводит нового языка определения типов. WSDL признает потребность в развитом механизме типизации для описания формата сообщений и поддерживает спецификацию XML Schema (XSD) как каноническую систему типизации. Однако это вовсе не означает, что выбор грамматики ограничивается только одной XSD — использование других грамматик допустимо посредством использования механизма расширения. Кроме того WSDL определяет общий механизм связывания. Он используется для ассоциации специфичных параметров протокола или формата и структуры данных с абстрактными сообщениями, операциями или конечными точками, что позволяет переиспользовать абстрактные определения. В дополнение к описанию самого механизма определения служб эта спецификация дает введение в расширения связывания [binding extension] для следующих протоколов и форматов сообщений:
Несмотря на то, что указанные выше расширения описываются в этом документе и наслаиваются на описание ядра механизма определения служб, никто не запрещает использовать другие расширения связывания вместе с WSDL. 1.1. Пример WSDL-документа
Ниже приведен пример WSDL для простой сетевой службы, которая предоставляет информацию о котировках на бирже. Она поддерживает одну операцию <?xml version="1.0"?> <definitions name="StockQuote" targetNamespace="http://example.com/stockquote.wsdl" xmlns:tns="http://example.com/stockquote.wsdl" xmlns:xsd1="http://example.com/stockquote.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> <schema targetNamespace="http://example.com/stockquote.xsd" xmlns="http://www.w3.org/2000/10/XMLSchema"> <element name="TradePriceRequest"> <complexType> <all> <element name="tickerSymbol" type="string"/> </all> </complexType> </element> <element name="TradePrice"> <complexType> <all> <element name="price" type="float"/> </all> </complexType> </element> </schema> </types> <message name="GetLastTradePriceInput"> <part name="body" element="xsd1:TradePriceRequest"/> </message> <message name="GetLastTradePriceOutput"> <part name="body" element="xsd1:TradePrice"/> </message> <portType name="StockQuotePortType"> <operation name="GetLastTradePrice"> <input message="tns:GetLastTradePriceInput"/> <output message="tns:GetLastTradePriceOutput"/> </operation> </portType> <binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="GetLastTradePrice"> <soap:operation soapAction="http://example.com/GetLastTradePrice"/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="StockQuoteService"> <documentation>My first service</documentation> <port name="StockQuotePort" binding="tns:StockQuoteBinding"> <soap:address location="http://example.com/stockquote"/> </port> </service> </definitions> 1.2. Соглашение об обозначенияхВ этом документе используются следующие пространства имен с префиксами:
В текущей спецификации используется свободный синтаксис для описания XML-грамматики WSDL:
Для строгого формального определения грамматики WSDL в разделе A4 приведены XSD-схемы. 2. Определение службы2.1 Структура WSDL-документа
<wsdl:definitions name="nmtoken"? targetNamespace="uri"?> Для определения службы используются шесть основных XML-элементов:
Эти элементы будут детально описаны в разделах 2.2-2.7. В завершение этого раздела будут описаны устанавливаемые WSDL правила именования документов, включения (импорта) документов с определениями, использования расширений и добавления контекстной документации. 2.1.1. Именование и включение документов
Для справочных целей WSDL-документу может быть присвоено опциональное имя, оно задается в атрибуте name типа WSDL позволяет ассоциировать пространство имен [namespace] с адресом размещения документа [location] с помощью конструкции import. <definitions .... > <import namespace="uri" location="uri"/> * </definitions> Адресация определений из подключенного документа выполняются по QName. Можно обращаться к следующим определениям импортированного документа:
Области имен определений разных видов не пересекаются — так, например, допустимо существования порта и сообщения с одинаковыми именами, но имена однотипных определений должны быть уникальны в рамках WSDL-документа. Разрешение QName в WSDL выполняется аналогично их разрешению, описанному в спецификации XML Schema. 2.1.2. Стиль составления документаИспользование элемента import позволяет разнести различные элементы определения службы по разным документам. Хорошим подходом является разделение определений в соответствии с их уровнем абстракции, что позволяет создавать более структурированные, следовательно проще читаемые, понимаемые и поддерживаемые определения служб. К тому же подход способствует переиспользованию определений всех уровней. Доработаем определение службы из первого примера — разнесем его по трем документам: определение базовых типов данных, абстрактное определение службы и связывание абстрактного определения со специфичными параметрами формата сообщений и транспорта. Возможности механизма импорта не ограничиваются работой с видами определений, явно установленными этой спецификацией. Любые другие определения, созданные посредством механизма расширения, могут быть переиспользованы подобным образом. <?xml version="1.0"?> <schema targetNamespace="http://example.com/stockquote/schemas" xmlns="http://www.w3.org/2000/10/XMLSchema"> <element name="TradePriceRequest"> <complexType> <all> <element name="tickerSymbol" type="string"/> </all> </complexType> </element> <element name="TradePrice"> <complexType> <all> <element name="price" type="float"/> </all> </complexType> </element> </schema> <?xml version="1.0"?> <definitions name="StockQuote" targetNamespace="http://example.com/stockquote/definitions" xmlns:tns="http://example.com/stockquote/definitions" xmlns:xsd1="http://example.com/stockquote/schemas" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <import namespace="http://example.com/stockquote/schemas" location="http://example.com/stockquote/stockquote.xsd"/> <message name="GetLastTradePriceInput"> <part name="body" element="xsd1:TradePriceRequest"/> </message> <message name="GetLastTradePriceOutput"> <part name="body" element="xsd1:TradePrice"/> </message> <portType name="StockQuotePortType"> <operation name="GetLastTradePrice"> <input message="tns:GetLastTradePriceInput"/> <output message="tns:GetLastTradePriceOutput"/> </operation> </portType> </definitions> <?xml version="1.0"?> <definitions name="StockQuote" targetNamespace="http://example.com/stockquote/service" xmlns:tns="http://example.com/stockquote/service" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:defs="http://example.com/stockquote/definitions" xmlns="http://schemas.xmlsoap.org/wsdl/"> <import namespace="http://example.com/stockquote/definitions" location="http://example.com/stockquote/stockquote.wsdl"/> <binding name="StockQuoteSoapBinding" type="defs:StockQuotePortType"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="GetLastTradePrice"> <soap:operation soapAction="http://example.com/GetLastTradePrice"/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="StockQuoteService"> <documentation>My first service</documentation> <port name="StockQuotePort" binding="tns:StockQuoteBinding"> <soap:address location="http://example.com/stockquote"/> </port> </service> </definitions> 2.1.3. Расширение языка и связываниеТермин «связывание» в WSDL означает процесс ассоциации параметров транспорта и формата данных с абстрактными определениями, такими как сообщения, операции, типы портов. Под определенными спецификацией стандартными элементами разрешается размещать элементы расширения, представляющие специфичные технологии. Как правило, эти точки расширения используются для задания параметров транспортного протокола и формата сообщений, однако их область применения этим не ограничивается. Пространство имен элементов расширения должно быть отличным от пространства имен WSDL.
Обычно элементы расширения используются для задания параметров связывания, специфичных для применяемой технологии передачи. Чтобы различать ситуации, когда учет этих параметров является обязательным для обмена сообщениями, элемент расширения может содержать атрибут wsdl:required логического типа. Он определен в пространстве имен WSDL, значение по умолчанию — Механизм расширения позволяет поддержать новые сетевые протоколы без внесения изменений в базовую спецификацию WSDL. Рекомендуется, чтобы спецификации этих протоколов и форматов также содержали определение необходимых WSDL-расширений. 2.1.4. ДокументированиеДля создания пользовательской документации WSDL позволяет использовать элемент wsdl:document, содержащий произвольный текст и XML-элементы («mixed content» в терминах XSD). Он может лежать под любым элементом из WSDL. 2.2 ТипЭлемент types содержит определения типов данных, соответствующих сообщениям. С целью унификации WSDL использует XSD как встроенную систему типизации и рассматривает ее как каноническую и основную. <definitions .... > <types> <xsd:schema .... />* </types> </definitions> Система типизации XSD может быть использована для определения типов данных в сообщениях независимо от того, будут ли сообщения передаваться в формате XML, или в каком-либо специфическом формате — в любом случае XSD-схема может быть использована для проверки структуры сообщений. Возможны случаи, когда для одного абстрактного сообщения имеются различные связывания, либо одно связывание, но не имеющее своей распространенной системы типизации. В этих случаях рекомендуется придерживаться следующих правил при описании абстрактных типов данных с помощью XSD:
Однако необоснованно ожидать, что в настоящем и будущем для определения типов данных будет использоваться только одна грамматика. Поэтому WSDL позволяет подключать другие системы типизации с помощью элементов расширения. Элемент расширения может быть добавлен под элемент types — он будет служить для идентификации системы типизации и для организации контейнера для определений типов. Роль такого элемента аналогична элементу schema языка XML Schema. <definitions ... > <types> <-- type-system extensibility element --> * </types> </definitions> 2.3 СообщениеСообщение состоит из одной или нескольких логических частей [part]. Каждая часть ассоциирована с типом данных с помощью атрибута типизации, набор таких атрибутов расширяемый. WSDL определяет следующие атрибуты типизации сообщений для случая использования системы типизации XSD:
Другие атрибуты типизации сообщений могут быть определены в пространстве имен, отличном от WSDL. Элементы расширения связывания также могут использовать атрибуты типизации. <definitions ... > <message name="nmtoken"> * <part name="nmtoken" element="qname"? type="qname"? /> * </message> </definitions>
Атрибут name элемента 2.3.1 Часть сообщенияЧасть сообщения — это гибкий механизм для описания абстрактного логического содержимого сообщения. Связывание может ссылаться на часть по имени для указания дополнительных специфичных параметров. Например, при определении сообщения для RPC часть может соответствовать одному аргументу вызываемой процедуры. Однако часть — абстрактное определение, и для работы с ее реальным значением придется обращаться к связыванию. Если сообщение состоит из нескольких цельных компонентов, то в WSDL его можно определить как состоящее из нескольких частей. Например, следующее сообщение состоит их платежного ордера и накладной: <definitions .... > <types> <schema .... > <element name="PO" type="tns:POType"/> <complexType name="POType"> <all> <element name="id" type="string/> <element name="name" type="string"/> <element name="items"> <complexType> <all> <element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/> </all> </complexType> </element> </all> </complexType> <complexType name="Item"> <all> <element name="quantity" type="int"/> <element name="product" type="string"/> </all> </complexType> <element name="Invoice" type="tns:InvoiceType"/> <complexType name="InvoiceType"> <all> <element name="id" type="string"/> </all> </complexType> </schema> </types> <message name="PO"> <part name="po" element="tns:PO"/> <part name="invoice" element="tns:Invoice"/> </message> </definitions> Однако если содержимое сообщения достаточно сложное, то определение типа можно полностью перенести на уровень системы типизации. В следующем примере сообщение содержит платежный ордер, либо набор накладных: <definitions .... > <types> <schema .... > <!-- POType и InvoiceType - типы из прошлого примера --> <complexType name="Composite"> <choice> <element name="PO" minOccurs="1" maxOccurs="1" type="tns:POType"/> <element name="Invoice" minOccurs="0" maxOccurs="unbounded" type="tns:InvoiceType"/> </choice> </complexType> </schema> </types> <message name="PO"> <part name="composite" type="tns:Composite"/> </message> </definitions> 2.3.2 Абстрактные / конкретные сообщенияОпределение сообщения всегда рассматривалось как абстрактное определение содержимого. Связывание сообщения описывает соответствие между абстрактным содержимым и конкретным форматом / представлением. Однако в некоторых случаях, абстрактное определение может очень близко, или даже однозначно, соответствовать какому-либо формату. Связывание для такого формата поставляет мало дополнительной информации, либо не поставляет совсем. Однако связывание для того же сообщения, но для другого формата, может потребовать обширных данных. Поэтому без изучения связывания невозможно сказать «насколько абстрактным» является определение сообщения. 2.4 Тип портаТип порта — это именованный набор абстрактных операций, ссылающихся на задействованные в обмене абстрактные сообщения. <wsdl:definitions .... > <wsdl:portType name="nmtoken"> <wsdl:operation name="nmtoken" .... /> * </wsdl:portType> </wsdl:definitions> Атрибут name задает уникальное имя порта среди всех портов, определенных в рамках WSDL-документа. Операция именуется также с использованием атрибута name. В WSDL имеется четыре примитива организации способа взаимодействия, которые может поддерживать конечная точка:
WSDL рассматривает эти примитивы как операции [operation]. Конечно, операции типа запрос-ответ и просьба-ответ могут быть смоделированы с использованием двух однонаправленных сообщений, однако полезно иметь такие операции как примитивы, так как:
Запрос / просьба и ответ связаны в WSDL логически, а конкретный механизм их корреляции описывает связывание. Например, запрос и ответ могут быть частью одного сетевого взаимодействия, либо являться физически разными сетевыми посылками. Хотя WSDL и поддерживает связывания для всех четырех примитивов, но определяет их только для примитивов однонаправленный запрос и запрос-ответ. Ожидается, что спецификации, определяющие протоколы для взаимодействий просьба-ответ и уведомление, также должны поставлять связывания для WSDL, что позволит использовать эти примитивы. Операции просьба-ответ и уведомление достаточно искусственные, вносящие сложность и путаницу, но не приносящие дополнительную полезность. В них инициатором обмена сообщениями является служба: она первая отправляет уведомление или запрос-просьбу и получает ответ для обработки. Например, web-служба, реализующая операцию типа уведомление, будет технически реализована как HTTP-клиент, а ее клиент — как HTTP-сервер. Распространения эти операции не получили, поддерживаются только теоретически на уровне спецификации. Поэтому web-службу следует разрабатывать как обработчик запросов с соответствующим использованием в ее WSDL-документе примитивов однонаправленный запрос и запрос-ответ. 2.4.1 Однонаправленный запросГрамматика определения операции следующая: <wsdl:portType .... > <wsdl:operation name="nmtoken"> <wsdl:input name="nmtoken"? message="qname"/> </wsdl:operation> </wsdl:portType> Элемент input задает абстрактное содержание сообщения-запроса. 2.4.2 Запрос-ответ<wsdl:portType .... > <wsdl:operation name="nmtoken" parameterOrder="nmtokens"> <wsdl:input name="nmtoken"? message="qname"/> <wsdl:output name="nmtoken"? message="qname"/> <wsdl:fault name="nmtoken" message="qname"/>* </wsdl:operation> </wsdl:portType> Элементы input и output задают абстрактное содержание запроса и ответа соответственно. Опциональные элементы fault задают абстрактное содержание сообщений об ошибках, которое могут приходить в результате выполнения операции (сверх тех, что специфичны для протокола). Обратите внимание, что операция запрос-ответ — это абстрактное представление. Нужно рассмотреть конкретное связывание, чтобы определить, как в действительности будет передано сообщение: в рамках одного взаимодействия (также как HTTP запрос и ответ), либо в рамках двух независимых взаимодействий (например, как два разных HTTP-запроса). 2.4.3 Просьба-ответ<wsdl:portType .... > <wsdl:operation name="nmtoken" parameterOrder="nmtokens"> <wsdl:output name="nmtoken"? message="qname"/> <wsdl:input name="nmtoken"? message="qname"/> <wsdl:fault name="nmtoken" message="qname"/>* </wsdl:operation> </wsdl:portType> Элементы output и input задают абстрактное содержание запроса-просьбы и ответа соответственно. Опциональные элементы fault задают содержание возможных сообщений об ошибках. Операция просьба-ответ также является абстрактным представлением, и для определения реального способа передачи сообщений необходимо обратиться к соответствующему связыванию. 2.4.4 Уведомление<wsdl:portType .... > <wsdl:operation name="nmtoken"> <wsdl:output name="nmtoken"? message="qname"/> </wsdl:operation> </wsdl:portType> Элемент output задает абстрактное содержание сообщения-уведомления. 2.4.5 Имена элементов в рамках операции
Атрибут name элементов
Чтобы избежать необходимости именования всех элементов
Так как элементов 2.4.6 Порядок параметров в рамках операции
На уровне операции не настраивается, будет ли она использоваться вместе с RPC-связыванием. Однако при использовании операции с RPC-связыванием полезно зафиксировать сигнатуру оригинальной функции. Для этой цели операции запрос-ответ и просьба-ответ могут содержать список имен параметров в атрибуте parameterOrder типа
Обратите внимание, что эта информация служит только как «подсказка», поэтому может быть безопасно проигнорирована в случае незаинтересованности в RPC-сигнатуре. Кроме того она является необязательной даже в случае использования операции с RPC-связыванием. 2.5 СвязываниеСвязывание определяет формат сообщений и детали протокола для операций и сообщений конкретного типа порта. Одному типу порта могут соответствовать несколько разных связываний. Грамматика определения связывания следующая: <wsdl:definitions .... > <wsdl:binding name="nmtoken" type="qname"> * <-- extensibility element (1) --> * <wsdl:operation name="nmtoken"> * <-- extensibility element (2) --> * <wsdl:input name="nmtoken"? > ? <-- extensibility element (3) --> </wsdl:input> <wsdl:output name="nmtoken"? > ? <-- extensibility element (4) --> * </wsdl:output> <wsdl:fault name="nmtoken"> * <-- extensibility element (5) --> * </wsdl:fault> </wsdl:operation> </wsdl:binding> </wsdl:definitions> Атрибут name задает имя связывания, уникальное среди всех связываний WSDL-документа. Связывание ссылается на тип порта с помощью атрибута type типа QName (см. Раздел 2.1.2). Элементы расширения связывания используются для указания конкретной грамматики для входящих (3) и исходящих (4) сообщений, сообщений об ошибках (5). Также может указываться информация уровня операции (2) и уровня связывания (1).
Элемент связывания Связывание должно устанавливать только один протокол. Связывание не должно содержать информации об адресе. 2.6 ПортПорт определяет отдельную конечную точку посредством установки адреса для связывания. <wsdl:definitions .... > <wsdl:service .... > * <wsdl:port name="nmtoken" binding="qname"> * <-- extensibility element (1) --> </wsdl:port> </wsdl:service> </wsdl:definitions> Атрибут name задает уникальное имя среди всех портов в рамках WSDL-документа. Атрибут binding типа QName содержит ссылку на связывание (см. Раздел 2.1.2). Элементы расширения (1) используются для задания адреса. Порт не должен задавать более одного адреса. Порт не должен содержать любую информацию связывания, отличную от адреса. 2.7 СлужбаСлужба объединяет вместе набор связанных портов. <wsdl:definitions .... > <wsdl:service name="nmtoken"> * <wsdl:port .... />* </wsdl:service> </wsdl:definitions> Атрибут name задает уникальное имя среди всех служб, определенных в рамках WSDL-документа. Порты внутри службы связаны следующим образом:
|