|
|
|
Описание для автора не найдено
|
|
|
|
|
|
|
|
RPC/Литерал и свобода выбора
Автор: Yasser Shohoud, Microsoft
Перевод: Шатохина Надежда(sna@uneta.org), Ukraine .Net
Alliance (http://www.uneta.org)
Апрель 2003
Применяется к:
Удаленный вызов процедур (Remote Procedure Calls - RPC)
SOAP Messaging
SOAP 1.1 спецификация
WSDL 1.1 спецификация
WS-I Basic спецификация
Обзор: Посмотрим, почему используемый для
Web сервиса формат обмена сообщениями SOAP не всегда определяет используемую
модель программирования. Больше узнаем о форматах обмена сообщениями SOAP и
разделении формата сообщения и модели программирования.
Введение
Форматы сообщений SOAP
Описание форматов сообщений SOAP
Преобразование RPC/литерал в документ/литерал сообщения
Действительно ли нам нужны два формата сообщений?
WS-I Basic Profile и RPC/литерал
Введение
Сегодня существует две популярные модели программирования для Web сервисов:
RPC и обмен сообщениями (messaging). Спецификация WSDL 1.1 напрасно определяет
два стиля сообщений SOAP, RPC и документ, которые будто бы соответствуют двум
моделям программирования. Я говорю напрасно, потому что взаимосвязь между
моделью программирования и форматом сообщения полностью искусственна. Например,
для отправки и получения сообщений документ стиля (document-style) я могу
использовать модель программирования RPC. Кстати, Web сервисы на базе Microsoft®
.NET (.asmx) по умолчанию делают именно это. Я также могу прямо послать
сообщение SOAP RPC стиля, используя некоторые XML API (т.е. DOM или XmlReader),
а затем отправить полученное ответное сообщение для обработки в какую-то другую
программу.
Несмотря на это, среди производителей инструментальных средств наблюдается
мощная тенденция выводить модель программирования из формата сообщений,
определенного в WSDL сервисе. Я, конечно, могу понять использование формата
сообщения в качестве рекомендации для предлагаемой модели
программирования, но ошибочным является навязывание модели
программирования, исходя из формата сообщений. Как потребитель Web сервиса, я
конечно не хочу, чтобы он диктовал мне, какую модель программирования
использовать. Скорее я хочу иметь свободу выбора платформы, языка и модели
программирования для вызова этого сервиса. Производители инструментальных
средств должны понимать, что потребители (клиенты) в состоянии сами выбирать
модель программирования независимо от того, что рекомендуют разработчики
сервиса.
В этой статье обсуждаются два формата сообщений SOAP и показывается, как WSDL
описывает эти форматы. Здесь также объясняется, почему нужен только один формат
сообщений, и предлагается разделить модель программирования и формат
сообщений.
Форматы сообщений SOAP
Спокойно пропускайте этот раздел, если вы хорошо знакомы с форматами
сообщений SOAP.
WSDL 1.1 выделяет два стиля сообщений: документ и RPC. Вот как каждый стиль
влияет на содержимое <soap:Body>.
- Document: <soap:Body> содержит
один или более дочерних элементов, называемых частями. Для содержимого
<soap:Body> нет правил форматирования SOAP; он содержит
все, о чем бы ни договорились отправитель и получатель.
- RPC: RPC предполагает, что
<soap:Body> содержит элемент с именем вызываемого
метода или удаленной процедуры. Этот элемент, в свою очередь, содержит элемент
для каждого параметра этой процедуры.
Для приложений, которые используют сериализацию/десериализацию для для
передачи данных, надо сделать еще один выбор: формат сериализации. Сегодня
популярны два формата сериализации:
- SOAP кодирование: SOAP кодирование – это ряд правил
сериализации, определенных в разделе 5 SOAP 1.1, которые иногда назвают
"кодирование 5-го раздела". Правила определяют как должны быть сериализованы
объекты, структуры, массивы и деревья объектов. В общем, приложения,
использующие SOAP кодирование, фокусируются на вызовах удаленных процедур и,
вероятно, будут использовать стиль сообщений RPC. Далее в этой статье все
внимание сосредоточено на литерал формате.
- Литерал: Данные сериализовываются в соответствии со
схемой. На практике эта схема обычно выражается с помощью W3C XML Схемы. Хотя
для сериализации объектов, структур и т.д. нет установленных правил, схема
сервиса описывает стуктуру на уровне приложения каждого из сообщений сервиса.
Далее приведены два примера сообщений SOAP: документ/литерал и RPC/литерал.
Обратите внимание, что так случилось (но это не обязательно), что оба
примера содержат элемент Example с дочерним элементом
cust. Однако пространства имен элементов
Example и cust в двух примерах различны, что
показано жирным шрифтом.
Документ/литерал
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<!—- следующее является документом XML, описанным в
контракте сервиса с помощью XML Схемы. В этом случае
Example может или может и не быть именем удаленной
процедуры, вызываемой этим сообщением. Также cust
может или может и не быть именем параметра. Мы знаем
структуру XML документа, но мы не знаем, как сервер
обрабатывает его -->
<Example xmlns="http://example.org/soapformat">
<cust>
<Customer>
<Name>John Doe</Name>
<Id>ABC-1234</Id>
</Customer>
<Customer>
<Name>Jane Doe</Name>
<Id>XYZ-1234</Id>
</Customer>
</cust>
</Example>
</soap:Body>
</soap:Envelope>
RPC/ литерал
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<!—- Example – это имя вызываемой процедуры, cust – это параметр этой процедуры. Обратите внимание, что cust не привязан
к пространству имен. Два элемента Customer являются содержимым параметра cust. В этом случае cust может рассматриваться как
массив элементов Customer. Обратите внимание, что Customer принадлежит пространству имен, но он с Example в разных
пространствах имен. Эти правила пространства имен уникальны для сообщений RPC-стиля и будут описаны в следующем разделе
-->
<x:Example xmlns:x="http://example.org/soapformat/Example">
<cust>
<t:Customer xmlns:t="http://example.org/soapformat">
<t:Name>John Doe</t:Name>
<t:Id>ABC-1234</t:Id>
</t:Customer>
<t:Customer>
<t:Name>Jane Doe</t:Name>
<t:Id>XYZ-1234</t:Id>
</t:Customer>
</cust>
</x:Example>
</soap:Body>
</soap:Envelope>
Описание форматов сообщений SOAP
Описание документ/литерал сообщений
В этом разделе я объясню, как WSDL описывает документ/литерал и RPC/литерал
форматы сообщений. Приведенные здесь примеры и объяснения принимают во внимание
рекомендации WS-I Basic Profile 1.0. Я не буду брать во внимание SOAP
кодирование, чтобы сосредоточиться на сравнении документ/литерал и RPC/литерал
форматов.
Ниже приведен WSDL пример, описывающий два документ/литерал метода. Их
основные особенности следующие:
- Каждое сообщение содержит ноль или одну часть. Эта часть указывает на
объявление элемента схемы, который описывает полное содержимое тела
сообщения.
- В связывании SOAP, стиль - это"документ" и использование - это "литерал".
Основной особенностью документ/литерал формата и его ключевое преимущество по
сравнению с RPC/литерал является использование объявление элемента схемы для
полного описания содержимого soap:Body. Это означает, что вы
можете сказать, что содержит тело сообщения, только взглянув на схему и без
использования дополнительных правил. Следовательно, вы можете взять схему,
описывающую документ/литерал сообщение, и использовать ее для проверки
правильности формарования сообщения. Вы не можете сделать этого с RPC/литерал
сообщениями.
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://example.org/soapformat"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
targetNamespace="http://example.org/soapformat"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://example.org/soapformat">
<!—- объявление этого элемента описывает все содержимое soap:Body в запрашивающем сообщении. Эта та возможность
документ/литерал сообщений, которой нет в RPC/литерал -->
<s:element name="Example">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="cust"
type="tns:ArrayOfCustomer" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="ArrayOfCustomer">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded"
name="Customer" nillable="true"
type="tns:Customer" />
</s:sequence>
</s:complexType>
<s:complexType name="Customer">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="Name" type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
name="Id" type="s:string" />
</s:sequence>
</s:complexType>
<!-- Аналогично, объявление этого элемента описывает содержимое soap:Body в ответном сообщении. В этом случае ответ
пустой -->
<s:element name="ExampleResponse">
<s:complexType />
</s:element>
</s:schema>
</types>
<message name="ExampleSoapIn">
<!-- using element="" to reference an element declaration -->
<part name="parameters" element="tns:Example" />
</message>
<message name="ExampleSoapOut">
<part name="parameters" element="tns:ExampleResponse" />
</message>
<portType name="testserviceSoap">
<operation name="Example">
<input message="tns:ExampleSoapIn" />
<output message="tns:ExampleSoapOut" />
</operation>
</portType>
<binding name="testserviceSoap" type="tns:testserviceSoap">
<soap:binding
transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="Example">
<soap:operation
soapAction="http://example.org/soapformat/Example"/>
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
</definitions>
Описание RPC/литерал сообщений
Ниже приведен WSDL пример, описывающий два RPC/литерал сообщения. Их основные
особенности следующие:
- Каждое сообщение содержит ноль или одну часть. Каждая часть указывает на
объявление типа схемы, которая описывает содержимое этой части.
- В SOAP связывании, стиль - это "RPC" и использование - это " литерал".
Основной особенностью (если можно так это назвать) RPC/литерал формата и
ключевым его недостатком по сравнению с документ/литерал является полагание на
чудо при выяснении содержимого soap:Body. Это означает, что
сама схема не скажет вам, что содержится в теле сообщения, вы должны знать еще и
правила RPC. Поэтому описание схемой RPC/литерал сообщения не достаточно для
проверки правильности формирования.
Правила для наследования RPC/литерал сообщения от его WSDL описания
следующие:
- Soap:Body содержит один элемент, который имеет имя WSDL
операции и пространство имен, определенное в элементе
soap:body в WSDL (смотрите атрибут
namespace="http://example.org/soapformat/Example" в
распечатке, приведенной ниже).
- В этом элементе есть элемент для каждой части сообщения. Имя этого
элемента - это имя части. Этот элемент не привязан к пространству имен.
- В элементе каждой части есть содержимое этой части, как определено типом
схемы, на которую в WSDL ссылается часть.
Нет необходимости говорить, что то, что должно произойти между схемой,
описывающей RPC/литерал сообщение, и реальным сообщением, является загадкой.
Документ/литерал сообщения устраняют эту загадочность.
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://example.org/soapformat"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
targetNamespace="http://example.org/soapformat"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://example.org/soapformat">
<!—- нет глобального объявления элемента. В schema нет ничего, что полностью описывает содержимое soap:Body -->
<s:complexType name="ArrayOfCustomer">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded"
name="Customer" nillable="true"
type="tns:Customer" />
</s:sequence>
</s:complexType>
<s:complexType name="Customer">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="Name" type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
name="Id" type="s:string" />
</s:sequence>
</s:complexType>
</s:schema>
</types>
<message name="ExampleSoapIn">
<!-- using type="" to reference a type declaration -->
<part name="cust" type="tns:ArrayOfCustomer" />
</message>
<message name="ExampleSoapOut"/>
<portType name="testserviceSoap">
<operation name="Example">
<input message="tns:ExampleSoapIn" />
<output message="tns:ExampleSoapOut" />
</operation>
</portType>
<binding name="testserviceSoap" type="tns:testserviceSoap">
<soap:binding
transport="http://schemas.xmlsoap.org/soap/http"
style="rpc" />
<operation name="Example">
<soap:operation
soapAction="http://example.org/soapformat/Example"/>
<input>
<soap:body
namespace="http://example.org/soapformat/Example"use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
</definitions>
Преобразование RPC/литерал в документ/литерал
сообщения
RPC/литерал сообщения оказались подмножеством документ/литерал. Это означает,
что для любого данного RPC/литерал WSDL вы можете создать полностью
эквивалентное документ/литерал WSDL, которое будет описывать те же сообщения.
Здесь приведена последовательность действий при этом (в основном, объявления
элемента схемы).
Для каждой RPC/литерал операции
- Для каждой части во входном и выходном сообщениях этой операции объявите
тип с содержимым, описанным в шаге 2.
- Объявите элемент в именем части, на которую выражением
type=" ссылается тип. Форма элемента не должна принадлежать
пространству имен.
- Объявите глобальный элемент с именем операции и пространством имен из
soap:body/@namespace в binding секции. Сделайте типом этого
элемента тип, определенный в шаге 1 для входного сообщения.
- Объявите глобальный элемент с именем операции и прикрепленным к нему
словом Response и пространство имен из
soap:body/@namespace в binding секции. Сделайте типом этого
элемента тип, определенный в шаге 1 для выходного сообщения.
- Измените входное сообщение так, чтобы оно содержало одну часть и ссылалось
на элемент, объявленный вами в шаге 3.
- Измените выходное сообщение так, чтобы оно содержало одну часть и
ссылалось на элемент, объявленный вами в шаге 4.
- Замените стиль на document в binding секции.
Действительно ли нам нужны два формата сообщений?
Итак, действительно ли нам нужны два формата сообщений и все эти запутанные
правила наследования сообщения от его описания? Конечно нет – по двум простым
причинам:
- Документ/литерал является объемлющим множеством RPC/литерал. Для любого
данного RPC/литерал WSDL описания может быть создано эквивалентное
документ/литерал WSDL описание, так чтобы сообщения были идентичными. Все, что
надо – это некоторое изменение схемы для формального описания RPC/литерал
сообщения.
- Формат сообщения и модель программирования ортогональны. Необходимость
двух форматов сообщений из-за существования двух моделей программирования
ложна. Более того, сервис не должен диктовать потребителю программную модель.
Я осознаю, однако, необходимость существования рекомендации по модели
программирования, которая дает возможность разработчикам сервиса определить, что
их проект оптимизирован для RPC или программных моделей обмена сообщениями. Это
должна быть простая рекомендация, которая может быть по желанию проигнорирована
инструментальными средствами потребителя. Например, глобальный атрибут в binding
секции или операции сделает такой фокус:
<binding
xmlns:x="http://example.org/descriptionHints"
name="testserviceSoap"
type="tns:testserviceSoap"
<!-- the service developer suggests RPC programming style -->
x:hint="rpc">
<soap:binding
transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="Example">
<soap:operation
soapAction="http://example.org/soapformat/Example"/>
<input>
<soap:body
use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
Web сервисы на базе .NET используют модель программирования RPC и по
умолчанию используют документ/литерал сообщения. Рекомендация, на которую
полагаются инструментальные средства разработки Microsoft .NET, - это имя части
сообщения в WSDL. Если это имя - "параметры", потребитель WSDL принимает, что
это метод, названный по объявлению глобального элемента части, и что каждый
элемент в этой части является параметром метода. То, как работает Microsoft
.NET, интересно только в качестве примера, доказывающего, что RPC модель
программирования и документ/литерал сообщения могут сосуществовать. Я не говорю,
что все должны принять эту рекомендацию. Более предпочтительным должен быть
другой, более ясный механизм, такой как глобальный атрибут, т.к. он более ясно
отображает рекомендацию и не перегружает использование имени части.
WS-I Basic Profile и RPC/литерал
К сожалению WS-I Basic Profile явно разрешает использование и
документ/литерал, и RPC/литерал сообщений. Беря во внимание приведенный выше
анализ, я верю, что в существовании двух форматов сообщений нет необходимости и
в конечном счете не улучшает способности к взаимодействию. Будем надеяться,
большинство, если не все, разработчики Web сервиса будут игнорировать
RPC/литерал сообщения и обеспечат необходимую обратную связь для WS-I, чтобы
закрепить это в будущих версиях Basic Profile.
Никакая часть настоящей статьи не может быть воспроизведена или
передана в какой бы то ни было форме и какими бы то ни было средствами, будь то
электронные или механические, если на то нет письменного разрешения владельцев
авторских прав.
Материал, изложенный в данной статье, многократно
проверен. Но, поскольку вероятность технических ошибок все равно существует,
сообщество не может гарантировать абсолютную точность и правильность приводимых
сведений. В связи с этим сообщество не несет ответственности за возможные
ошибки, связанные с использованием статьи.
|
|
|
|
|
|
|