Главная » Spring » Создание WSDL-файлов Spring

0

Наконец, я собираюсь выполнить свое обещание и показать, от- куда берется WSDL-файл с определением веб-службы оценки ком- бинации карт при игре в покер. В разделе 15.2.1 мы уже определили формат представления данных в виде схемы на языке XML Schema, в файле PokerTypes.xsd. Прежде чем двинуться дальше, вернитесь к листингу 15.1, чтобы освежить в памяти, как выглядит определе- ние формата представления данных.

Особое внимание обратите на имена, которые я выбрал для XML-элементов, определяющих типы сообщений для веб-службы: EvaluateHandRequest  и EvaluateHandResponse. Эти имена были выбраны

не случайно. Они выбирались целенаправленно, с учетом поддержки в Spring-WS принципа преимущества соглашений перед настройка- ми, которая будет автоматически создавать WSDL-файл для службы оценки комбинации карт.

Чтобы задействовать эту поддержку, необходимо настроить спе- циальный компонент DynamicWsdl11Definition.DynamicWsdl11Definition, который используется сервлетом MessageDispatcherServlet для созда- ния WSDL-определения из схемы на языке XML Schema. Это очень удобно, так как у нас уже имеется схема XML Schema, определяю- щая формат представления данных. Ниже показано, как я настроил компонент DynamicWsdl11Definition в контексте Spring:

<bean id="poker"

class="org.springframework.ws.wsdl.wsdl11.DynamicWsdl11Definition">

<property name="builder">

<bean class="org.springframework.ws.wsdl.wsdl11.builder.

➥  XsdBasedSoap11Wsdl4jDefinitionBuilder">

<property name="schema" value="/PokerTypes.xsd"/>

<property  name="  portTypeName  "  value="Poker"/>

<property  name="locationUri" value="http://localhost:8080/Poker-WS/services"/>

</bean>

</property>

</bean>

Компонент DynamicWsdl11Definition читает описание схемы на язы- ке XML Schema из файла PokerTypes.xsd, как определено свойством schema. Он отыскивает в файле все определения элементов, оканчи- вающихся словом Request или Response. И исходя из предположения, что эти окончания соответствуют сообщениям, посылаемых операци- ям службы или возвращаемых ими, создает соответствующие элемен- ты <wsdl:operation> в WSDL-определении, как показано на рис. 15.7.

Например, обрабатывая файл PokerTypes.xsd, компонент Dynamic- Wsdl11Definition предполагает, что элементы EvaluateHandRequest и EvaluateHandResponse описывают входящее и исходящее сообщения для операции с именем EvaluateHand. В результате он воспроизводит следующее определение WSDL:

<wsdl:portType name="Poker">

<wsdl:operation   name="EvaluateHand">

<wsdl:input    message="schema:EvaluateHandRequest" name="EvaluateHandRequest">

</wsdl:input>

<wsdl:output   message="schema:EvaluateHandResponse" name="EvaluateHandResponse">

</wsdl:output>

</wsdl:operation>

</wsdl:portType>

Рис. 15.7. Компонент DynamicWsdl11Definition автоматически воспроизводит WSDL-определение для веб-службы,

опираясь на описание схемы на языке XML Schema, определяющей сообщения, которыми клиенты обмениваются со службой

Обратите внимание, что компонент DynamicWsdl11Definition по- местил элемент <wsdl:operation>  с именем EvaluateHand  в элемент

<wsdl:portType> с именем Poker. Имя для элемента <wsdl:portType> было взято из свойства portTypeName.

Последним в компоненте DynamicWsdl11Definition мы настроили свойство locationUri. Это свойство сообщает клиенту адрес, где нахо- дится служба. Диаграмма на рис. 15.8 изображает структуру адреса URL, который присваивается свойству locationUri.

Рис. 15.8. Структура адреса URL в свойстве locationUri

В данном случае предполагается, что служба будет действовать на локальном компьютере, поэтому, если вы соберетесь опробовать ее на удаленном компьютере, вам придется изменить URL. Обра- тите внимание, что URL оканчивается строкой /services в соответ- ствии с настройками в элементе <servlet-mapping> для компонента MessageDispatcherServlet.

Коль скоро мы заговорили об элементе <servlet-mapping>, нам также необходимо добавить в файл web.xml новый элемент <servlet- mapping>, чтобы компонент MessageDispatcherServlet мог генерировать определение WSDL. Определение нового элемента <servlet-mapping> показано ниже:

<servlet-mapping>

<servlet-name>poker</servlet-name>

<url-pattern>*.wsdl</url-pattern>

</servlet-mapping>

Теперь сервлет MessageDispatcherServlet сможет автоматически ге- нерировать (с помощью DynamicWsdl11Definition) определение WSDL службы оценки комбинации карт при игре в покер. Единственный вопрос, который пока остается без ответа, – где искать сгенериро- ванное определение WSDL.

