<xs:any namespace="##any" minOccurs="0"
maxOccurs="unbounded" processContents="lax" />
</xs:sequence>
<xs:anyAttribute namespace="##any"
processContents="lax" />
</xs:complexType>
</xs:schema>
Если вы закончили рассмотрение complexType для Envelope, вы можете быстро ознакомиться с тем, какое отношение эти элементы имеют друг к другу. Следующий шаблон сообщения иллюстрирует структуру Конверта SOAP:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header> <!-- optional -->
<!-- header blocks go here... -->
</soap:Header>
<soap:Body>
<!-- payload or Fault element goes here... -->
</soap:Body>
</soap:Envelope>
Элемент Envelope всегдаявляетсякорневымэлементом SOAP сообщения. Таким образом, приложения могут, просто взглянув на имя корневого элемента, распознать "SOAP сообщения". Приложения также могут определить версию используемого SOAP, проверяя имя пространства имен элемента Envelope.
Элемент Envelope содержит необязательный элемент Header (более подробно см. в разделе Расширяемость), за которым следует обязательный элемент Body. Элемент Body представляет полезный груз сообщения. Элемент Body является контейнером, в котором может содержаться любое количество элементов из любого пространства имен. Именно здесь размещаются данные, которые вы пытаетесь отправить.
Например, следующее SOAP сообщение представляет запрос для трансфара фондов между банковскими счетами:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<x:TransferFunds xmlns:x="urn:examples-org:banking">
<from>22-342439</from>
<to>98-283843</to>
<amount>100.00</amount>
</x:TransferFunds>
</soap:Body>
</soap:Envelope>
Если получатель поддерживает запрос/ответ и может успешно обработать сообщение, он отправит другое SOAP сообщение назад отправителю. В этом случае информация ответа также будет содержаться в элементе Body, как показано в данном примере:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<x:TransferFundsResponse
xmlns:x="urn:examples-org:banking">
<balances>
<account>
<id>22-342439</id>
<balance>33.45</balance>
</account>
<account>
<id>98-283843</id>
<balance>932.73</balance>
</account>
</balances>
</x:TransferFundsResponse>
</soap:Body>
</soap:Envelope>
Оболочка обмена сообщениями также определяет элемент Fault для представления ошибок в пределах элемента Body, когда что-то идет не так. Это важно, потому что без стандартного представления ошибки каждому приложению придется вводить собственные, что сделает невозможным для общей инфраструктуры различить успех и неудачу. Следующий пример SOAP сообщения содержит элемент Fault, который представляет ошибку "Несоответствующие фонды", происходящую при обработке запроса:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Insufficient funds</faultstring>
<detail>
<x:TransferError xmlns:x="urn:examples-org:banking">
<sourceAccount>22-342439</sourceAccount>
<transferAmount>100.00</transferAmount>
<currentBalance>89.23</currentBalance>
</x:TransferError>
</detail>
</x:TransferFunds>
</soap:Body>
</soap:Envelope>
Элемент Fault долженсодержатьэлемент faultcode, закоторымследуетэлемент faultstring. Элемент faultcode, используя имя определенного пространства имен, классифицирует ошибку, в то время как элемент faultstring обеспечивает читабельное описание ошибки для человека (подобно тому, как работает HTTP). В Таблице 2 приведены краткие описания определенных в SOAP 1.1 кодов ошибок (все они в пространстве имен http://schemas.xmlsoap.org/soap/envelope/)
Элемент Fault также может содержать элемент detail для предоставления деталей ошибки, которые могут помочь клиентам диагностировать проблему, особенно в случае кодов ошибки Client и Server.
Таблица 2. Коды ошибок в SOAP 1.1
Name | Meaning |
VersionMismatch | Обрабатывающая сторона обнаружила неверное пространство имен для SOAP элемента Envelope. |
MustUnderstand | Ближайший дочерний элемент SOAP элемента Header, который был или не понят, или не подходил обрабатывающей стороне, содержит SOAP атрибут mustUnderstand со значением "1". |
Client | Класс ошибок Client показывает, что сообщение было неправильно сформировано или не содержит соответствующей информации для того, чтобы быть успешно обработанным. Это обычно свидетельствует о том, что не надо повторно отправлять сообщение, не изменив его. |
Server | Класс ошибок Server показывает, что сообщение не может быть обработано не из-за его содержимого, но, скорее, из-за сбоя при обработки сообщения. Сообщение может пройти успешно, если будет повторно отправлено в более поздний момент времени. |
Теперь представьте, что вы хотите в оригинальное сообщение добавить некоторую идентификационную информацию, чтобы получатель мог определить, имеет ли отправитель соответствующие права на выполнение пересылки. Чтобы сделать это, необходимо добавить удостоверяющую информацию в Body, как показано ниже:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<x:TransferFunds xmlns:x="urn:examples-org:banking">
<from>22-342439</from>
<to>98-283843</to>
<amount>100.00</amount>
<!-- security credentials -->
<credentials>
<username>dave</username>
<password>evad</password>
</credentials>
</x:TransferFunds>
</soap:Body>
</soap:Envelope>
Этот путь требует, чтобы каждая операция, требующая идентификации, работала с удостоверениями. Это также означает, что другие приложения при необходимости обеспечения безопасности должны разрабатывать свои собственные решения проблемы; разумеется, страдает возможность взаимодействия. Для общих нужд, таких как безопасность, больше смысла имеет определить стандартные SOAP заголовки, которые будут со всеми согласованы. Затем производители смогут встроить поддержку для расширенных функциональных возможностей в свою инфрастуктуру SOAP, и все будут в выигрыше. Этот подход увеличивает производительность разработчика и, в то же время, помогает обеспечить более высокий уровень взаимодействия. Это именно то, для облегчения чего была разработана модель расширяемости SOAP.
Расширяемость
Большинство существующих протоколов делают различие между управляющей информацией (т.е. заголовками) и полезной информацией сообщения. В этом отношении SOAP ничем не отличается. SOAP элементы Header и Body обеспечивают те же различия в легкообрабатываемом мире XML. Кроме простоты в использовании, ключевым преимуществом расширяемого Envelope является то, что он может использоваться любым протоколом связи.
Заголовки всегда играли важную роль в протоколах, таких как HTTP, SMTP и др., потому что они дают возможность приложениям на обоих концах провода обсуждать поведение поддерживаемых команд. Хотя сама спецификация SOAP не определяет встроенные заголовки, со временем они будут играть в SOAP такую же важную роль. Стандартизация GXA и заголовков SOAP облегчит разработчикам определение протоколов богатых приложений без необходимости каждый раз изобретать колесо.
Элемент Header, так же как и элемент Body, является контейнером для управляющей информации. Он может содержать любое количество элементов из любого пространства имен (не из пространства имен SOAP). На элементы, помещенные в элемент Header, ссылаются как на блоки заголовка. Как и в других протоколах, блоки заголовка должны содержать информацию, оказывающую влияние на обработку полезной информации. Таким образом, это подходящее место для размещения чего-то, вроде элемента credentials, который помогает контролировать доступ к операции:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<!-- security credentials -->
<s:credentials xmlns:s="urn:examples-org:security">
<username>dave</username>
<password>evad</password>
</s:credentials>
</soap:Header>
<soap:Body>
<x:TransferFunds xmlns:x="urn:examples-org:banking">
<from>22-342439</from>
<to>98-283843</to>
<amount>100.00</amount>
</x:TransferFunds>
</soap:Body>
</soap:Envelope>
Блоки заголовка также могут быть аннотированы глобальным SOAP атрибутом mustUnderstand, чтобы обозначить необходимость понимания заголовка получателем до обработки сообщения. Следующий пример иллюстрирует, как потребовать обработку заголовка credentials:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<!-- security credentials -->
<s:credentials xmlns:s="urn:examples-org:security"
soap:mustUnderstand="1"
>
<username>dave</username>
<password>evad</password>
</s:credentials>
</soap:Header>
...
Если блок заголовка аннотирован mustUnderstand="1", и получатель не поддерживает данный заголовок, сообщение не будет обработано и отправителю будет возвращен Fault (с кодом состояния soap:MustUnderstand). Когда mustUnderstand="0" или этого атрибута нет, получатель может игнорировать эти заголовки и продолжать обработку. Атрибут mustUnderstand играет центральную роль во всей модели обработки SOAP.
Модель обработки
SOAP определяет модель обработки, которая содержит основные правила обработки SOAP сообщений по мере их следования от SOAP отправителя к SOAP получателю. Рисунок 1 иллюстрирует простейший сценарий обмена SOAP сообщениями, в котором одно приложение (SOAP отправитель) посылает SOAP сообщение другому приложению (SOAP получателю).
Однако модель обработки допускает и более интересные архитектуры, подобные приведенной на Рисунке 3, которая содержит множество промежуточных узлов. Далее я буду использовать термин SOAP узел для обозначения любого приложения, которое обрабатывает SOAP сообщения, независимо от того, является ли оно начальным отправителем, промежуточным или конечным получателем; в противном случае я буду точен и буду использовать конкретный термин.
Рисунок 3. Сложный обмен SOAP сообщениями
Посредник располагается между начальным отправителем и конечным получателем и перехватывает SOAP сообщения. Посредник работает одновременно и как SOAP отправитель, и как SOAP получатель. Промежуточные узлы делают возможным разрабатывать некоторые интересные и гибкие сетевые архитектуры, на которые можно воздействовать содержимым сообщения. Маршрутизация SOAP сообщений является хорошим примером того, что значительно усиливает значимость SOAP посредников (более подробно о маршрутизации SOAP сообщений см. в Routing SOAP Messages with Web Services Enhancements 1.0)