Как создать wsdl файл из xml
SCA генерирует WSDL для компонентов, которые содержат аннотацию @binding.soap после аннотации @service. Чтобы создать WSDL, SCA во время исполнения с помощью Reflection отражает компонент и анализирует аннотации @param и @return для каждого публичного метода, а также любые аннотации @types в компоненте. Информация из аннотаций @param и @return используется для построения раздела WSDL <types>. Любые аннотации @types, которые указывают на отдельный файл схемы, приведут к созданию элемента <import> в схеме WSDL.
Аттрибут location элемента <service>
Внизу WSDL присутствует элемент <service>, который использует аттрибут location для идентификации URL сервиса. К примеру он может быть таким:
Обертка WSDL документ/литерал и позиционные параметры
SCA генерирует WSDL в стиле обертки документ/литерал. Этот стиль помещает параметры и возвращаемые типы метода в "обертки", которые названы в честь соответствующего метода. Элемент WSDL <types> каждую из этих оберток. Если мы рассмотрим метод getQuote() примера ConvertedStockQuote:
<?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-схему для этих параметров. Секция типов будет выглядеть как-то так:
Когда SCA генерирует WSDL для SCA-компонента, он включает комментарий в WSDL, который отмечает, что WSDL является интерфейсом для SCA-компонента. В этом случае, когда один компонент SCA вызывает другой через веб-сервис, SCA на вызывающем конце во время исполнения принимает список позиционных параметров из вызова и, один за другим, присваивает значения названным элементам в SOAP-запроса. Например, вызов метода getQuote() , определенного выше, которому передаются значения "IBM" и "USD", выглядит так:
В результате SOAP-запрос будет выглядеть так:
И на стороне клиента и на стороне сервиса SCA будет полагаться на тот порядок аргументов, в каком они появились в SOAP-запросе и считать, что именно в этом порядке аргументы нужно передавать в запрошенный метод. Изначально этот порядок определяется порядком описания аргументов с помощью аннотаций @param. Т.е. порядок аннотаций @param определяет как порядок аргументов метода, так и порядок в котором аргументы будут описаны в SOAP-запросе.
Когда-то поставили передо мной задачу начать разработку Web-сервисов и дали мне сорцы простейшего проекта без каких-либо объяснений. Проект, конечно же, не запускался. Что такое Spring и как он работает, я тоже представления не имел. Адекватных статей по разработке Web-сервисов средствами Spring ни русскоязычных, ни англоязычных я тоже не смог найти. Пришлось разбираться во всем самому, оказалось все не так страшно.
И вот недавно я решил посмотреть, какие новые возможности добавились в Spring с тех пор, и обновить старые сервисы, что в результате и сподвигло меня на написание данной статьи.
Данная статья является руководством по разработке простейшего Web-сервиса, использующего SOAP-протокол, средствами Spring-WS.
И так, писать будем простейший сервис, принимающий имя пользователя и отправляющий приветствие и текущее время на сервере.
Что же нам потребуется?
Подготовка к работе
Создаем новый проект Web-приложения. В Eclipse это: «File => New => Dynamic Web Project».
Я назвал проект: HelloService.
Далее копируем библиотеки из Spring, XMLBean, wsdl4j, commons-logging в каталог проекта WEB-INF/lib.
При желании можете добавить их к библиотекам сервера, чтобы не таскать их с каждым приложением.
Создание WSDL-схемы
По сути WSDL-схема предназначена для описания сервиса.
Вручную создавать её мы, конечно же, не будем. Схема будет сгенерирована автоматически средствами Spring'а, но об этом позднее.
Определяем входные и выходные данные
- String имя.
- String приветствие;
- Time текущее время.
Создаем описание входных и выходных данных
В каталоге WEB-INF создаем файл HelloService.xsd. Данный файл нужен будет для генерации WSDL-схемы и создания соответствующих Java-классов.
Текст файла:
Атрибут targetNamespace – используемое пространство имен. Т.е. все созданные объекты будут располагаться в пакете org.example.helloService.
Элементы ServiceRequest и ServiceResponse описывают соответственно входные и выходные данные (запрос/ответ).
Атрибуты minOccurs и maxOccurs определяют количество повторений данного компонента в пределах одного элемента. Если эти параметры не указывать, то по умолчанию они считаются равными 1. Для необязательного компонента необходимо указать minOccurs=0. При неограниченном количестве компонент: maxOccurs=unbounded.
Подробнее о XML-схемах можно прочитать здесь.
Создаем JavaBeans
На основании созданной схемы будем создавать Java классы. Для этого создаем файл build.xml:
Параметр WS_HOME должен указывать на каталог, где располагается XMLBeans.
HelloService.xsd – путь к созданной схеме.
lib\helloservice.jar – создаваемая java-библиотека.
Далее запускаем Ant-build (надеюсь, вы его уже установили).
В Eclipse можно запустить так: ПКМ по файлу build.xml=> Run As => Ant Build.
Если через командную строку:
ant -buildfile build.xml
Ну и ждем завершения построения. После чего, можем проверить каталог проекта WEB-INF\lib на наличие соответствующей библиотеки (helloservice.jar).
Реализация сервиса
Создаем интерфейс и класс сервиса
Интерфейс сервиса: HelloService.java:
Реализация сервиса: HelloServiceImpl.java:
Данный код, я думаю, не нуждается в комментариях. Единственное, что у людей, не сталкивающихся ранее со Spring'ом, может вызвать вопросы, так это аннотация @ Service. Но об этом же расскажу чуть позже.
Endpoint
Endpoint – класс, который будет отвечать за обработку входящих запросов (своего рода точка входа).
Создаем файл HelloServiceEndpoint.java:
Что же здесь сделано?
Аннотация @Endpoint как раз и определяет, что данный класс будет обрабатывать входящие запросы.
namespaceUri – то же пространство имен, что и указывалось при создании xml-схемы.
Теперь вернемся немного назад и вспомним про аннотацию @ Service. Если не вдаваться в подробности, чтобы не перегружать читателя лишней информацией, то эта аннотацию говорит Spring'у создать соответствующий объект. А аннотация @Autowired служит для инъекции (автоматической подстановки) соответствующего объекта. Конечно же при построении простых приложений в использовании данных аннотаций отсутствует смысл, но я решил все-такие не исключать их в данном примере.
И так, идем далее.
Аннотация @PayloadRoot перед методом определяет, при получении какого запроса будет вызван данный метод. В нашем случае, это «ServiceRequest».
В остальном опять же все должно быть ясно. Обратите внимание, что ServiceRequest, ServiceResponse и т.д. – это как раз те классы, которые были созданы на основе нашей xml-схемы.
Spring-конфигурация сервиса
Вот и близится уже завершение.
Создаем файл service-ws-servlet.xml.
sws:annotation-driven – говорит как раз о том, что в данном проекте используются аннотации.
А context:component-scan указывает на пакет, в котором будет производится поиск аннотаций, при этом поиск производится и в подпакетах.
Два последующих бина всегда будут неизменны. Суть их заключается в приеме и преобразовании запроса из Xml в Java-объект и дальнейшего обратного преобразования.
sws:dynamic-wsdl отвечает за автоматическую генерацию WSDL-документа на основе созданной Xml-схемы.
location указывает на путь к схеме.
locationUri – адрес (относительно контейнера), по которому будет доступна WSDL-схема.
В моем случае WSDL доступен по следующему адресу:
localhost/HelloService/HelloService.wsdl
Дескриптор развертывания
Ну и, наконец, последнее.
В каталоге WEB-INF изменяем или создаем файл web.xml.
Данный файл описывать уже не буду, большинство и так должны знать. Для несложных проектов он по сути не должен изменяться. Стоит отметить только, что имя сервлета(servlet-name) должно соответствовать имени файла Spring-конфигурации сервиса service-ws-servlet.xml.
Ну и далее деплоим приложение на сервер.
На этом создание сервиса завершено. Если ничего не пропустили, то сервис должен функционировать.
Проверка работоспособности
Использование XML совместно с SQL
Эту статью я собирался написать очень давно. Около года прошло с момента появления первой части «Использование XML совместно с SQL», а это – очень большой срок для современной IT-индустрии. Сейчас уже доступна первая бета новой версии SQL Server-а под кодовым названием «Yukon». В нем будет просто сумасшедшее количество нововведений, связанных с XML (и не только), одним из которых является возможность напрямую обращаться к серверу через Internet. Как вы знаете, в текущей версии это невозможно: взаимодействие с сервером происходит через специальное ISAPI-расширение, которое является частью пакета SQLXML. Вообще, по сравнению с Yukon (или Oracle9i), поддержка XML в SQL Server 2000 очень слаба. По существу, она ограничивается двумя конструкциями: FOR XML и OPENXML. Вся остальная функциональность реализуется с помощью SQLXML[1]. Все, что предоставляет SQLXML, как-то: шаблоны, запросы в URL, запросы XPath в конечном счету превращаются в ту или иную форму SQL-запроса, вида:
Вызов хранимых процедур и функций через Internet – также целиком и полностью заслуга SQLXML: с помощью ISAPI-расширения он перехватывает SOAP-запросы, транслирует их в вызовы соответствующих функций и процедур SQL Server-а и возвращает результат в виде XML. Трансформация выбранного recordset-а в XML происходит на основе информации конфигурационного файла (расширение ssc), но обо всем по порядку.
Настройка IIS
Для того чтобы стал возможен вызов хранимых процедур и функций как Web-методов, необходимо создать и настроить виртуальную директорию Internet-сервера. Это выполняется с помощью консоли «IIS Virtual Directory Management for SQLXML 3.0». Я не буду рассматривать все шаги этого процесса, так как для всех типов запросов (soap, templates, dbobject и schema) он одинаков. Подробную информацию об этом можно получить из документации по SQLXML 3.0 и в [1]. Рассмотрим лишь, как настроить запросы типа soap. На рисунке 1 приведен пример.
Рисунок 1. Создание Web-сервиса.
Здесь имя виртуальной директории – «srv». Имя Web-сервиса – webserv, тип директории – soap, имя хоста – dcit06. Кроме этого, необходимо указать физический путь до папки, где будут располагаться конфигурационный файл и файл описания Web-сервиса. После того, как вы нажмете кнопку «Save», SQLXML создаст wsdl-файл, в котором будет содержаться описание Web-сервиса, и конфигурационный файл ssc, в котором будут содержаться описания всех Web-методов и их параметров. Файл ssc предназначен только для внутренних служебных нужд SQLXML, его формат нигде не описан и в любой момент может измениться.
На вкладке Settings не забудьте поставить галочку напротив опции «Allow POST».
Содержание wsdl-файла
WSDL – это специальный формат, предназначенный для описания Web-сервисов, их методов, параметров и используемых протоколов. Это обычный XML-документ с корневым тегом definitions, содержащий описания типов, параметров, операций, протоколов и сервисов. Они подробно будут описаны далее. SQLXML генерирует файл в формате WSDL 1.1, который имеет статус ноты (как и SOAP 1.1).
ПРИМЕЧАНИЕ
Файл WSDL условно можно поделить на две части: абстрактную и конкретную часть. Первая описывает типы, параметры и операции и не касается конкретных протоколов и конечных точек (endpoints) или сервисов. WSDL предназначен не только для работы по протоколу SOAP, так что описание конкретного транспорта выделается в отдельные, конкретные элементы, описание которых находится в второй части WSDL файла. Рассмотрим по порядку фрагменты абстрактной и конкретной частей, которые далее в статье будут называться секциями.
Секция types
Эта секция содержит набор схем в формате XML Schema, каждая из которых описывает абстрактные типы, не зависящие от какого-либо языка или машины. Эта секция не является обязательной и может быть опущена, если Web-сервис не нуждается в дополнительных типах (как правило, это составные типы – complex types) и вполне обходится стандартными, определенными в XML Schema.
SQLXML определяет четыре схемы типов:
Простой тип nonNegativeInteger – целочисленный тип без знака в диапазоне от 0 до 2147483647.
Атрибут IsNested булевого типа.
Простой тип SqlResultCode - целочисленный тип без знака в диапазоне от 0 до 2147483647, который используется для описания возвращаемого хранимой процедурой значения.
Сложный тип SqlMessage – содержит поля для описания кода ошибки, номера строки, строкового представления ошибки и других параметров.
Сложный тип SqlResultStream – содержит одно и более вхождений полей следующих типов: SqlRowSet, SqlXml, SqlMessage и SqlResultCode.
Пространство имен конкретного Web-сервиса, которое импортирует все вышеперечисленные пространства имен и описывает типы, необходимые конкретным Web-методам. В данный момент эта схема не содержит ни одного описания, так как пока Web-сервис не определил каких-либо Web-методов.
В качестве примера приведу фрагмент WSDL-файла, сгенерированного при создании виртуальной директории.
Секция message
Эта секция содержит описания параметров Web-методов. В текущем WSDL-файле ее нет, так как мы пока еще не определили никакого метода. Вообще, секция message состоит из набора частей (parts), каждая из которых описывает конкретный параметр. Часть может быть и одна, в этом случае используется несколько отличный синтаксис, при котором задается конкретный элемент части, вместо перечисления нескольких типов. Ниже приведен пример одинаковых параметров.
Секция portType
Последняя секция, где описываются абстрактные параметры Web-сервиса. Эта секция является обязательной и содержит неопределенное количество необязательных разделов operation. Операции описывают конкретные Web-методы. Так как у нас пока нет Web-методов, то и количество разделов operation равно нулю.
Возможны также и комбинации этих форматов: RPC/literal, document/encoded. Рассмотрим их по порядку.
Encoded-сериализация слишком сложна и объемна для этой статьи. Интересующихся отсылаю к разделу 5 спецификации [6]. Что касается WSDL-документа, то используя этот тип сериализации, вы не можете указывать конкретных элементов в части секции message. Т.е. допустим только синтаксис указания типа.
Этот урок освещает пошаговое создание сервера SOAP web сервиса с использованием Spring.
Что вы создадите
Вы создадите сервер, который предоставляет данные из различных Европейских стран, используя WSDL SOAP web сервис.
Для простоты примера, вы будете использовать фиксированные данные Соединенного королевства, Испании и Польши.Что вам потребуется
- Примерно 15 минут свободного времени
- Любимый текстовый редактор или IDE и выше
- Вы также можете импортировать код этого урока, а также просматривать web-страницы прямо из Spring Tool Suite (STS), собственно как и работать дальше из него.
Как проходить этот урок
Как и большинство уроков по Spring, вы можете начать с нуля и выполнять каждый шаг, либо пропустить базовые шаги, которые вам уже знакомы. В любом случае, вы в конечном итоге получите рабочий код.
Чтобы начать с нуля, перейдите в Настройка проекта.
Когда вы закончите, можете сравнить получившийся результат с образцом в gs-producing-web-service/complete .
Настройка проекта
Для начала вам необходимо настроить базовый скрипт сборки. Вы можете использовать любую систему сборки, которая вам нравится для сборки проетов Spring, но в этом уроке рассмотрим код для работы с Gradle. Если вы не знакомы с ней, ознакомьтесь с соответсвующим уроком Сборка Java-проекта с использованием Gradle.
Создание структуры каталогов
В выбранном вами каталоге проекта создайте следующую структуру каталогов; к примеру, командой mkdir -p src/main/java/hello для *nix систем:
Создание файла сборки Gradle
Ниже представлен начальный файл сборки Gradle. Если вы используете Spring Tool Suite (STS), то можете импортировать урок прямо из него.
Если вы посмотрите на pom.xml , вы найдете, что указана версия для maven-compiler-plugin. В общем, это не рекомендуется делать. В данном случае он предназначен для решения проблем с нашей CI системы, которая по умолчанию имеет старую(до Java 5) версию этого плагина.Spring Boot gradle plugin предоставляет множество удобных возможностей:
- Он собирает все jar'ы в classpath и собирает единое, исполняемое "?ber-jar", что делает более удобным выполнение и доставку вашего сервиса
- Он ищет public static void main() метод, как признак исполняемого класса
- Он предоставляет встроенное разрешение зависимостей, с определенными номерами версий для соответсвующих Spring Boot зависимостей. Вы можете переопределить на любые версии, какие захотите, но он будет по умолчанию для Boot выбранным набором версий
Добавление Spring-WS зависимости
Созданный вами проект должен включать в ваш файл сборки зависимости spring-ws-core и wsdl4j.
Создание XML схемы для определения домена
Домен web сервиса описан в файле XML схемы(XSD), который Spring-WS будет экспортировать автоматически как WSDL.
Создайте XSD файл с операциями для возвращения name, population, capital и currency:
Генерация доменных классов на основе XML схемы
Следубщим шагом необходимо сгенерировать Java классы из XSD файла. Правильным подходом является их автоматическое создание в процессе сборки с использованием плагина maven или gradle.
Конфигурация плагина для maven:
Сгенерированные классы будут помещены в target/generated-sources/jaxb/ каталог.
То же самое и с gradle:
Следующий шаг - добавление задачи getJaxb , необходимой gradle для генерации Java классов:
Т.к. gradle не имеет JAXB плагина(пока), он включает в себя ant задачу, которая делает файл сборки немного сложнее по сравнению с файлом сборки Maven.
В обоих случаях, процесс генерации объектов включен в жизненный цикл сборки, поэтому не требуются отдельные шаги по запуску этого процесса.
Создание репозитория
Для предоставления данных web сервисом, создайте репозиторий. В этом уроке вы создаете простой репозиторий с установленными данными.
Создание точки выхода сервиса
Для создания точки выхода сервиса, вам необходим только POJO с несколькими Spring WS аннотациями для обработки входящих SOAP запросов.
@ResponsePayload создает соответствующее значение возвращаемому значению полезной части ответа.
Во всех этих фрагментах кода, классы io.spring.guides будут выбрасывать ошибку компиляции в вашей IDE до тех пор, пока вы не запустите задачу генерации доменных классов на основе WSDL.Конфигурирование бинов web сервиса
Создайте новый класс, связанный с конфигурацией Spring WS бинов:
Создание приложения исполняемым
main() метод передает управление вспомогательному классу SpringApplication, где Application.class - аргумент его run() метода. Это сообщает Spring о чтении метаданных аннотации из Application и управлении ею как компонента в Spring application context.
Аннотация @ComponentScan говорит Spring'у рекурсивно искать в пакете hello и его потомках классы, помеченные прямо или косвенно Spring аннотацией @Component. Эта директива гарантирует, что Spring найдет и зарегистрирует CountryRepository и CountriesEndpoint , потому что он отмечен @Controller , который, в свою очередь, является своего рода @Component аннотацией.
Аннотация @EnableAutoConfiguration переключает на приемлемое по умолчанию поведение, основанное на содержании вашего classpath. К примеру, т.к. приложение зависит от встраиваемой версии Tomcat (tomcat-embed-core.jar), Tomcat сервер установлен и сконфигурирован на приемлемое по умолчанию поведение от вашего имени. И т.к. приложение также зависит от Spring MVC (spring-webmvc.jar), Spring MVC DispatcherServlet сконфигурирован и зарегестрирован для вас - web.xml не нужен! Автоконфигурация полезный и гибкий механизм. Подробную информацию смотрите в API документации.
Сборка исполняемого JAR
Вы можете собрать единый исполняемый JAR-файл, который содержит все необходимые зависимости, классы и ресурсы. Это делает его легким в загрузке, версионировании и развертывании сервиса как приложения на протяжении всего периода разработки, на различных средах и так далее.
Затем вы можете запустить JAR-файл:
Если вы используете Maven, вы можете запустить приложение, используя mvn spring-boot:run , либо вы можете собрать приложение с mvn clean package и запустить JAR примерно так:
Процедура, описанная выше, создает исполняемый JAR. Вы также можете вместо него собрать классический WAR-файл.Запуск приложения
Если вы используете Gradle, вы можете запустить ваш сервис из командной строки:
Если вы используете Maven, то можете запустить ваш сервис таким образом: mvn clean package && java -jar target/gs-producing-web-service-0.1.0.jar .Как вариант, вы можете запустить ваш сервис напрямую из Gradle примерно так:
Тестирование приложения
Когда приложение запустится, вы можете протестировать его. Создайте файл request.xml , содержащий следующий SOAP запрос:
Существует несколько способов тестирования SOAP интерфейса. Вы можете использовать что-то типа SoapUI или просто использовать инструменты командной строки, если у вас *nix/Mac система, как показано ниже:
В результате вы должны увидеть следующий ответ:
Поздравляем! Вы только что создали SOAP сервис с использованием Spring Web Services.
Читайте также: