Описание Web Services на языке WSDL. Язык WSDL. Структура WSDL-документа. Способы создания. Режимы операции WSDL
Заголовок топика – это действительно вопрос, т.к. я сам не знаю, что это и впервые попробую поработать с этим в рамках настоящей статьи. Единственное, что могу гарантировать, что код, представленный ниже, будет работать, однако мои фразы будут лишь предположениями и догадками о том, как я сам все это понимаю. Итак, поехали…
Введение
Начать надо с того, для чего создавалась концепция веб-сервисов. К моменту появления этого понятия в мире уже существовали технологии, позволяющие приложениям взаимодействовать на расстоянии, где одна программа могла вызвать какой-нибудь метод в другой программе, которая при этом могла быть запущена на компьютере, расположенном в другом городе или даже стране. Все этого сокращенно называется RPC (Remote Procedure Calling – удаленный вызов процедур). В качестве примеров можно привести технологии CORBA, а для Java – RMI (Remote Method Invoking – удаленный вызов методов). И все вроде в них хорошо, особенно в CORBA, т.к. с ней можно работать на любом языке программирования, но чего-то все же не хватало. Полагаю, что минусом CORBA является то, что она работает через какие-то свои сетевые протоколы вместо простого HTTP, который пролезет через любой firewall. Идея веб-сервиса заключалась в создании такого RPC, который будет засовываться в HTTP пакеты. Так началась разработка стандарта. Какие у этого стандарта базовые понятия:- SOAP . Прежде чем вызвать удаленную процедуру, нужно этот вызов описать в XML файле формата SOAP. SOAP – это просто одна из многочисленных XML разметок, которая используется в веб-сервисах. Все, что мы хотим куда-то отправить через HTTP, сначала превращается в XML описание SOAP, потом засовывается в HTTP пакет и посылается на другой компьютер в сети по TCP/IP.
- WSDL . Есть веб-сервис, т.е. программа, методы которой можно удаленно вызывать. Но стандарт требует, чтобы к этой программе прилагалось описание, в котором сказано, что «да, вы не ошиблись – это действительно веб-сервис и можно у него вызвать такие-то такие-то методы». Такое описание представляется еще одним файлом XML, который имеет другой формат, а именно WSDL. Т.е. WSDL – это просто XML файл описания веб-сервиса и больше ничего.
Общий подход
В веб-сервисах всегда есть клиент и сервер. Сервер – это и есть наш веб-сервис и иногда его называют endpoint (типа как, конечная точка, куда доходят SOAP сообщения от клиента). Нам нужно сделать следующее:- Описать интерфейс нашего веб-сервиса
- Реализовать этот интерфейс
- Запустить наш веб-сервис
- Написать клиента и удаленно вызвать нужный метод веб-сервиса
Сервер
Запустим IDEA и создадим новый проект Create New Project . Укажем имя HelloWebService и нажмем кнопку Next , далее кнопку Finish . В папке src создадим пакет ru.javarush.ws . В этом пакете создадим интерфейс HelloWebService: package ru. javarush. ws; // это аннотации, т.е. способ отметить наши классы и методы, // как связанные с веб-сервисной технологией import javax. jws. WebMethod; import javax. jws. WebService; import javax. jws. soap. SOAPBinding; // говорим, что наш интерфейс будет работать как веб-сервис @WebService // говорим, что веб-сервис будет использоваться для вызова методов @SOAPBinding (style = SOAPBinding. Style. RPC) public interface HelloWebService { // говорим, что этот метод можно вызывать удаленно @WebMethod public String getHelloString (String name) ; } В этом коде классы WebService и WebMethod являются так называемыми аннотациям и ничего не делают, кроме как помечают наш интерфейс и его метод, как веб-сервис. Это же относится и к классу SOAPBinding . Разница лишь в том, что SOAPBinding – это аннотация с параметрами. В данном случае используется параметр style со значением, говорящим, что веб-сервис будет работать не через сообщения-документы, а как классический RPC, т.е. для вызова метода. Давайте реализуем логику нашего интерфейса и создадим в нашем пакете класс HelloWebServiceImpl . Кстати, замечу, что окончание класса на Impl – это соглашение в Java, по которому так обозначают реализацию интерфейсов (Impl – от слова implementation, т.е. реализация). Это не требование и вы вольны назвать класс как хотите, но правила хорошего тона того требуют: package ru. javarush. ws; // таже аннотация, что и при описании интерфейса, import javax. jws. WebService; // но здесь используется с параметром endpointInterface, // указывающим полное имя класса интерфейса нашего веб-сервиса @WebService (endpointInterface = "ru.javarush.ws.HelloWebService" ) public class HelloWebServiceImpl implements HelloWebService { @Override public String getHelloString (String name) { // просто возвращаем приветствие return "Hello, " + name + "!" ; } } Запустим наш веб-сервис как самостоятельный сервер, т.е. без участия всяких Tomcat и серверов приложений (это тема отдельного разговора). Для этого в структуре проекта в папке src создадим пакет ru.javarush.endpoint , а в нем создадим класс HelloWebServicePublisher с методом main: package ru. javarush. endpoint; // класс, для запуска веб-сервера с веб-сервисами import javax. xml. ws. Endpoint; // класс нашего веб-сервиса import ru. javarush. ws. HelloWebServiceImpl; public class HelloWebServicePublisher { public static void main (String. . . args) { // запускаем веб-сервер на порту 1986 // и по адресу, указанному в первом аргументе, // запускаем веб-сервис, передаваемый во втором аргументе Endpoint. publish ("http://localhost:1986/wss/hello" , new HelloWebServiceImpl () ) ; } } Теперь запустим этот класс, нажав Shift+F10 . В консоли ничего не появится, но сервер запущен. В этом можно убедиться набрав в браузере строку http://localhost:1986/wss/hello?wsdl . Открывшаяся страница, с одной стороны, доказывает, что у нас на компьютере (localhost) запустился веб-сервер (http://) на порту 1986, а, с другой стороны, показывает WSDL описание нашего веб-сервиса. Если вы остановите приложение, то описание станет недоступно, как и сам веб-сервис, поэтому делать этого не будем, а перейдем к написанию клиента.Клиент
В папке проекта src создадим пакет ru.javarush.client , а в нем класс HelloWebServiceClient с методом main: package ru. javarush. client; // нужно, чтобы получить wsdl описание и через него // дотянуться до самого веб-сервиса import java. net. URL; // такой эксепшн возникнет при работе с объектом URL import java. net. MalformedURLException; // классы, чтобы пропарсить xml-ку c wsdl описанием // и дотянуться до тега service в нем import javax. xml. namespace. QName; import javax. xml. ws. Service; // интерфейс нашего веб-сервиса (нам больше и нужно) import ru. javarush. ws. HelloWebService; public class HelloWebServiceClient { public static void main (String args) throws MalformedURLException { // создаем ссылку на wsdl описание URL url = new URL ("http://localhost:1986/wss/hello?wsdl" ) ; // Параметры следующего конструктора смотрим в самом первом теге WSDL описания - definitions // 1-ый аргумент смотрим в атрибуте targetNamespace // 2-ой аргумент смотрим в атрибуте name QName qname = new QName ("http://ws.сайт/" , "HelloWebServiceImplService" ) ; // Теперь мы можем дотянуться до тега service в wsdl описании, Service service = Service. create (url, qname) ; // а далее и до вложенного в него тега port, чтобы // получить ссылку на удаленный от нас объект веб-сервиса HelloWebService hello = service. getPort (HelloWebService. class ) ; // Ура! Теперь можно вызывать удаленный метод System. out. println (hello. getHelloString ("JavaRush" ) ) ; } } Максимум комментариев по коду я дал в листинге. Добавить мне нечего, поэтому запускаем (Shift+F10). Мы должны в консоли увидеть текст: Hello, JavaRush! Если не увидели, то видимо забыли запустить веб-сервис.Заключение
В данном топике был представлен краткий экскурс в веб-сервисы. Еще раз скажу, что многое из того, что я написал – это мои догадки по поводу того, как это работает, и поэтому мне не стоит сильно доверять. Буду признателен, если знающие люди меня поправят, ведь тогда я чему-нибудь научусь. UPD.В главе 2 мы говорили о том, что после создания Web-службы на сервере в виде сервлета, страницы JSP, JWS-файла, компонента EJB или другого объекта, следует описать состав и возможности Web-службы на языке, не зависящем от платформы, операционной системы, системы программирования, использованной при создании Web-службы. Это описание регистрируется в общедоступном месте Интернета, например, реестре UDDI или ebXML, или хранится на сервере Web-службы. Описание должно содержать полную и точную информацию обо всех услугах, предоставляемых Web-службой, способы получения услуг, содержимое запроса на получение услуги, формат предоставляемой информации.
Одно из средств точного и единообразного описания Web-услуг - язык WSDL, созданный консорциумом W3C. Этот язык - еще одна реализация XML. Его последняя рекомендованная спецификация всегда публикуется на странице http://www.w3.org/TR/wsdI . Во время написания книги на черновой стадии была версия WSDL 1.2, которую мы и опишем в этой главе.
Состав документа WSDL
Корневым элементом документа XML - описания WSDL - служит элемент
Описания WSDL активно используют различные пространства имен. Кроме собственных имен, язык WSDL часто использует имена типов и элементов языка описания схем XSD (см. главу 1) и имена языка протокола SOAP. Пространство имен языка WSDL часто описывается как пространство имен по умолчанию. Идентификатор пространства имен последней на время написания этих строк версии WSDL 1.2 был равен http://www.w3.org/2002/07/wsdl . Целевое пространство имен, идентификатор которого определяется атрибутом обычно получает префикс tns (target namespace).
В корневой элемент
?
?
?
?
?
? < service > - указывает местоположение Web-службы как один или несколько портов. Каждый порт описывается вложенным элементом
Кроме этих шести основных элементов есть еще два вспомогательных элемента.
?
Комментарий. Его можно включить в любой элемент
описания WSDL.
Можно сказать, что элементы
Элементы
Наконец, элементы
Структура документа WSDL показана в листинге 4.1. Символы в квадратных скобках не содержатся в документе. Они показывают повторяемость элемента или атрибута в описании Web-службы:
Символ [?] означает, что элемент или атрибут может появиться в документе нуль или один раз;
Символ [*] означает, что элемент может появиться нуль или несколько раз;
Символ [+] означает, что элемент может появиться один или несколько раз;
Отсутствие символа в квадратных скобках означает, что атрибут должен появиться ровно один раз.
j Листинг 4.1. Схема WSDL-документа
targetNamespace="nfleH l ra«iij location="URI-aflpec" /> [*] Произвольный комментарий Описания сложных и нестандартных типов.
Абстрактное описание SOAP-послания как набора составляющих его частей.
Абстрактное описание Web-службы как набора операций (услуг). Описание услуги как получения (input) и отправки (output, fault) посланий. Получаемое послание. Отправляемое message="nMH соотв. элемента Отправляемое сообщение об ошибке. type="MMH соотв. элемента Детали конкретного протокола. Они определяются в схеме этого протокола. -> Сюда записываются элементы, описывающие детали конкретной операции. -> Сюда записываются элементы, описывающие детали конкретного получаемого послания. -> Сюда записываются элементы, описывающие детали конкретного отправляемого послания. ->
Сюда записываются элементы, описывающие детали конкретного сообщения об ошибке. ->
serviceType="MMH соотв. элемента Описание интерфейса Web-службы как набора портов. binding="nMH соотв. элемента Сюда записывается обязательный и единственный адрес интерфейса Web-службы, записанный по правилам протокола, указанного в элементе
Каждый конкретный протокол пересылки посланий - SOAP, HTTP, FTP, SMTP - добавляет к шести основным и двум вспомогательным элементам языка WSDL свои дополнительные элементы, описывающие особенности данного протокола.
Приведем простой пример. В листинге 3.14 мы записали в виде класса Java простейшую Web-службу, возвращающую без всякой обработки присланный запрос:
public class EchoService{
public String getEcho (String req) { return req;
В листинге 4.2 приведено описание этой Web-службы на языке WSDL, использующее протокол SOAP.
Листинг 4.2. Описание Web-службы EchoService
version="1.0" encoding="UTF-8" ?>
targetNamespace="http://echoservice.com/echoservice.wsdl" xmlns="http://www.w3.org/2002/07/wsdl" xmlns:tns="http://echoservice.com/echoservice.wsdl" xmlns:soap="http://www.w3.org/2002/07/wsdl/soapl2" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
transport="http://schemas.xmlsoap.org/soap/http" /> "http://schemas.xmlsoap.org/soap/encoding/" namespace= "http: //echoservice. ccm/echcservice .wsdl" use="encoded" /> ^oapKbocy enccdingStyle= "http: //schemas .xmlsoap. org/soap/encoding/" namespace= "http: //echoservice. c^/ech^service .wsdl" use="encoded" /> "http://localhost:8080/axis/EchoService.jws" /> В листинге 4.2 мы в элементе Имена "getEchoRequest" И "getEchoResponse" ИСПОЛЬЗОВаны В следующем элементе txarspcrt^=^"ht:tp^://?cheпas^.>пlscap^.c^rc^/?cap^/ht:tp^" /> Если применяется документный стиль SOAP, то в атрибуте style записывается значение "document". Наконец, в элементе В листинге 4.2 имена с префиксом soap конкретизировали описание послания и способы его пересылки. Посмотрим, какие конкретные протоколы предлагает спецификация WSDL 1.2. Литература:
Хабибуллин И. Ш. Разработка Web-служб средствами Java. - СПб.: БХВ-Петербург, 2003. - 400 с: ил.
Когда-то поставили передо мной задачу начать разработку Web-сервисов и дали мне сорцы простейшего проекта без каких-либо объяснений. Проект, конечно же, не запускался. Что такое Spring и как он работает, я тоже представления не имел. Адекватных статей по разработке Web-сервисов средствами Spring ни русскоязычных, ни англоязычных я тоже не смог найти. Пришлось разбираться во всем самому, оказалось все не так страшно. Данная статья является руководством по разработке простейшего Web-сервиса, использующего SOAP -протокол, средствами Spring-WS. Далее запускаем Ant-build (надеюсь, вы его уже установили). Создаем файл HelloServiceEndpoint.java: Теперь вернемся немного назад и вспомним про аннотацию @ Service
. Если не вдаваться в подробности, чтобы не перегружать читателя лишней информацией, то эта аннотацию говорит Spring"у создать соответствующий объект. А аннотация @Autowired
служит для инъекции (автоматической подстановки) соответствующего объекта. Конечно же при построении простых приложений в использовании данных аннотаций отсутствует смысл, но я решил все-такие не исключать их в данном примере. В остальном опять же все должно быть ясно. Обратите внимание, что ServiceRequest, ServiceResponse и т.д. – это как раз те классы, которые были созданы на основе нашей xml-схемы. Два последующих бина всегда будут неизменны. Суть их заключается в приеме и преобразовании запроса из Xml в Java-объект и дальнейшего обратного преобразования. sws:dynamic-wsdl
отвечает за автоматическую генерацию WSDL-документа на основе созданной Xml-схемы. Для дальнейшей проверки нам потребуется soapUI (у меня версия 3.0.1). Как WSDL 1.1 определяет Web-сервисы, и как создать модели на языке Java для верификации и преобразования WSDL-документов Web-сервисы ― важная функция технологии Java™ в корпоративных вычислениях. В этом цикле статей консультант по XML и Web-сервисам Денис Сосновский рассказывает об основных структурах и технологиях, ценных для Java-разработчиков, использующих Web-сервисы. Следите за статьями цикла, чтобы быть в курсе последних разработок в данной области и знать, как применить их в своих собственных проектах. Web-сервисы для корпоративных приложений в значительной степени зависят от использования определений сервисов. Определения сервисов описывают основное соглашение между поставщиком услуг и любым потенциальным потребителем, детализируя типы функций, предоставляемых сервисом, и сообщения в рамках каждой функции. Поставщики и потребители свободны в выборе способа реализации своих объектов обмена в той мере, в какой фактические сообщения, которые они посылают, соответствуют определению сервиса. Использование определения сервиса с описанием способа обмена XML-сообщениями ― это то, что отличает Web-сервисы от более ранних технологий распределенного программирования. Предлагались различные методы определения Web-сервисов, но наиболее широко используемым подходом остается WSDL 1.1. WSDL 1.1 имеет некоторые недостатки, в том числе чрезмерно сложную структуру, которая затрудняет его чтение для непосвященных. Он страдает также от отсутствия авторитетного формального определения, что привело к последовательным «уточнениям», которые заполняют некоторые пробелы в исходном документе спецификации. В результате стеки Web-сервисов стараются обрабатывать документы WSDL 1.1 как можно более гибко. Эта гибкость может усилить путаницу в понимании WSDL 1.1, так как разработчики видят широкий спектр WSDL-структур без каких-либо указаний на то, какой подход предпочтительнее. В этой статье мы покажем, как разобрать документы WSDL 1.1, и рассмотрим первые части модели Java для проверки WSDL-документов и их преобразования в стандартную форму. В этой статье используются: Редакция 1.1 WSDL, опубликованная в начале 2001 года, технически заменена рекомендациями W3C WSDL 2.0, опубликованными в 2007 году. WSDL 2.0 предлагает более четкую структуру, чем WSDL 1.1, наряду с большей гибкостью. Но WSDL 2.0 страдает от проблемы курицы и яйца: WSDL 2.0 не используется широко, потому что не поддерживается широко, а так как он широко не используется, у разработчиков стеков Web-сервисов мало стимулов его поддерживать. Несмотря на все его недостатки, для большинства целей WSDL 1.1 достаточно хорош. Оригинальная спецификация WSDL 1.1 была неточной в отношении количества используемых функций. Так как в центре внимания WSDL была работа с определениями служб SOAP, он включал также поддержку функций SOAP (таких как кодирование rpc), которые позднее оказались нежелательными. Организация Web Services Interoperability Organization (WS-I) решила эти проблемы в Базовом профиле (BP), который содержит практические рекомендации по Web-сервисам с использованием SOAP и WSDL. BP 1.0 был утвержден в 2004 году, а в 2006 году вышла редакция BP 1.1. В этой статье рассматривается WSDL 1.1 на базе рекомендаций BP WS-I и не затрагиваются фактически устаревшие функции, такие как кодирование rpc для SOAP. Предполагается, что структура XML-документов задается определениями XML-схемы. В первоначальную спецификацию WSDL 1.1 входит описание схемы, но эта схема в нескольких отношениях не соответствует текстовым описаниям. Позже это было исправлено в модифицированной версии схемы, но документ WSDL 1.1 не был отредактирован с учетом этого изменения. Затем группа BP WS-I решила внести еще больше изменений в схему WSDL и создала то, что преподносится как практические рекомендации к этой скользкой схеме. Документы, написанные для одной версии схемы, как правило, не совместимы с другими версиями (несмотря на то, что используется одно и то же пространство имен), но к счастью, большинство инструментов Web-сервисов в основном игнорирует схему и принимает все, что выглядит разумным. (См. ссылки на многие схемы WSDL в разделе ). Даже версия BP WS-I схемы WSDL 1.1 не очень помогает гарантировать соответствие спецификации документов WSDL 1.1. Схема не отражает всех ограничений BP WS-I, особенно в отношении порядка следования компонентов. Кроме того, XML-схема не способна обработать многие типы легко устанавливаемых ограничений в документах (такие как альтернативные атрибуты или необходимые дополнительные элементы из отдельной схемы). Поэтому проверка соответствия документа WSDL 1.1 спецификации WSDL 1.1 (с поправками, внесенными BP WS-I) включает в себя гораздо больше, чем просто выполнение валидации XML-схемы. Мы еще вернемся к данной теме в этой статье. Но сначала рассмотрим структуру описаний сервиса WSDL 1.1. В документах WSDL 1.1 используется фиксированный корневой элемент с удобным названием Существует также элемент Для полного описания сервиса, как правило, требуется, по крайней мере, один элемент каждого из этих типов, за исключением В листингах 1 и показан пример описания сервиса WSDL, разбитого на два WSDL-документа, так что компоненты описания интерфейса содержится в файле BookServerInterface.wsdl, а компоненты реализации ― в файле BookServerImpl.wsdl. В листинге 1 показан BookServerInterface.wsdl. В листинге 2 показан BookServerImpl.wsdl. Элемент Помимо определений элементов (и атрибутов) в пространстве имен WSDL 1.1, WSDL 1.1 определяет также дополнительные элементы. Они предназначены для заполнения конкретных ячеек в описаниях сервисов WSDL 1.1 для передачи дополнительной информации, необходимой для конкретного типа сервисов. Единственные дополнительные элементы WSDL 1.1, которые все еще широко используются, это привязки для SOAP 1.1 (они представлены в , в элементах Элемент Поскольку один элемент Помимо Сообщения, представленные элементами Элементы WSDL 1.1 определяет несколько шаблонов взаимодействия между клиентом и поставщиком услуг, представленных различными последовательностями дочерних элементов Каждый элемент Во многих отношениях SOAP 1.1 широко используется для Web-сервисов с момента опубликования спецификации в 2000 году. Версия SOAP 1.2 разработана при более широкой поддержке отрасли через W3C и опубликована в качестве официального стандарта W3C в 2007 году. SOAP 1.2 лучше документирована и чище, чем SOAP 1.1, причем некоторые уродливые аспекты 1.1 хирургически удалены. Несмотря на эту очищенную структуру, для большинства Web-сервисов практических различий между ними немного. Вероятно, наиболее существенная особенность SOAP 1.2 заключается в том, что это единственный официально поддерживаемый способ использования расширенной поддержки SOAP-вложений XML-binary Optimized Packaging (XOP) и SOAP Message Transmission Optimization Mechanism (MTOM). В цикле Web-сервисы Java
я до сих пор использовал SOAP 1.1, потому что некоторые старые стеки не поддерживают SOAP 1.2, но для разработки новых Web-сервисов 1.2, вероятно, является лучшим выбором. Элементы Дочерние элементы Расширения, определяемые WSDL, вступают в игру в Внутри каждого дочернего элемента Последним компонентом описания сервиса WSDL является элемент Не удивительно, что при всех вариациях схем и правил для документов WSDL 1.1 многие документы не соответствуют практическим рекомендациям BP WS-I. Поддержка всеми стеками Web-сервисов многих отклонений от практических рекомендаций помогла увековечить использование устаревших или неправильных конструкций, что привело к распространению дурной практики по всей отрасли. И я определенно не застрахован от этой инфекции – просматривая WSDL-документы, которые я приводил в качестве примеров кода для этого цикла, я к своему удивлению обнаружил, что ни один из них не является полностью корректным. Так что когда я решил написать эту статью, я подумал, что было бы хорошо включить в нее инструмент, с помощью которого можно проверять WSDL-документы на соответствие практическим рекомендациям. Казалось бы, отсюда всего один шаг до преобразования WSDL-документов в правильную форму, при условии, что оригинальный WSDL свободен от ошибок. Но работы оказалось значительно больше, чем я первоначально планировал, и полную информацию об этой модели я включу в следующие две статьи этого цикла. Для работы с WSDL-документами на языке Java построено множество различных моделей, в том числе широко используемый язык описания Web-сервисов для Java Toolkit (WSDL4J), который представляет собой эталонную реализацию JSR 110 (см. раздел ). Ни одна из этих моделей не соответствует тому, что я собирался сделать, ввиду двоякой постановки задачи: во-первых, чтение WSDL-документов в любой полуразумной форме и сообщение об ошибках и отклонениях от практических рекомендаций, и во-вторых, написание безошибочных WSDL-документов, переформатированных в форму, соответствующую практическим рекомендациям. WSDL4J, например, не сохраняет порядок вводимых элементов, так чтобы можно было сообщать о проблемах порядка их следования, и не обрабатывает определения схемы, так что его нельзя напрямую использовать для проверки ссылок из элементов В этой статье я использую термин верификация
для обозначения проверки правильности WSDL-документа, потому что альтернативный термин валидация
, обычно используемый для XML-документов, означает проверку документов на соответствие определению схемы. Ранее я уже частично реализовал модель WSDL для использования с привязкой данных JiBX в рамках проекта JiBX/WS. Эта модель предназначена только для вывода и включает относительно небольшое число классов, которые в некоторых случаях объединяют данные из вложенных элементов структуры WSDL XML ( Еще один вариант ― генерирование кода из схемы BP WS-I для WSDL 1.1. Увидев это, я понял, что простое использование созданных классов напрямую приведет к путанице, так как схема включает избыточные типы, а также некоторые неудобные конструкции, которые используются для представления различных моделей обмена сообщениями (некоторые из которых затем были запрещены текстом BP WS-I). Так что в конечном итоге я составил классы вручную, хотя результат оказался почти таким же, как если бы я начал с кода, сгенерированного из схемы, и просто сократил ненужное дублирование и сложность. Привязка данных JiBX поддерживает несколько связей с одними и теми же классами, так что мне удалось создать привязку ввода для обработки всего спектра вариантов, допускаемых любой версией WSDL 1.1, хотя настройка привязки выхода для вывода WSDL была только в форме, соответствующей практическим рекомендациям. В листинге 3 показана часть класса Definitions , соответствующая корневому элементу Организация данных дочерних элементов в показывает, каким образом модель поддерживает как общую форму ввода, так и форму вывода в соответствии с практическими рекомендациями. Вместо единого списка дочерних элементов всех типов, используются отдельные списки для каждого типа. Привязка ввода JiBX обрабатывает дочерние элементы как неупорядоченный набор, вызывая специфический для данного типа элементов set-метод всякий раз, когда дочерний элемент находится не на своем месте. Вместо того чтобы заменять какое-либо из предшествующий значений, set-метод добавляет экземпляр в типизированный список, как видно из set-метода addMessage() , который используется для дочерних элементов В любом из элементов WSDL разрешены дополнительные атрибуты и элементы (как правило, все атрибуты или элементы, которые не используют пространство имен WSDL 1.1). Примером таких дополнительных элементов служат конфигурации WS-Policy, встроенные в WSDL-документы из предыдущих статей данного цикла, как и ссылки на фактические политики. Лучше всего, чтобы эти дополнительные элементы предшествовали любым дочерним элементам из пространства имен WSDL 1.1, и именно так они обрабатываются в привязке вывода. Привязка ввода обрабатывает дополнительные элементы и атрибуты с помощью кода базового класса из классов элементов WSDL, не показанного в , и позволяет элементам следовать в любом порядке (генерируя предупреждение, если они следуют за элементом из пространства имен WSDL 1.1). Модель обрабатывает известные элементы, используя отдельные привязки для каждого дополнительного пространства имен, каждая из которых имеет свой собственный набор классов. Я рассмотрю обработку этих дополнительных элементов более подробно в следующем выпуске Web-вервисов Java
, где будет подробнее представлен и исходный код. Некоторая базовая верификация данных WSDL выполняется по мере добавления немаршаллизованных объектов, соответствующих элементам, в древовидную структуру WSDL-документа, как показано в коде addMessage() в конце . Этот код использует метод checkAdd() для проверки порядка следования дочерних элементов и метод addName() для проверки того, что представлено допустимое имя (текст соответствует типу схемы NCName и значение уникально в пределах типа элемента), и отображения имени на объект. Но это только проверка самой основной информации для отдельного элемента; для проверки других свойств каждого элемента и взаимосвязей между элементами необходим дополнительный код верификации. JiBX позволяет вызывать обработчики пользовательских расширений в рамках процесса маршаллинга и демаршаллинга. Для исполнения логики верификации модель WSDL использует один из таких дополнительных обработчиков, метод post-set. Метод post-set вызывается после завершения демаршаллинга связанного объекта, так что это часто хороший способ выполнения проверок типа верификации объектов. В случае проверки WSDL простейший подход – это выполнение всей верификации объектов из одного метода post-set для корневого элемента В этой статье изложены основы структуры и использования WSDL и введение в модель данных Java для WSDL, предназначенную для поддержки верификации WSDL-документов и их преобразования в форму, соответствующую практическим рекомендациям. Следующая статья продолжит эту тему, рассматривая проблемы, часто встречающиеся при написании утверждений WS-Policy и WS-SecurityPolicy. Кроме того, в ней будет более подробно рассмотрена модель WSDL и процесс верификации, в том числе расширение модели с включением утверждений WS-Policy/WS-SecurityPolicy, встроенных в WSDL. WSDL
(Web Services Description Language
) версии 1.1 был опубликован 15 марта 2001 года. WSDL
- это формат, базирующийся на XML и использующийся для описания сетевых cервисов, при помощи сообщений, содержащих информация о том как осуществлять доступ к конкретному веб-сервису. WSDL
расширяем, что позволяет описывать услуги (сервисы) и их сообщения независимо от того, какие форматы сообщений или сетевые протоколы используются для транспорта, однако, чаще всего используется WSDL 1.1 вместе с SOAP 1.1, HTTP GET/POST и MIME. Поскольку WSDL
был разработан совместно с SOAP, в его разработке участвовали все те же фирмы Microsoft, Ariba и IBM. Если рассматривать документ WSDL
интуитивно, то можно сказать, что он позволяет ответить на 4 вопроса
: 1) что вы делаете?
Ответ на этот вопрос дается в форме пригодной как для восприятия человеком так и форме воспринимаемой машиной. Ответ для чел-ка в тегах: <name
/>, <documentation
/>, для машины - <message
/>, <pointType
> 2) на каком языке вы разговариваете?
(какие типы вы используете?)Ответ в теге: <types
/> 3) как я буду с вами общаться?
(как клиент будет обращаться к веб-службе?):HTTP или SMTP. Ответ находится в <binding
/> 4) где мне вас найти?
(где я могу найти эту веб-службу или какой у нее URL?). Ответ находится: <service
/> Структура:
Каждый документ WSDL можно разбить на три логические части: 1. определение типов данных
- определение вида отправляемых и получаемых сервисом XML сообщений 2. абстрактные операции
- список операций, которые могут быть выполнены с сообщениями 3. связывание сервисов
- способ, которым сообщение будет доставлено Документы WSDL
можно создавать вручную, однако строгая формализация языка WSDL
позволяет автоматизировать процесс написания WSDL
-документов. Многие интсрументальные средства создания Web-служб содержат утилиты, которые автоматичеки создают WSDL
-файлы, описывающие готовые Web-службы. Например средство создания Web-служб Apache Axis
содержит в своем составе класс Java2WSDL
, создающий WSDL
-файл по классу или интерфейсу Java, описывающему Web-службу. Пакет IBM WSTK, в состав которого входит Axis
, содержит утилиту java2wsdl
, создающую и запускающую объект из этого класса. Она работает из командной строки. Элементы WSDL-документа Опишем наиболее часто употребляемые теги WSDL: Тег 1)target Name space – это пространство имен нашей веб-службы 2)xmlns – стандартное пространство имен документа WSDL 3)xmlns: SOAP_ENC – пространство имен используемое для описания кодировки SOAP 4)xmlns: impl и intf – пространство имен реализации и определения нашей веб-службы · Документ для определения веб-службы · Документ для реализации веб-службы Для простоты, как правило, используют 1 файл, который содержит всю информацию Элемент Для описания вызова RPC необходимо создать входной сообщение и выходное сообщение. В рамках этого элемента можно указать параметры метода с помощью элемента
Элемент Операции могут иметь входные сообщения, а также сообщения об ошибках. Элемент Элемент Элемент import
. Очень часто элемент service выделяется в свой wsdl документ из соображений практичности. Для того, чтобы позволить собрать из нескольких wsdl документов один используется элемент import. Он позволяет включать один wsdl документ в другой. Элемент types
позволяет указать типы передаваемых данных если они не являются стандартными. WSDL поддерживает 4 режима операций: · операции типа one-way или односторонние операции. Сообщение посылается конечной точке службы. В этом случае операция описывается только одним входным сообщением. · Request-Response – режим запрос-ответ. Этот режим операции является наиболее общим. В этом режиме описание операции содержит входное и выходное сообщение и необязательное сообщение об ошибке. · Операция типа требование-ответ. В этом режиме конечной точкой является клиент другой конечной точки. Формат операции похож на режим запрос-ответ, но выходные данные перечисляются перед входными данными. · Операция уведомление. Этот режим – еще одна версия примитива односторонней передачи, в которой конечная точка посылает сообщение а не получает его. Операция содержит только выходное сообщение.
И вот недавно я решил посмотреть, какие новые возможности добавились в Spring с тех пор, и обновить старые сервисы, что в результате и сподвигло меня на написание данной статьи.
И так, писать будем простейший сервис, принимающий имя пользователя и отправляющий приветствие и текущее время на сервере.Что же нам потребуется?
Подготовка к работе
Создаем новый проект Web-приложения. В Eclipse это: «File => New => Dynamic Web Project».
Я назвал проект: HelloService.
Далее копируем библиотеки из Spring, XMLBean, wsdl4j, commons-logging в каталог проекта WEB-INF/lib.
При желании можете добавить их к библиотекам сервера, чтобы не таскать их с каждым приложением.Создание WSDL-схемы
По сути WSDL-схема предназначена для описания сервиса.
Вручную создавать её мы, конечно же, не будем. Схема будет сгенерирована автоматически средствами Spring"а, но об этом позднее.Определяем входные и выходные данные
Входные данные:
Выходные данные:Создаем описание входных и выходных данных
В каталоге 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-библиотека.
В Eclipse можно запустить так: ПКМ по файлу build.xml=> Run As => Ant Build.
Если через командную строку:
ant -buildfile build.xml
Ну и ждем завершения построения. После чего, можем проверить каталог проекта WEB-INF\lib на наличие соответствующей библиотеки (helloservice.jar).Реализация сервиса
Создаем интерфейс и класс сервиса
Интерфейс сервиса: HelloService.java:
package org.example;
import java.util.Calendar;
public interface HelloService {
public String getHello(String name) throws Exception;
public Calendar getCurrentTime();
}
Реализация сервиса: HelloServiceImpl.java:
package org.example;
import java.util.Calendar;
import org.springframework.stereotype.Service;
@Service
public class HelloServiceImpl implements HelloService {
public String getHello(String name) throws Exception {
return "Hello, " + name + "!";
}
public Calendar getCurrentTime() {
return Calendar.getInstance();
}
}
Данный код, я думаю, не нуждается в комментариях. Единственное, что у людей, не сталкивающихся ранее со Spring"ом, может вызвать вопросы, так это аннотация @ Service. Но об этом же расскажу чуть позже.Endpoint
Endpoint – класс, который будет отвечать за обработку входящих запросов (своего рода точка входа).
package org.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.example.helloService.ServiceRequestDocument;
import org.example.helloService.ServiceRequestDocument.ServiceRequest;
import org.example.helloService.ServiceResponseDocument;
import org.example.helloService.ServiceResponseDocument.ServiceResponse;
@Endpoint
public class HelloServiceEndpoint{
private static final String namespaceUri = "http://www.example.org/HelloService";
private HelloService helloService;
@Autowired
public void HelloService (HelloService helloService) {
this.helloService = helloService;
}
@PayloadRoot(localPart = "ServiceRequest", namespace = namespaceUri)
public ServiceResponseDocument getService(ServiceRequestDocument request) throws Exception {
ServiceRequestDocument reqDoc = request;
ServiceRequest req = reqDoc.getServiceRequest();
ServiceResponseDocument respDoc = ServiceResponseDocument.Factory.newInstance();
ServiceResponse resp = respDoc.addNewServiceResponse();
String userName = req.getName();
String helloMessage = testNewService.getHello(userName);
Calendar currentTime = testNewService.getCurrentTime();
resp.setHello(helloMessage);
resp.setCurrentTime(currentTime);
return respDoc;
}
}
Что же здесь сделано?
Аннотация @Endpoint
как раз и определяет, что данный класс будет обрабатывать входящие запросы.
namespaceUri
– то же пространство имен, что и указывалось при создании xml-схемы.Spring-конфигурация сервиса
Вот и близится уже завершение.
Создаем файл service-ws-servlet.xml.
sws:annotation-driven
– говорит как раз о том, что в данном проекте используются аннотации.
А context:component-scan
указывает на пакет, в котором будет производится поиск аннотаций, при этом поиск производится и в подпакетах.
location
указывает на путь к схеме.
locationUri
– адрес (относительно контейнера), по которому будет доступна WSDL-схема.
В моем случае WSDL доступен по следующему адресу:
localhost/HelloService/HelloService.wsdl Дескриптор развертывания
Ну и, наконец, последнее.
В каталоге WEB-INF изменяем или создаем файл web.xml.
Данный файл описывать уже не буду, большинство и так должны знать. Для несложных проектов он по сути не должен изменяться. Стоит отметить только, что имя сервлета(servlet-name) должно соответствовать имени файла Spring-конфигурации сервиса service-ws
-servlet.xml.Проверка работоспособности
Самым первым признаком корректной работы является созданная WSDL-схема.
Для проверки просто переходим по адресу этой схемы (http://localhost/HelloService/HelloService.wsdl) и смотрим: там должен отобразиться xml-файл. Если ничего не отобразилось или какая ошибка появилась, перечитываем внимательно всю статью и ищем, что сделали не так.
Устанавливаем и запускаем его.
Создаем новый проект: File => New soapUI Project. В поле Initial WSDL/WADL вставляем ссылку на WSDL-схему (http://localhost/HelloService/HelloService.wsdl).
В созданном проекте открываем необходимый запрос.
В поле Name вбиваем имя и жмем на кнопку «Send request»
В результате получаем ответ от сервера с приветствием и текущим временем.
Если что-то пошло не так, то опять перечитываем данную статью.Что дальше?
Ну а дальше предстоит написание клиента для данного Web-сервиса. Но это уже материал для другой статьи, которая возможно будет написана позже, если данный материал кого-то заинтересует.
Серия контента:
Об этом цикле статей
Разбор WSDL 1.1
Используемые пространства имен
Компоненты описания
Листинг 1. BookServerInterface.wsdl
Листинг 2. BookServerImpl.wsdl
Детали компонентов
Рисунок 1. Связи между компонентами WSDL
Сравнение SOAP 1.1 и 1.2
Работа с WSDL
Модель WSDL
Валидация и верификация
Листинг 3. Класс Definitions (частично)
public class Definitions extends ElementBase
{
/** Перечисление дочерних элементов в ожидаемом порядке. */
static enum AddState {
invalid, imports, types, message, portType, binding, service };
/** Список разрешенных имен атрибутов. */
public static final StringArray s_allowedAttributes =
new StringArray(new String { "name", "targetNamespace" });
/** Валидация используемого контекста. */
private ValidationContextВерификация модели
Другие дополнения