Рассказ о том, как генерируется WSDL
SCA генерирует WSDL для компонентов, которые содержат аннотацию @binding.soap после аннотации @service. Чтобы создать WSDL, SCA во время исполнения с помощью Reflection отражает компонент и анализирует аннотации @param и @return для каждого публичного метода, а также любые аннотации @types в компоненте. Информация из аннотаций @param и @return используется для построения раздела WSDL <types>. Любые аннотации @types, которые указывают на отдельный файл схемы, приведут к созданию элемента <import> в схеме WSDL.
Аттрибут location элемента <service>
Внизу WSDL присутствует элемент <service>, который использует аттрибут location для идентификации URL сервиса. К примеру он может быть таким:
Пример #1 Аттрибут location
<service name="ConvertedStockQuote" ... location="http://localhost/ConvertedStockQuote/ConvertedStockQuote.php"/>
Обратите внимание, что местоположение является относительным для корня документов веб-сервера и не может быть обработано заранее. Оно может быть создано только после того, как компонент поместили в нужное место работающего веб-сервера, и когда имя и порт хоста становятся известны и могут быть помещены в WSDL. Подробности из URL-адреса, который запрашивает WSDL, используется, например, если WSDL в ответ на запрос http://www.example.com:1111/ConvertedStockQuote/ConvertedStockQuote.php?wsdl генерирует адрес http: //www.example.com:1111/ConvertedStockQuote/ConvertedStockQuote.php - это то, что будет вставлено в атрибут location в WSDL.
Обертка WSDL документ/литерал и позиционные параметры
SCA генерирует WSDL в стиле обертки документ/литерал. Этот стиль помещает параметры и возвращаемые типы метода в "обертки", которые названы в честь соответствующего метода. Элемент WSDL <types> каждую из этих оберток. Если мы рассмотрим метод getQuote() примера ConvertedStockQuote:
Пример #2 Метод с двумя аргументами
<?php
/**
* Получение стоимости акции в заданной валюте.
*
* @param string $ticker Название акции.
* @param string $currency В какой валюте возвращать результат.
* @return float Стоимость акции в заданной валюте.
*/
function getQuote($ticker, $currency)
{
$quote = $this->stock_quote->getQuote($ticker);
$rate = $this->exchange_rate->getRate($currency);
return $rate * $quote;
}
?>
WSDL создастся с описанием этого метода и его параметров и выдаст XML-схему для этих параметров. Секция типов будет выглядеть как-то так:
Пример #3 Секция типов с именованными параметрами
<types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://ConvertedStockQuote"> <xs:element name="getQuote"> <xs:complexType> <xs:sequence> <xs:element name="ticker" type="xs:string"/> <xs:element name="currency" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="getQuoteResponse"> <xs:complexType> <xs:sequence> <xs:element name="getQuoteReturn" type="xs:float"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> </types>
Во время выполнения SCA производит обработку для определения, как списки позиционных параметров в интерфейсе преобразуются в XML, содержащий именованные параметры в SOAP-запросе, а затем преобразуются обратно в списки позиционных параметров. Чтобы понять зачем это делается, рассмотрим как скрипт PHP, который использовал другой интерфейс для вызова SOAP, должен задавать список параметров. Например, PHP-скрипт с использованием PHP SoapClient должен передать SoapClient'у один параметр, задающий значения для "ticker" и "currency", например как ассоциативный массив. Поэтому для обеспечения одинакового вызова сервисов компонентов SCA как локально так и удаленно, требуется иной подход.
Когда SCA генерирует WSDL для SCA-компонента, он включает комментарий в WSDL, который отмечает, что WSDL является интерфейсом для SCA-компонента. В этом случае, когда один компонент SCA вызывает другой через веб-сервис, SCA на вызывающем конце во время исполнения принимает список позиционных параметров из вызова и, один за другим, присваивает значения названным элементам в SOAP-запроса. Например, вызов метода getQuote(), определенного выше, которому передаются значения "IBM" и "USD", выглядит так:
<?php
$quote = $remote_service->getQuote('IBM','USD');
?>
В результате SOAP-запрос будет выглядеть так:
<getQuote> <ticker>IBM</ticker> <currency>USD</currency> </getQuote>
На стороне предоставляющей сервис, SCA будет брать параметры по очереди из SOAP-запроса и создавать из него список аргументов ('IBM','USD').
И на стороне клиента и на стороне сервиса SCA будет полагаться на тот порядок аргументов, в каком они появились в SOAP-запросе и считать, что именно в этом порядке аргументы нужно передавать в запрошенный метод. Изначально этот порядок определяется порядком описания аргументов с помощью аннотаций @param. Т.е. порядок аннотаций @param определяет как порядок аргументов метода, так и порядок в котором аргументы будут описаны в SOAP-запросе.