Сгенерированное определение WSDL можно найти по адресу http://localhost:8080/Poker-WS/poker.wsdl. Как я это узнал? Я знаю, что контроллер MessageDispatcherServlet отображается в шаблон *.wsdl, поэтому при обращении по любому адресу, соответствующему этому шаблону, будет создано определение WSDL. Но откуда он знает, что определение WSDL для нашей службы должно быть сгенерировано в виде файла с именем poker.wsdl?

Ответ на этот вопрос находится в последнем пункте соглашения, которому следует MessageDispatcherServlet. Обратите внимание, что я объявил компонент DynamicWsdl11Definition с идентификатором poker. Когда компонент MessageDispatcherServlet  получит запрос для URL

/poker.wsdl, он будет искать в контексте Spring компонент с именем poker, создающий определение WSDL. В данном случае он найдет компонент DynamicWsdl11Definition.

Использование   предопределенного WSDL-определения

Компонент DynamicWsdl11Definition с успехом можно использовать в самых разных ситуациях, так как он избавляет от необходимости

писать WSDL-определения вручную. Но иногда может потребовать- ся более полный контроль над WSDL-определением службы. В таких ситуациях бывает желательно вручную создать WSDL-файл и затем внедрить его в контекст Spring с помощью SimpleWsdl11Definition:

<bean id="poker"

class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">

<property  name="wsdl"  value="/PokerService.wsdl"/>

</bean>

Компонент SimpleWsdl11Definition не генерирует WSDL-определе- ние автоматически (рис. 15.9), он просто возвращает WSDL-файл, имя которого указывается в свойстве wsdl.

Рис. 15.9. Компонент SimpleWsdl11Definition просто возвращает предопределенный WSDL-файл

посредством MessageDispatcherServlet. При необходимости компонент MessageDispatcherServlet можно настроить так, чтобы он изменял адрес службы в соответствии с настройками

Единственная проблема при использовании предопределенного WSDL-файла (кроме усилий, необходимых на его создание) – в том, что он определен статически. Это создает сложности в той части WSDL-определения, где указывается местоположение службы. На- пример, взгляните на следующий (статический) фрагмент WSDL:

<wsdl:service name="PokerService">

<wsdl:port  binding="tns:PokerBinding"  name="PokerPort">

<wsdlsoap:address

location="http://localhost:8080/Poker-WS/services"/>

</wsdl:port>

</wsdl:service>

Здесь определяется, что служба будет доступна по адресу http:// localhost:8080/Poker-WS/services. Что, в принципе, вполне годится для этапа разработки, не подходит при развертывании на другом сервере. Можно было бы вручную изменять WSDL-файл при каж- дом развертывании службы на другом сервере, но это слишком уто- мительно и есть риск допустить ошибку.

Но компонент MessageDispatcherServlet знает, где он разворачива- ется, и знает, какой адрес URL будет использоваться для запросов к нему. Поэтому вместо редактирования WSDL-файла при развер- тывании службы на другом сервере почему бы не позволить ком- поненту MessageDispatcherServlet переопределить адрес самостоя- тельно?

Для этого достаточно добавить параметр <init-param> с именем transformWsdlLocations и значением true, а обо всем остальном поза- ботится компонент MessageDispatcherServlet:

<servlet>

<servlet-name>poker</servlet-name>

<servlet-class>org.springframework.ws.transport.http.

➥    MessageDispatcherServlet</servlet-class>

<init-param>

<param-name>transformWsdlLocations</param-name>

<param-value>true</param-value>

</init-param>

</servlet>

Обнаружив параметр transformWsdlLocations со значением true, ком- понент MessageDispatcherServlet перезапишет адрес службы в WSDL- файле, возвращаемом компонентом SimpleWsdl11Definition, в соответ- ствии с адресом URL запроса.

Развертывание службы

Итак, мы создали определение службы, реализовали конечную точку и настроили все необходимые компоненты фреймворка Spring- WS. Сейчас все готово к упаковке и развертыванию веб-службы. Поскольку для управления проектом я выбрал инструмент Maven 2, создание WAR-файла для последующего развертывания сводится к выполнению простой команды:

%   mvn   package   deploy

Как только утилита mvn завершит работу, в целевом каталоге по- явится файл Poker-WS.war, который можно развернуть на большин- стве серверов веб-приложений.

Пример применения фреймворка Spring-WS для создания веб- службы продемонстрировал лишь половину его возможностей. Вто- рая его половина включает клиентский API, реализующий ту же самую парадигму, основанную на обмене сообщениями. Посмотрим далее, как с помощью Spring-WS создать клиента, использующего службу оценки комбинации карт при игре в покер.

Источник:   Уоллс К., Spring в действии. – М.: ДМК Пресс, 2013. – 752 с.: ил.

По теме:

  • Комментарии