Рассказ о том, как генерируется 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-запросе.