Kратко рассмотрены основные положения архитектуры веб-сервисов. Освещена разработка веб-сервиса и его клиентов. Пример основывается на реализации концепции веб-сервисов в рамках Java-технологий (Apache AXIS). (Внимание! Статья написана в начале 2003, в ней рассматривается Apache AXIS 1.0. Apache AXIS 1.1 и выше несколько отличны от него. Поэтому имейте под рукой документацию к AXIS. ;-)
Сеть Интернет стала общепризнанным фактором деловой и общественной жизни. Широкая распространенность и возросшая пропускная способность создают условия, при которых выгодно решать многие задачи при помощи интернет-технологий.
Однако Интернет объединяет в себе много различных платформ, а информация содержится в разнообразных источниках данных. Поэтому актуальна проблема связи таких разнородных данных, а также создания способа, который позволяет получать их в виде удобном для дальнейшей обработки.
Концепция веб-сервисов (Web Services) призвана решить эту задачу объединения, интеграции разнородных систем на основе открытых стандартов. Данная работа посвящена веб-сервисам, в ней кратко рассмотрены основные положения модели веб-сервисов, а также компоненты этой модели и технологии, используемые для их реализации. Практическая часть работы содержит небольшой пример, демонстрирующий разработку веб-сервиса и приложений использующих его. Пример основывается на реализации концепции веб-сервисов в рамках Java-технологий. Для понимания примера достаточно базовых знаний Java.
Веб-сервисы являются концепцией создания таких приложений, функции которых можно использовать при помощи стандартных протоколов Интернет. В настоящее время эту концепцию применяют и развивают многие ведущие компании в IT-области. Концепция веб-сервисов реализуется при помощи ряда технологий, которые стандартизованы World Wide Web Consortium (W3C).
Взаимосвязь этих технологий можно условно представить следующим образом.
Веб-сервисы являются одним из вариантов реализации компонентной архитектуры.
XML является фундаментом для создания большинства технологий, связанных с веб-сервисами.
Для удаленного взаимодействия с веб-сервисами используется Simple Object Access Protocol (SOAP) [3]. SOAP обеспечивает взаимодействие распределенных систем, независимо от объектной модели, операционной системы или языка программирования. Данные передаются в виде особых XML документов особого формата.
Согласно определению W3C, веб-сервисы это приложения, которые доступны по протоколам, которые являются стандартными для Интернет. Нет требования, чтобы веб-сервисы использовали какой-то определенный транспортный протокол. Спецификация SOAP определяет, каким образом связываются сообщения SOAP и транспортный протокол.
Наиболее часто реализуется передача SOAP сообщений по протоколу HTTP. Также широко распространено использование в качестве транспортного протокола SMTP, FTP, TCP.
Согласно определению W3C, "WSDL - формат XML для описания сетевых сервисов как набора конечных операций, работающих при помощи сообщений, содержащих документно-ориентированную или процедурно-ориентированную информацию" [4]. Документ WSDL полностью описывает интерфейс веб-сервиса с внешним миром. Он предоставляет информацию об услугах, которые можно получить, воспользовавшись методами сервиса, и способах обращения к этим методам.
Технология Universal Description, Discovery and Integration (UDDI) предполагает ведения реестра веб-сервисов. Подключившись к этому реестру, потребитель сможет найти веб-сервисы, которые наилучшим образом удовлетворяют его потребностям. Технология UDDI дает возможность поиска и публикации нужного сервиса, как человеком, так и программой-клиентом. Поиск и публикация в реестре предоставляется программе-клиенту как набор веб-сервисов реестра UDDI.
Веб-сервисы позиционируются как программное обеспечение промежуточного слоя. Использовать веб-сервисы могут как клиентские приложения, непосредственно работающие с пользователем, так и другие приложения (в том числе и другие веб-сервисы).
Веб-сервисы размещаются на серверах приложений.
Разработчики концепции веб-сервисов предлагают следующие сценарии применения веб-сервисов:
Веб-сервисы как реализация логики приложения (бизнес-логики). То есть, создание нового приложения бизнес-логика, которого реализуется в веб-сервисе.
Веб-сервисы как средство интеграции. То есть, использование веб-сервиса как способа доступа удаленных клиентов к внутренней ИС компании, или для организации взаимодействия компонента (например, EJB, COM-компонента) с различными удаленными клиентами.
Создание альтенативного сервиса. В этом случае, при разработке нового веб-сервиса используется описание интерфейса уже существующего веб-сервиса. Таким образом, сервис имеет много потенциальных клиентов сразу с момента начала работы, а подключение к нему не требует существенных изменений на стороне клиента.
Как было сказано выше, концепция веб-сервисов включает в себя возможность ведения реестра веб-сервисов. Описание интерфейса может быть получено из такого реестра. После создания и внедрения нового веб-сервиса, имеет смысл зарегистрировать его в реестре. Тогда клиенты при поиске сервисов, реализующих исходный интерфейс, получат указание и на новый веб-сервис.
Использование веб-сервиса как строительного блока при создании приложения. Приложение может использовать веб-сервисы как удаленные компоненты, которые предоставляют определенную функциональность. Существуют различные сервисы, которые предоставляют качественное решение таких задач как аутентификация, ведение календаря, отправка сообщений, поиск, перевод и т. п.
Кроме этого, и возможны другие варианты использования веб-сервисов. Например, существуют исследования по использованию веб-сервисов для построения распределенных вычислительных и информационных систем и одноранговых и со сложной иерархической структурой.
Целью практической части данной работы является знакомство читателя с основными положениями разработки веб-сервисов и их использования. А также с реализацией модели веб-сервисов на платформе Java-технологий. Знания, полученные при изучении этого примера, можно применить и при работе с веб-сервисами на других платформах.
Пример веб-сервиса, созданный в практической части данной работы, носит учебный характер. И сам веб-сервис и его клиенты упрощены таким образом, чтобы показать основные моменты создания и использования веб-сервисов, не отвлекая на моменты, не связанные непосредственно с концепцией веб-сервисов.
При создании примера я ориентировался на широко распространенные программные продукты, а также старался, чтобы они не были сложны в использовании. Поэтому была выбрана реализация архитектуры веб-сервисов на базе AXIS и библиотека SOAP::Lite (использовалась в данной работе для создания клиентских приложений на Perl-е).
Итак, для изучения примера потребуются следующие знания:
Пусть существует FAQ(Частые Вопросы и Ответы) по некоторой тематике. В него включаются часто задаваемые вопросы на форумах по этой тематике. Ответы в FAQ создаются на основе ответов участников форумов. Те, чьи ответы используются в FAQ, включаются в список FAQmaker-ов.
Задачей нашего веб-сервиса будет предоставление удаленному приложению информации о FAQmaker-ах. Такой информацией будет список FAQmaker-ов, наиболее активные FAQmaker-ы, данные по конкретному FAQmaker-у (выдаваемые, например, по его имени).
Для разработки примера веб-сервиса использовалась реализация архитектуры веб-сервисов в Java-технологиях. Такой реализацией является проект Apache Software Foundation под названием AXIS (Apache eXtensible Interaction System). AXIS включает в себя контейнер для размещения и использования веб-сервисов на серверах приложений, утилиты для работы с WSDL-описаниями, классы для разработки веб-сервисов и их клиентов.
Для работы AXIS требуется парсер XML. В документации к AXIS рекомендуется использовать Xerces.
Для организации сервера приложений для веб-сервисов, кроме AXIS понадобится JSP/Servlet контейнер, поддерживающий спецификацию 2.2 для сервлетов. Я предлагаю использовать Tomcat 4.
Также необходимо Java JDK 1.3 или выше.
При разработке клиентов веб-сервиса использовался Perl 5.6 c библиотекой SOAP::Lite. Для ОС Windows 98/Windows 2000/Windows XP я предлагаю использовать ActivePerl 5.6.
Использовать какую-либо особенную среду разработки (IDE) для создания веб-сервиса и его клиентов необязательно.
Как сказано в постановке задачи, веб-сервис должен предоставлять своему клиенту данные по конкретному FAQmaker-у, имена наиболее активных FAQmaker-ов, а также полный список FAQmaker-ов.
Примем решение, что данные по конкретному FAQmaker-у веб-сервис выдает в виде экземпляра класса MakerInfo. Класс MakerInfo содержит 2 поля: имя (FAQmaker) и число его ответов (Answer), которые включены в FAQ.
public class MakerInfo {
public String FaqMaker;
public int Answer;
}
Имена наиболее активных FAQmaker-ов веб-сервис возвращает как массив строк, а полный список FAQmaker-ов выдается веб-сервисом как массив объектов MakerInfo.
Таким образом, наш веб-сервис можно представить в виде класса FaqMakerService.
public class FaqMakerService{
/**метод возвращает полный список FAQmaker-ов
*/
public MakerInfo[] getMakerList(){
MakerInfo ResInfos[];
. . .
return ResInfos;
}
/**метод возвращает информацию о FAQmaker-е по имени (Name)
*/
public MakerInfo getMakerInfo(String Name){
MakerInfo ResInfo;
. . .
return ResInfo;
}
/**метод возвращает имена наиболее активных FAQmaker-ов
*/
public String mostActiveMaker(){
. . .
return mostActiveMakerNames;
}
}
Класс FaqMakerService и является исходным кодом нашего веб-сервиса.
Пример веб-сервиса носит учебный характер, поэтому класс реализующий веб-сервис намеренно упрощен, в нем не используется соединение с БД, или получение данных из другого источника.
Для того, чтобы передавать данные по протоколу SOAP, сервер должен иметь механизм упаковки этих данных в набор тегов сообщения SOAP. Протокол SOAP предусматривает автоматическое преобразование для простых типов, а также для массивов, для элементов которых определен механизм преобразования.
Веб-сервис FaqMakerService передает клиенту объекты MakerInfo, поэтому для класса MakerInfo необходимо организовать механизм сериализации. Для нашего случая AXIS предлагает использовать так называемый "beanMapping". Для использования "beanMapping" полный код класса MakerInfo должен реализовывать интерфейс java.io.Serializable.
Механизм "beanMapping" - наиболее простой в использовании механизм преобразования. При его использовании достаточно убедится, что передаваемый сложный тип реализует интерфейс java.io.Serializable, а также описать при развертывании веб-сервиса имя типа и пространство имен, к которому он относится.
Для использования веб-сервиса FaqMakerService, его необходимо разместить на сервере приложений. Веб-приложение, в которое войдет веб-сервис, должно иметь доступ к AXIS, а также к парсеру XML.
Приложение располагается в каталоге приложений сервера (обычно "каталог Tomcat"/webapp), в отдельном подкаталоге с именем этого приложения.
AXIS размещается на сервере приложений как сервлет. JAR-файлы, составляющие AXIS , помещаются в каталог веб-приложения: в "приложение"/WEB-INF/lib/. В качестве парсера XML используется xerces. Парсер может быть отдельным для приложения и располагаться в каталоге приложения: в "приложение"/WEB-INF/lib/, или использоваться совместно с другими приложениями на сервере и располагаться вместе с другими совместно используемыми JAR-файлами (обычно "каталог Tomcat"/common/lib/).
Кроме того, необходимо настроить параметры приложения в "приложение"/WEB-INF/web.xml (зарегистрировать AXIS, открыть доступ к сервисам приложения, указать, как веб-серверу передавать WDSL-файлы).
Для веб-сервиса FaqMakerService будем использовать веб-приложение webservice, доступ к веб-сервисам этого приложения откроем как /webservice/services/*.
Настройки AXIS находятся в файле /webservice/WEB-INF/server-config.wsdd (server-config.wsdd сконфигурированный для нового приложения надо скопировать из дистрибутива AXIS). В нем указываются установленные веб-сервисы. По умолчанию установлен веб-сервис для администрирования AXIS. Теперь при обращении к /webservice /services/* можно увидеть сообщения от AXIS.
Для установки веб-сервиса FaqMakerService необходимо описать для AXIS следующую информацию:
Также надо указать механизм сериализации для класса MakerInfo.
Информация для развертывания веб-сервиса содержится в специальном файле - deployment descriptor-е (*.wsdd). Deployment descriptor веб-сервиса FaqMakerService - файл FaqMaker.wsdd
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="urn:FaqMaker" provider="java:RPC">
<parameter name="allowedMethods"
value="mostActiveMaker getMakerList getMakerInfo"
/>
<parameter name="className" value="FaqMakerService"/>
</service>
<beanMapping xmlns:ns1="urn:FaqMaker"
languageSpecificType="java:MakerInfo"
qname="ns1:MakerInfo"
/>
</deployment>
Классы (откомпилированные), которые реализуют веб-сервис, надо скопировать в каталог веб-приложения, в /WEB-INF/classes.
Для осуществления развертывания веб-сервиса нужно использовать утилиту AdminClient:
java org.apache.axis.client.AdminClient -l хостинг/веб-приложение/services/AdminService FaqMaker.wsdd
Установленный веб-сервис появляется в server-config.wsdd. Теперь его можно использовать.
Для использования веб-сервиса клиент должен обладать следующей информацией:
В простейшем случае можно задать эту информацию при разработке клиента
С учетом сказанного можно создать простейший клиент для веб-сервиса urn:FaqMaker. Ниже приведен исходный код, где получается информация по FAQMaker-у зарегистрированному как "Ivanov".
#подключение библиотеки SOAP::Lite
use SOAP::Lite;
print "SOAP::Lite - FaqMaker Direct Client\n";
print "возвращается объект MakerInfo\n";
$mi = SOAP::Lite
->uri('urn:FaqMaker')
->proxy('http://localhost:8070/webservice/services/')
->getMakerInfo('Ivanov')
->result;
#$mi содержит объект MakerInfo
#при сериализации первая буква приводится к ниж. регистру
print $mi->{faqMaker}, "\t", $mi->{answer}, "\n";
Скрипт FaqMakerDirectClient.pl - клиент, который использует все методы веб-сервиса urn:FaqMaker.
Этот и все приведенные ниже клиенты веб-сервиса urn:FaqMaker всего лишь выводят информацию, полученную от веб-сервиса. Однако они позволяют продемонстрировать различные способы подключения к веб-сервису, а также преимущества и недостатки этих способов.
В состав AXIS входит утилита tcpmon, которая позволяет следить за обменом сообщений между клиентом и веб-сервисом.
java org.apache.axis.utils.tcpmon
В настройке утилиты указывается прослушиваемый порт и адрес, на который надо перенаправлять сообщения. Tcpmon позволит нам пронаблюдать за взаимодействием квинта FaqMakerDirectClient.pl и веб-сервиса urn:FaqMaker.
Сообщения SOAP передаются между клиентом и веб-сервисом в теле сообщений HTTP.
Рассмотрим использование клиентом метода getMakerInfo().
Вот фрагмент вызова метода getMakerInfo():
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope>
. . .
<SOAP-ENV:Body>
<namesp2:getMakerInfo xmlns:namesp2="urn:FaqMaker">
<c-gensym4 xsi:type="xsd:string">Ivanov
</c-gensym4>
</namesp2:getMakerInfo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Вызываемый метод и его параметры передаются внутри тела сообщения SOAP (тег <SOAP-ENV:Body>). Название веб-сервиса используется как указание пространства имен, к которому относится название метода.
Вот фрагмент ответа метода getMakerInfo():
. . .
<ns1:getMakerInfoResponse
. . .
xmlns:ns1="urn:FaqMaker">
<getMakerInfoResult href="#id0"/>
</ns1:getMakerInfoResponse>
<multiRef id="id0"
. . .
xmlns:ns2="urn:FaqMaker">
<faqMaker xsi:type="xsd:string">Ivanov</faqMaker>
<answer xsi:type="xsd:int">5</answer>
</multiRef>
. . .
Название вызванного метод и его результат передаются внутри тела сообщения SOAP (тег <SOAP-ENV:Body>). Тег <ns1:getMakerInfoResponse> определяет ответное сообщение метода getMakerInfo(), а тег <getMakerInfoResult> определяет результат этого метода. Результатом метода является сложный структурированный объект MakerInfo, его содержимое вынесено из тега <ns1:getMakerInfoResponse>.
Взаимодействие клиента и веб-сервиса при использовании метода getMakerList() и метода mostActiveMaker() имеют некоторые отличия.
Во-первых, оба метода не имеют входных параметров, поэтому для них, при вызове метода веб-сервиса, тег, определяющий вызываемый метод имеет пустое тело.
Во-вторых, оба метода выдают результат в виде массива. Метод mostActiveMaker() возвращает массив строк. Этот массив передается внутри <mostActiveMakerResult>.
. . .
<mostActiveMakerResult xsi:type="SOAP-ENC:Array"
SOAP-ENC:arrayType="xsd:string[2]"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<item xsi:type="xsd:string">Ivanov
</item>
<item xsi:type="xsd:string">Sidorov
</item>
</mostActiveMakerResult>
. . .
Метод getMakerList() возвращает массив объектов MakerInfo.
. . .
<getMakerListResult xsi:type="SOAP-ENC:Array"
SOAP-ENC:arrayType="ns1:MakerInfo[3]"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<item href="#id0"/>
<item href="#id1"/>
<item href="#id2"/>
</getMakerListResult>
. . .
Содержимое элементов массива объектов MakerInfo вынесено в тег <multiRef>.
Кроме этого, протокол SOAP предусматривает реакцию веб-сервиса на различные ошибки. Например, на неверный вызов методов. Информация об ошибках в протоколе SOAP передается при помощи тегов
<fault>
<faultcode>. . .</faultcode>
<faultstring>. . .</faultstring>
<faultdetail>. . .</faultdetail>
</fault>
Если ошибок не было, то эти теги отсутствуют в сообщении.
Покажем реакцию веб-сервиса urn:FaqMaker на неверный вызов метода.
FaqMakerDirectClient_Fault.pl - клиент, вызывающий несуществующий метод и метод с неверными параметрами.
use SOAP::Lite;
print "SOAP::Lite - FaqMaker Direct Client\n";
my $soap = SOAP::Lite
->uri('urn:FaqMaker')
->proxy('http://localhost:8070/webservice/services/');
#попытка вызова несуществующего метода getInfo()
print "возвращается объект MakerInfo\n";
$som=$soap->getInfo('Ivanov');
#сервер сообщает об ошибке
if ($som->fault) {
print $som->faultcode, "\n", $som->faultstring, "\n";
}else{
print "call getInfo('Ivanov') is done. %(\n";
}
print "возвращается String\n";
#попытка вызова mostActiveMaker() с неверным числом параметров
$som=$soap->mostActiveMaker(dfhgf);
#сервер сообщает об ошибке
if ($som->fault) {
print $som->faultcode, "\n", $som->faultstring, "\n";
}else{
print "call mostActiveMaker(dfhgf) is done %(\n";
}
Документ WSDL полностью описывает интерфейс веб-сервиса с внешним миром, он дает клиенту возможность получить необходимую информацию для использования веб-сервиса.
Клиент может использовать WSDL-описание в виде файла, хранящегося на жестком диске вместе с клиентской программой, а также в виде веб-ресурса.
AXIS может создать по запросу WSDL-описание для установленных веб-сервисов. Для получения WSDL-описания нужно обратится в браузере по адресу
хост/веб-приложение/services/имя_сервиса?WSDL
Отметим некоторые важные моменты в WSDL-описании веб-сервиса urn:FaqMaker.
Методы веб-сервиса urn:FaqMaker используют сложные (комплексные) типы данных: объекты класса MakerInfo, массив объектов класса MakerInfo, массив строк. Эти комплексные типы имеют описание в WSDL-документе для веб-сервиса urn:FaqMaker.
. . .
<complexType name="MakerInfo">
<sequence>
<element name="FaqMaker" nillable="true" type="xsd:string"/>
<element name="Answer" type="xsd:int"/>
</sequence>
</complexType>
<element name="MakerInfo" nillable="true" type="tns1:MakerInfo"/>
. . .
<complexType name="ArrayOf_tns1_MakerInfo">
<complexContent>
<restriction base="SOAP-ENC:Array">
<attribute ref="SOAP-ENC:arrayType"
wsdl:arrayType="tns1:MakerInfo[]"/>
</restriction>
</complexContent>
</complexType>
<element name="ArrayOf_tns1_MakerInfo" nillable="true"
type="intf:ArrayOf_tns1_MakerInfo"/>
. . .
Скрипт FaqMakerWSDLClient.pl - клиент, который использует веб-сервис urn:FaqMaker при помощи его WSDL-описания. Ниже приведен фрагмент скрипта FaqMakerWSDLClient.pl
use SOAP::Lite
service => 'http://localhost:8070/webservice/services/urn:FaqMaker?WSDL';
print "SOAP::Lite - FaqMaker WSDL Client\n";
my $mlist = getMakerList();
print "возвращается массив объектов MakerInfo \n";
foreach $r ( @$mlist ){
print $r->{faqMaker}, "\t", $r->{answer}, "\n";
}
Очевидно, что использование WSDL-документа имеет существенные преимущества по сравнению с прямым указанием местоположения, имени, методов и параметров веб-сервиса:
Скрипт FaqMakerWSDLClient_badmethod.pl демонстрирует попытку использования неверного имени метода и неправильных входных параметров.
use SOAP::Lite;
print "SOAP::Lite - FaqMaker WSDL Client\n";
#попытка использовать несуществующий метод getList()
my $m = SOAP::Lite
->service('http://localhost:8070/webservice/services/urn:FaqMaker?WSDL')
->getList();
#при интерпретации скрипта библиотека SOAP::Lite выдаст ошибку
#попытка вызова mostActiveMaker() с неверным числом параметров
my $m = SOAP::Lite
->service('http://localhost:8070/webservice/services/urn:FaqMaker?WSDL')
->mostActiveMaker(Ivanov);
#при интерпретации скрипта библиотека SOAP::Lite выдаст ошибку
Пример веб-сервиса носит учебный характер, поэтому класс FaqMakerService, реализующий веб-сервис, намеренно упрощен, в нем не используется соединение с БД, или получение данных из другого источника. Клиенты не производят каких-либо особенных действий, а просто выводят результат, полученный из метода веб-сервиса.
Однако, используя знания, полученные при прочтении данной работы, можно создать свой веб-сервис и клиентов с необходимой функциональностью. Стоит отметить, что работа веб-сервиса с БД (или использование EJB-компонента) осуществляется так же как в сервлетах и JSP-страницах.
Знания, полученные при изучении веб-сервиса FaqMakerService и его клиентов из данной работы, можно применить как при разработке своих веб-сервисов и клиентов в рамках Java-технологий, так и при работе с веб-сервисами на других платформах.
В архиве "source4ws.zip" находятся исходные тексты веб-сервиса, его клиентов, а также deployment descriptor, WSDL-описание и bat-файлы для компиляции, установки веб-сервиса на сервере приложений.
В ходе прочтения данной работы вы познакомились с концепцией веб-сервисов, узнали об основных технологиях, составляющих модель веб-сервисов, и о роли этих технологий.
В работе продемонстрировано создание несложного веб-сервиса, взаимодействие с ним клиентских приложений как с явным заданием веб-сервиса и метода, так и с использованием описания сервиса в виде WSDL-документа.
Я считаю, что данная работа может быть использована как основа для дальнейшего изучения технологий, объединенных концепцией веб-сервисов.
P.S. На моем сайте http://pavelsha.pp.ru опубликовано еще несколько вводных статей по веб-сервисам и архитектуре, ориентированной на сервисы.