Главная страница

Разработка веб-служб средствами Java. Ильдар ХабибуллинРазработкаWebслужбсредствами


Скачать 9.24 Mb.
НазваниеИльдар ХабибуллинРазработкаWebслужбсредствами
АнкорРазработка веб-служб средствами Java.pdf
Дата03.02.2018
Размер9.24 Mb.
Формат файлаpdf
Имя файлаРазработка веб-служб средствами Java.pdf
ТипКнига
#15148
КатегорияИнформатика. Вычислительная техника
страница6 из 21
1   2   3   4   5   6   7   8   9   ...   21
и обязательное тело . Схема SOAP- послания такова:

Глава 2. Архитектура Web Services 93
?>


< ! — Содержимое послания —>


В заголовке содержится один или несколько блоков, оформление и содер- жание которых никак не регламентируются. Точно так же ничего не гово- рится о содержании тела послания. Тем не менее, различают процедурный
стиль послания SOAP, предназначенный для вызова удаленных процедур, и
документный стиль, предназначенный для обмена документами XML. Про- цедурный стиль часто называют а документный стиль — XML-
стилем.
Процедурный стиль послания SOAP
При вызове удаленных процедур по протоколу SOAP в заголовке послания устанавливают параметры вызова, например, номер транзакции, в которой выполняется процедура. В теле послания перечисляются аргументы вызы- ваемой процедуры.
Например, обращение к процедуре получения прогноза погоды, приведен- ной в предыдущем разделе, может выглядеть так:
?>
env:encodingStyle=

94 Разработка Web-служб средствами Java
location>

Аргументы вызываемой процедуры записываются как члены структуры,
именем которой служит имя процедуры. Оно же служит именем элемента
XML, представляющего структуру. Имя аргумента становится именем эле- мента XML, в теле которого записывается значение аргумента. Типы аргу- ментов определены в пространстве имен, указанном атрибутом
Приведенное в примере значение этого атрибута
http://www.w3.org/2002/06/soap-encoding определяет стандартное про- странство имен SOAP, описанное в спецификации. В этом пространстве имен определены стандартные типы SOAP.
Записанное таким образом SOAP-послание передается серверу по сети ка- ким-нибудь прикладным протоколом. Чаще всего это протокол HTTP или
SMTP. При пересылке по протоколу HTTP редко используется метод GET.
Обычно это метод POST с типом содержимого
Content-Type:
Ответ сервера выглядит так:
?>
env:encoding

Глава 2. Архитектура Web

Имя элемента, вложенного в тело, не имеет значения, но часто повторяется имя процедуры, дополненное словом "Response", как сделано в примере.
Возвращаемое значение представляется структурой или массивом. Имя струк- туры или массива определяется элементом
Этот элемент определен в пространстве имен с идентификатором http://www.w3.org/2002/06/ soap-rpc.
Такое двухступенчатое описание возвращаемого значения — сначала описывается элемент met: forecast, а уж потом возвращаемое значе- ние — удобно тем, что можно точно описать тип возвращаемого значе- ния в схеме документа XML. В приведенном примере это можно сделать при определении элемента в пространстве имен с идентифи- катором http://www.meteoservice.com/.
Впрочем, можно вернуть результат и прямо в теле элемента
Типы данных SOAP, определенные в пространстве имен с идентификатором
http://www.w3.org/2002/06/soap-encoding, во многом совпадают с типами данных языка XSD
главу 1). Их можно указать в схеме документа или прямо в документе, например:

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

Разработка Web-служб средствами Java

Как видно из приведенных примеров, кроме типов XSD, в SOAP-посланиях широко применяются массивы и структуры.
Массив состоит из безымянных элементов, они различаются своим поряд- ковым номером, например:
<пате>Сидоров
Элементы массива надо записывать в определенном порядке.
В отличие от массива у каждого элемента структуры есть свое имя, например:
Элементы структуры можно записывать в любом порядке.
Документный стиль послания SOAP
Послание SOAP может содержать не аргументы вызова какой-то а просто документ XML или структуру данных. Важно только сохранить схему послания — у него может быть необязательный заголовок и должно быть обязательное тело. Например:
?>



Глава 2. Архитектура Web Services 97

Такие послания характерны для асинхронного обмена сообщениями в духе электронной почты. Очень часто они пересылаются не по протоколу HTTP,
а по какому-нибудь почтовому протоколу, например, SMTP .
Мы ознакомимся подробно с протоколом SOAP в следующей главе, а пока заметим лишь, что консорциум W3C решил разработать стандартный про- токол пересылки документов XML, взяв за основу XML-RPC, SOAP и дру- гие известные протоколы. Новый протокол сначала был назван
(XML
Protocol). Это сокращение совпало с широко распространенным обозначе- нием экстремального программирования
Programming). Кроме то- го, в моду вошли четырехбуквенные аббревиатуры, и новый протокол на- звали XMLP (XML Protocol). Его разработка затягивается. На время напи- сания книги она была на начальной стадии, и не было ни одной производственной реализации протокола XMLP. Более того, появились све- дения, что консорциум оставит за ним название SOAP, изменив только но- мер версии протокола.
Средства разработки SOAP
Итак, протокол предоставления Web-услуг есть, остается его реализовать.
Написано уже много средств создания SOAP-серверов и SOAP-клиентов.
Их длинный список можно посмотреть на сайте
Ведущие фирмы, выпускающие продукты для предоставления Web-услуг —
IBM, Microsoft, Sun, Oracle — выпустили свои
Фирма IBM вначале выпустила продукт разработки SOAP-серверов и кли- ентов SOAP4J, но затем передала его разработку в сообщество Apache
Software Foundation, выпустившее на его основе набор классов и интерфей- сов Apache SOAP (http://xml.apache.org/SOAP/). Этот продукт входил в со- став сервера приложений IBM WebSphere и до сих пор входит в состав мно- гих серверов приложений.
4 748

98 Разработка Web-служб средствами Java
Сообщество Apache, с появлением сообщений о протоколе ХР, а затем о про- токоле XMLP, кроме сервера Apache SOAP, стало выпускать средство реализа- ции протокола XMLP под названием Axis
В на- звании звучит ирония по поводу переименований исходного протокола XMLP,
но оно расшифровывается как Apache extensible Interaction System. Его иногда называют Apache SOAP 3, следующей версией Apache SOAP. К моменту вы- пуска Axis протокол XMLP еще не был окончательно разработан, и Axis надо считать самостоятельным продуктом, реализующим некоторое расширение протокола SOAP. Axis входит в состав сервера приложений IBM WebSphere
Application Server и многих других серверов приложений.
Для создания SOAP-серверов и клиентов фирма IBM выпускает отдель- ный набор инструментальных средств разработчика Web-служб под на- званием WSTK (Web Services Toolkit) (http://www.alphaworks.ibm.com/
основанный на Axis. Конечно, для разработки
Web-служб можно воспользоваться и основным средством разработчика
IBM WebSphere Studio
Фирма Sun Microsystems выпускает пакет интерфейсов и классов названный SAAJ (SOAP with Attachments API for Java) и описанный спецификацией SAAJ. Интерфейсы и классы, входящие в этот пакет, помогают сформировать SOAP-послания и реализовать синхронный обмен ими. Асинхронный обмен посланиями осуществляется с помощью дополнительных интерфейсов и классов, входящих в пакет названный JAXM (Java API for XML Messaging). Этот пакет использует для пересылки SOAP-посланий систему обмена сообще- ниями JMS (Java Message Service).
Классы, входящие В пакеты javax.xmi. soap И
вуют в документном стиле SOAP. Они просто записывают и отправляют по- слание с любым заголовком и телом. Процедурный стиль посланий SOAP
реализован фирмой Sun в пакете и его подпакетах. Этот на- бор пакетов назван JAX-RPC (Java API for
В нем используется механизм обращения к методам удаленных объектов a SOAP применя- ется как транспортный протокол вместо "родного" для RMI протокола
JRMP (Java Remote Method Protocol) или протокола
ПОР (Internet
Protocol).
Все эти пакеты фирмы Sun входят в набор инструментальных средств J2EE
(http://java.sun.com/j2ee/) и в сервер приложений Sun ONE Application
Server
Кроме того, выпус- кается отдельный набор средств создания Web-служб WSDP (Web Services
Developer Pack) (http://java.sun.com/webservices/webservicepack.html). Для разработки Web-служб можно воспользоваться и универсальным средством разработки Sun ONE Studio (http://wwws.sun.com/software/sundev/jde/).

Глава 2. Архитектура Web Services
Корпорация Microsoft — пионер создания SOAP — выпускает собственный набор средств реализации протокола SOAP под названием Microsoft SOAP
Toolkit и включает его в свой Web-сервер IIS как или как ASP-сервер. Конечно, для разработки Web-служб можно пользоваться и Microsoft Visual Studio
Корпорация Oracle (http://www.oracle.com/) использует Apache SOAP, а так- же собственную разработку, входящую в состав
Containers for J2EE), и включает их в сервер приложений
Application Server.
Для разработки Web-служб Oracle предлагает свой продукт JDeveloper.
Фирма Borland Software Corporation использует Axis и Apache SOAP в со- ставе своего сервера приложений BES (Borland Enterprise Server)
(http://www.borland.com/besappserver/). Для разработки Web-служб фирма
Borland предлагает использовать JBuilder с добавлением пакета Borland Web Services Kit.
Фирма
(The Mind Electric) выпускает средство разработчика Web- служб GLUE (http://www.themindelectric.com/glue/). Его можно встраивать в серверы приложений или применять как отдельный продукт.
Есть еще масса средств реализации протокола SOAP, которые невозможно перечислить хотя бы потому, что каждый день появляются все новые и но- вые продукты.
Создание простейшей Java Web-службы
Продолжим рассмотрение примера метеослужбы и опишем ее классом Java.
Назовем этот класс
Наша метеослужба предоставляет только одну Web-услугу — прогноз погоды на завтра. Пусть эта услуга предоставля- ется методом getweatherForecast о.
будем изощряться в сложных алго- ритмах прогнозирования погоды, а просто дадим наиболее вероятный для
России прогноз.
В листинге 2.1 приведено описание нашей Web-службы.
- Листинг 2.1. Класс, описывающий простейшую Web-службу
public class public String location);
return location + ": пойдет дождь или снег";

Разработка Web-служб средствами Java
Воспользуемся Axis для реализации нашей Web-службы. Для этого запишем исходный текст класса в файл
(расширение имени файла означает "Java Web Service"), а файл занесем в каталог axis нашего сервера приложений, использующего Axis. Каталог axis дол- жен быть вложен в каталог сервера приложений.
Все, Web-служба создана и готова предоставить свои услуги любому клиен- ту. Не нужна ни компиляция, ни установка класса в Web- контейнер. Получив SOAP-послание, обращающееся к Web-службе прямо через файл MeteoService.jws, сервер приложений, увидев расширение имени файла обратится к Axis, точнее к сервлету
С этого серв- лета Axis начинает работу на сервере.
В листинге 2.2 приведен клиент метеослужбы, написанный просто как Java- приложение, использующее Axis.
Листинг 2.2. Клиент метеослужбы, написанный с помощью Axis
import import import import java.net.*;
public class public s t a t i c void args) throws Exception;
if
!= 1){
" +
");
}
S e r v i c e s e r v i c e = n e w
C a l l c a l l =
S t r i n g e n d p o i n t =
" h t t p : / / w w w . m e t e o . c o m :
j w s " ;

Глава 2. Архитектура Web Services 101
String r e s u l t =
на завтра: " + r e s u l t ) ;
}
Откомпилируем программу листинга 2.2 на машине клиента:
$ javac и запустим программу-клиент:
$
MeteoServiceClient
На консоли увидим прогноз погоды на завтра.
Как видите, для получения услуги надо только знать адрес URL Web- службы, размещенной в файле MeteoService.jws, и передать ей имя населен- ного пункта. Все остальное Axis берет на себя.
Посмотрим подробнее на то, что делает Axis в листинге 2.2. Вначале созда- ется объект класса service. Этот объект установит связь с Web-службой. Он предоставляет экземпляр класса в котором формируется HTTP- запрос, содержащий SOAP-послание. Для создания запроса в объект класса заносится адрес Web-службы и имя Web-услуги "getWeatherForecast".
После того как запрос сформирован, Axis обращается к Web-услуге методом invoke (). Аргумент этого метода — массив объектов — содержит аргументы предоставляемой Web-услуги.
Запрос направляется по сети серверу приложений, работающему по указан- ному в запросе адресу URL. Сервер приложений запускает сервлет играющий роль диспетчера и контейнера, в котором работают
Web-службы. Он разбирает SOAP-послание, пришедшее в запросе, отыски- вает указанный в послании файл MeteoService.jws и компилирует его содер- жимое. Затем Axis загружает class и обращается к методу getWeatherForecast передав ему аргумент. После выполнения этого ме- тода Axis формирует SOAP-ответ и отправляет его клиенту.
Клиентская часть Axis разбирает полученный ответ и передает его как ре- зультат выполнения метода invoke ().
Программу-клиент Web-службы, показанную в листинге 2.2, можно встро- ить в клиентское приложение или использовать отдельно, снабдив ее гра- фическим интерфейсом.

102 Разработка Web-служб средствами Java
Запрос, сформированный Axis и посылаемый клиентом нашей метеослужбы на сервер, без HTTP-заголовка выглядит буквально так, как показано в лис- тинге 2.3.
Листинг 2.3. SOAP-послание клиента метеослужбы
version="1.0"
Как видите, нигде в запросе нет упоминания о платформе, на которой ра- ботает клиент, и тем более не сказано, что клиентом должно быть Java- приложение. Поэтому клиентом Axis может быть любая программа, способ- ная составить такой запрос и разобрать ответ сервера. Ее можно написать на любом языке. Поскольку книга посвящена созданию Web Services с по- мощью Java, приведем в листинге 2.4 клиент, написанный только стандарт- ными сетевыми средствами Java, без использования Axis.
Листинг 2.4. Клиент метеослужбы
import java.net.*;
import j public class MeteoServiceClient2{
public static void args)

Глава 2. Архитектура Web Services 103
if
!= 1){
" +
");
String message =
" +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
;
try{
byte[] data =
URL
=
new
URLConnection
=
;
;

Разработка Web-служб средствами Java
""+
());
dos =
new
0,
br = new new
String res = null;
while ((res
!= null)
e){
client: " + e);
Ответ, полученный клиентом в листинге 2.4, приведен в листинге 2.5.
Листинг 2.5. SOAP-ответ метеослужбы

Глава 2. Архитектура Web Services

Конечно, клиент, показанный в листинге 2.4, должен еще разобрать ответ,
присланный сервером в виде SOAP-послания листинга 2.5, выделив из него результат — прогноз погоды. Для этого придется применить один из описанных в главе 1. Не будем сейчас заниматься этим.
Внимательный читатель заметил, что та часть Axis на сервере, которая при- нимает SOAP-послания, оформлена в виде сервлета
Действи- тельно, в технологии Java Web-службы реализуются сервлетами и страница- ми JSP, которые,
обращаются к компонентам EJB типа SLSB
(Stateless Session Beam) или типа MDB (MessageDriven Bean). Нашу простую метеослужбу можно реализовать без Axis одним сервлетом, например, та- ким, какой показан в листинге 2.6.
Листинг 2.6. Сервлет. реализующий метеослужбу
import import java.util.*;
import javax.servlet.http.*;
public class extends public String location))
return location + ": пойдет дождь или снег";
public void req,

Разработка Web-служб средствами Java
HttpServletResponse resp){
try{
;
br =
String message = "", buf = "", location = "";
while ((buf =
null)
message += buf;
// Анализ SOAP-послания message SAX-парсером и
// выделение аргумента location.
resp.setContentType("text/xml;
String response =
" +
+
+
+
+
+
+
+
+
+
+
"" +
"" +
+
PrintWriter pw =

Глава 2. Архитектура Web Services 107
pw.
() ;
pw. close () ;
e){
Вся наша простейшая метеослужба уместилась в одном методе
(). В реальной ситуации ее лучше вынести в один или несколько компонентов EJB.
Итак, построить любую Java Web-службу можно стандартными свободно доступными средствами Java, имеющимися в пакетах инструментальных средств J2SDK SE, J2SDK ЕЕ и WSDP. Их можно свободно загрузить с сай- та http://java.sun.com/.
Описание Web-службы
После создания Web-службы и размещения ее на сервере в виде сервлета,
страницы JSP, JWS-файла или другого объекта, следует подумать, как об этой службе узнают клиенты. На каждом сервере необходимо создать спи- сок имеющихся на нем Web-служб и услуг, предоставляемых ими. Но для этого надо точно знать, какие именно услуги оказывает каждая Web-служба,
и описать их.
Средства для такого описания есть во многих языках — это интерфейсы
Java, язык на котором описываются объекты заголовочные header-файлы языка С. Для описания Web-служб нужен язык, не зависящий от платформы, операционной системы, системы программирования. По- этому для точного описания Web-услуг консорциумом W3C создан специ- альный язык
Этот язык — еще одна реализация
Его специфи- кация опубликована на странице http://www.w3.org/TR/wsdl.
Корневым элементом документа
— описания WSDL — служит эле- мент i n i t i o n s x В этом элементе атрибутом name можно дать имя опи- санию. Кроме того, это удобное место для введения используемых в описа- нии пространств имен. Описания WSDL активно используют различные пространства имен. Кроме собственных имен WSDL часто использует язык описания схем XSD (см. главу Т) и язык протокола SOAP. Пространство имен WSDL часто описывается как пространство имен по умолчанию, тогда целевое пространство имен получает префикс, обычно tns (Target

Разработка Web-служб средствами Java
В корневой элемент вкладываются пять основных элементов.
— определяет сложные типы XSD, используемые Web-службой.
Этот элемент не нужен, если служба применяет только простые типы XSD.

— описывает каждое SOAP-послание: запрос, ответ, пере- сылку документов. В этот элемент вкладываются элементы
,
описывающие имя и тип каждого аргумента запроса или возвращаемо- го значения.

— описывает Web-службу, называемую здесь пунктом назна-
чения (endpoint) или портом (port) прибытия послания. Она описывается как набор услуг, называемых здесь операциями. Операции описываются вложенными элементами , описывающими каждую услугу:
отправку запроса — получение ответа или, наоборот, получение запро- са — отправку ответа. Получение и отправка, в свою очередь, описыва- ются вложенными элементами и а сообщение об ошибке — элементом

— описывает конкретный формат пересылки: протоколы
SOAP, HTTP, тип содержимого HTML, XML или другой по- слания. У каждой Web-службы может быть несколько таких элементов,
по одному для каждого способа пересылки.
— указывает местоположение Web-службы как один или не- сколько портов. Каждый порт описывается вложенным элементом
, содержащим адрес Web-службы, заданный по правилам выбран- ного в элементе способа пересылки.
Кроме этих пяти основных элементов есть еще два дополнительных элемента.

— включает файл с XSD-схемой описания WSDL или другой
WSDL-файл.

— комментарий. Его можно включить в любой элемент описания WSDL.
Можно сказать, что элементы , и показыва- ют, ЧТО есть в описываемой Web-службе, какие услуги она предоставляет,
как организованы услуги, какие типы данных у этих услуг.
Элементы объясняют, КАК реализована Web-служба, каков про- токол передачи посланий: HTTP, SMTP или что-то еще, задает технические характеристики передачи данных.
Наконец,
показывают, ГДЕ находится Web-служба,
связывая описание с конкретными адресами Web-службы.
В листинге 2.6 показано, как будет выглядеть WSDL-описание нашей ме- теослужбы.

Глава 2. Архитектура Web Services 109
Листинг 2.6. Описание WSDL метеослужбы
version="1.0"
xmlns="http://www.w3.org/2002/07/wsdl"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
/>

/>

/>
message="tns:ForecastResponse" />

/>
/>


Разработка Web-служб средствами Java
/>

"http://schemas.xmlsoap.org/soap/encoding/"
/>


File for MeteoService
/>


В листинге 2.6 мы дали в элементе описанию имя "MeteoService" и определили префиксы всех нужных нам пространств имен. Далее мы описали запрос и ответ в двух элементах . Мы
ИМ имена
И "ForecastResponse". В запросе ОДИН
аргумент типа xsd: string. Этот тип определен в языке XSD. Мы дали ар- гументу имя location, совпадающее с именем аргумента метода getweatherForecast
Значению, возвращаемому методом, мы дали имя forecast, его ТИП
xsd: string.
Имена "ForecastRequest" И "ForecastResponse" ИСПОЛЬЗОВаны В СЛедуЮ- щем элементе для указания входных и выходных параметров
Web-услуги. В нем один элемент . Это означает, что Web- служба "Meteo_PortType" предоставляет одну услугу, имя которой

Глава 2. Архитектура Web Services 111
совпадает с именем метода, выполняющего эту услу- гу. В элементе указаны входной и выходной
параметры услуги.
Затем, элементом мы указываем один способ пересылки посла- ний, а именно, как SOAP-посланий в процедурном стиле, пересылаемых по протоколу HTTP, на что указывает элемент
/>
Документный стиль SOAP отмечается значением "document" атрибута style.
Далее повторяется описание операции, но уже в терминах SOAP.
Наконец, элементом указываем адрес, по которому расположена
Web-служба.
Мы рассмотрим подробно спецификацию WSDL в главе 4, а пока дадим обзор инструментальных средств для создания WSDL-описаний.
Инструменты создания описаний WSDL
Описание WSDL написано в листинге 2.6 вручную. Однако строгость опи- сания позволяет автоматизировать этот процесс. Многие инструментальные средства создания Web-служб содержат утилиты, которые автоматически создают WSDL-файлы, описывающие готовые Web-службы. Например, уже упоминавшееся средство создания Web-служб Apache Axis содержит в составе класс создающий WSDL-файл по классу или интерфейсу
Java. Пакет IBM WSTK, в состав которого входит Axis, содержит утилиту создающую объект этого класса и работающую из командной строки. Достаточно набрать в командной строке
$
и будет создан файл MeteoService.wsdl, содержащий по одному элементу для каждого открытого метода класса, указанного в командной строке.
Интересно, что Axis может выполнить и обратное действие: по имеющемуся
WSDL-файлу класс создаст все классы Java, необходимые для работы Web-службы. В пакете IBM WSTK класс можно вызвать из командной строки утилитой
Например:
$
MeteoService.wsdl
Такие же утилиты есть в составе уже упоминавшегося продукта GLUE фир- мы The Mind Electric.

Разработка Web-служб средствами Java
Пакет Microsoft SOAP Toolkit содержит графическую утилиту вызываемую из стартового меню WSDL Generator, и утилиту командной строки которые создают WSDL-файлы.
Фирма Sun Microsystems готовит к выпуску пакет интерфейсов JWSDL (Java
API for WSDL), преобразующих описание WSDL в классы Java и обратно.
Это позволяет программно создавать, изменять, читать описания WSDL.
Фирма IBM уже реализовала этот пакет в своем продукте WSTK, назвав на- бор интерфейсов и реализующих их классов WSDL4J (WSDL for Java). Этот набор можно использовать в составе WSTK или отдельно, загрузив его с сайта
Самое ценное в описаниях WSDL то, что клиент Web-службы может обра- титься не к ней самой, а к ее WSDL-описанию. В состав GLUE входит ути- лита командной строки invoke, обращающаяся к Web-службе по ее WSDL- описанию. Например, достаточно набрать в командной строке:
$ invoke
— и на консоли появится прогноз
Фирма IBM выпускает пакет классов WSIF (Web Services Invocation
Framework), работающий в Web-контейнере Tomcat под управлением
Apache SOAP. С помощью этого пакета можно, в частности, сделать ту же работу:
$
\
\
Гадюкино
Напомним, что обратная наклонная черта здесь означает продолжение ко- мандной строки на следующую строку текста.
После этого на консоли появляются сообщения WSIF и прогноз погоды.
Регистрация Web-службы
Во всех приведенных выше примерах Web-служба вызывалась по ее адресу,
записанному строкой URI. Это приемлемо для вызова Web-услуг из ко- мандной строки или графического приложения, но неудобно для работы распределенного приложения, поскольку адрес Web-службы может поме- няться и придется сделать замены во всех клиентских приложениях. Для стабильной работы распределенных приложений нужно средство автомати- ческого поиска и связи с Web-службами, подобное реестру RMI, службам именования JNDI или CORBA Naming Service, сетевой информационной службе NIS, применяемой в UNIX. Это особенно важно для слабо связан- ных приложений: ведь основное их достоинство — быстрый поиск "на лету"
необходимых для работы компонентов.

Глава 2. Архитектура Web Services
Создано уже несколько систем поиска Web-служб. Наиболее распростране- ны две системы: универсальная система описания, обнаружения и ции UDDI и электронный бизнес-реестр ebXML Registry (electronic business
XML Registry). Обе системы громоздки и сложны в употреблении. Поэтому фирмы IBM и Microsoft недавно разработали облегченную систему обнару- жения Web-служб, названную
(Web Services Inspection
Language).
Схема взаимодействия клиента Web-службы с ее поставщиком через реестр показана на рис. 2.3.
Рис. 2.3. Взаимодействие клиента Web-службы с ее поставщиком
Рассмотрим последовательно эти три наиболее употребительные службы поиска Web-служб.
Система описания и обнаружения UDDI
Система описания, обнаружения и интеграции UDDI создана фирмами IBM
и Microsoft
Сейчас она развивается группой крупных компаний. На официальном сайте сообщества UDDI
приведен список около трехсот компа- ний-участников проекта. Сообщество выпустило спецификацию UDDI, кото- рую можно получить на том же сайте. Спецификация уже реализована множе- ством продуктов разработки реестра UDDI.
Реестр UDDI (UDDI Business Registry) состоит из множества узлов (nodes),
размещенных в Интернете. Они хранят информацию о Web-службах, дос- тупную на всех узлах, образующих распределенный
Клиент "видит" UDDI-реестр как единое целое, совершенно не ощущая того, что

Разработка Web-служб средствами Java
он размещен на нескольких машинах. Конечно, сами узлы организованы как Web-службы, а реестр UDDI — как слабо связанное распределенное приложение.
Многие крупные компании организовали и содержат свои например, реестр фирмы IBM расположен по адресу адрес реестра компании
Hewlett Packard реестр корпорации
Microsoft находится на сайте
Эти
UDDI-реестры связаны между собой и постоянно обмениваются информа- цией. Кроме того, это открытые (public) реестры. Любой желающий может зарегистрировать в них свою Web-службу или отыскать нужную Web-услугу.
Фирмы могут организовать и закрытые частные (private) реестры, доступные только зарегистрированным участникам. Список можно посмотреть на сайте проекта UDDI.
Реестр UDDI разбивает хранящуюся в нем информацию на несколько групп.
Четыре основные группы состоят из следующих элементов.
• Бизнес-информация — XML-элемент — описание фирмы-поставщика Web-услуг: ее ключ
(Unique Universal
Identifier), уникальный в пределах реестра и описанный атрибутом businessKey, название фирмы — вложенный элемент , краткое описание сферы ее деятельности, типы предоставляемых услуг, контакт- ная информация, ссылки URL. Эта информация предназначена для всех,
кто хочет воспользоваться услугами фирмы.
• Бизнес-услуги — элемент вложенный в элемент
- список услуг, оказываемых фирмой. Каждая услуга описывается вложенным элементом
В описание вхо- дит ключ UUID каждой услуги, описанный атрибутом serviceKey, имя услуги — вложенный элемент ее краткое описание и ссылки на подробную информацию. Услуги могут быть любыми, не обязательно
Web-услугами.
• Указатели на услуги — элемент вложенный в эле- мент - способы получения каждой услуги. Они мо- гут быть прямыми, например, URL-адрес Web-службы, или косвенными,
например, описание WSDL или IDL. Каждый способ описывается эле- ментом
Его атрибут bindingKey определяет уни- кальный ключ UUID указателя. Элемент содержит ссылку на соответствующий элемент
• Модель услуги — элемент
(technical Model) — подробное фор- мальное описание каждой услуги. Оно используется программным обес- печением узла. Обычно это отдельный документ XML.

Глава 2. Архитектура Web Services 1J5_
В реестре есть еще несколько дополнительных элементов.
• Утверждение — элемент
— описание установлен- ных ранее отношений между фирмами (утверждение peer-peer) или фир- мой и ее подразделениями (утверждение parent-child). Фирма утвержда-
ет, что она тесно связана с перечисляемыми фирмами или что это — ее подразделения. Третий вид утверждения — identity — отношение между одинаковыми фирмами — это фактически псевдоним. Отношение вхо- дит в силу, когда его утвердят оба участника. Это отдельный документ,
использующий элементы обеих фирм.
• Подписка — элемент — список фирм и сведений, кото- рые надо послать перечисленным фирмам при каких-либо изменениях в деятельности фирмы.
Итак, схема одного из документов XML, хранящихся в такова:
UUID">

< ! — Описание указателя -->
< ! — Описания других указателей —>

< ! — Описания других услуг —>
Клиент обращается к для того, чтобы зарегистрировать свою
Web-службу, изменить ее, или для того, чтобы отыскать нужную Web- услугу. Реестр предоставляет необходимый для этого интерфейс. Регистра-

Разработка Web-служб средствами Java
ция и последующие изменения выполняются методами поиск
Web-службы и получение услуги — методами ind_xxx () и get_xxx {). Все эти методы описаны в спецификации UDDI.
Есть уже много реализаций интерфейса UDDI на различных языках. В тех- нологии Java наиболее популярен пакет классов UDDI4J (UDDI for Java),
разработанный фирмой IBM (http://www.uddi4j.org/). Классы, входящие в этот пакет, обеспечивают выполнение всех действий клиента в UDDI- реестре.
реализован в пакете UDDI4J классом
Точнее говоря, этот класс служит посредником (proxy), обращающимся к соответ- ствующим методам интерфейса UDDI. Методы этого класса возвращают объекты классов, предоставляющих дополнительную информацию. Мы рас- смотрим подробно пакет UDDI4J в главе 5.
В листинге 2.7 показано, как можно зарегистрировать нашу метеослужбу в том или ином а потом найти ее.
Листинг 2.7. Регистрация метеослужбы в UDDI-реестре !
import import import import import import import public class SaveMeteoService{
public static void main (String[] args){
app = new proxy = new try{
// Выбираем
// Тестовый реестр IBM
+

Глава 2. Архитектура Web Services 117
"uddi/testregistry/inquiryapi");
+
// Официальный реестр IBM
//
+
// "uddi/inquiryapi");
//
+
//
// Тестовый реестр Microsoft
//
// "http://test.uddi.microsoft.com/inquire");
//
//
// Официальный реестр Microsoft
//
//
// Реестр Hewlett Packard
//
//
// Отладочный локальный реестр из пакета
//
//
//
//
// Заходим на сайт
AuthToken token =
"userid", "password");
"Регистрационный код: " +
Meteo Service");

Разработка Web-служб средствами Java
Vector entities = new
// Создаем элемент .
// Первый аргумент —
— пока неизвестен.
BusinessEntity be = new
// Регистрируем Web-службу
BusinessDetail
=
entities);
// Для проверки получаем UUID.
Vector businessEntities =
BusinessEntity returnedBusinessEntity =
UUID: " +
Web-служб:");
// Получаем список зарегистрированных
// Web-служб, чьи имена начинаются с буквы "М".
Ы =
null, 0 ) ;
Vector businessInfoVector =
for (int i = 0; i <
i++){
=
e){

Глава 2. Архитектура Web Services
DispositionReport dr =
if (dr != null){
faultCode:" +
+
"\n operator:" +
+
"\n generic:" +
+
"\n errno:" +
+
"\n errCode:" +
+
"\n
+
}
e){
proxy: " + e ) ;
Система взаимодействия фирм ebXML
Электронный бизнес-реестр ebXML первоначально был создан двумя орга- низациями: центром международной торговли и электронного бизнеса ООН
UN/CEFACT (United Nations Centre for Trade Facilitation and Electronic
Business)
и общественной организацией стандартизации структурной информации OASIS (Organization for the
Advancement of Structured Information Standards)
Затем в разработку проекта ebXML включились другие фирмы, сейчас их уже несколько сотен, в их числе IBM и Sun. Всю информацию о сообщест- ве ebXML можно получить на сайте проекта
Цель проекта ebXML широка — обеспечить взаимодействие между деловы- ми партнерами по Интернету, обычно обозначаемое сокращением В2В
(Business to Business). Взаимодействие может быть любым, Web-службы —
это только частный случай, причем не самый важный. Поэтому во множе- стве спецификаций проекта ebXML (http://www.ebxml/org/specs/) описыва- ется только каркас построения реестра. Спецификация ebXML делает это очень расплывчато, в самых общих терминах.
С точки зрения ebXML есть две фирмы, называемые сторонами (parties),
осуществляющие деловое сотрудничество (Business Collaboration). В реестре

120 Разработка Web-служб средствами Java
хранится информация о каждой стороне и их сотрудничестве, кото- рая разделена на две части: заявление о сотрудничестве
(Collaboration
Protocol Profile) и соглашение о сотрудничестве
(Collaboration Protocol
Agreement).
Заявление о сотрудничестве СРР
Заявление о сотрудничестве СРР — это документ XML, содержащий ин- формацию о фирме-стороне, предоставляемых ею услугах, возможных со- глашениях с другими сторонами, способах обмена услугами и получения информации, в том числе о транспортных протоколах. Заявление СРР от- крыто для всех, кто желает сотрудничать с фирмой. Каждая сторона может зарегистрировать в реестре одно заявление СРР, несколько заявлений, или не регистрировать их вообще.
Структура документа содержащего заявление СРР, такова:

< ! — Сведения о фирме-стороне —>
< ! — Описание сообщений —>
< ! — Цифровая подпись (необязательна) —>
(необязателен)

У каждого элемента этого документа есть вложенные элементы, детально описывающие заявление СРР. Мы не будем сейчас углубляться в них.

Глава 2. Архитектура Web Services 121_
Соглашение о сотрудничестве СРА
Соглашение о сотрудничестве СРА — это документ содержащий тех- нические сведения о соглашениях двух сторон. Эти сведения собираются из заявлений СРР двух фирм-сторон, желающих сотрудничать, или составля- ются фирмой, желающей получить услуги.
Схема документа XML, содержащего соглашение СРА, такова:
xmlns:ds =
= "http://www.w3.org/1999/xlink"
документа"
2">
< ! — Состояние документа: proposed, agreed, signed —>

и время вступления в силу и время окончания
< ! — Договоренность о продолжительности переговоров —>
concurrentConversations = "4"/>
< ! — Сведения об одной стороне —>
< ! — Сведения о другой стороне —>
< ! — Структура сообщений —>

Разработка Web-служб
Java
(необязателен)

У элементов этого документа есть вложенные элементы весьма сложной структуры, которые мы не будем сейчас рассматривать.
Вся информация, включая СРР и СРА, заносится в хранилище (repository)
вместе с любой дополнительной информацией.
Во время переговоров и после них стороны обмениваются сообщениями
(messages).
Соглашение достигается так:
1. Сторона А, оказывающая услуги, составляет заявления СРР и регистри- рует СРР в реестре ebXML.
2. Сторона В, желающая получить услуги, отыскивает в реестре подходя- щее заявление СРР стороны А.
3. Сторона В создает свое заявление СРР, затем на основании обоих заяв- лений составляет проект соглашения СРА и посылает его стороне А.
4. Стороны достигают соглашения, обмениваясь сообщениями.
5. После достижения соглашения стороны хранят копии СРА на своих сер- верах и/или в хранилище ebXML.
6. В процессе сотрудничества серверы обеих сторон обмениваются инфор- мацией согласно достигнутому соглашению СРА.
Реализация ebXML
В то время, когда пишутся эти строки, еще нет промышленных Java- реализаций реестра ebXML. Фирма Sun готовит пакет сервлетов и компо- нентов EJB, предварительно названный Sun ebXML Registry/Repository
Implementation. Этот пакет устанавливается в сервер приложений iPlanet
Application Server. В качестве хранилища пакет использует СУБД Oracle.
Познакомиться с этой разработкой фирмы Sun и получить исходные тексты ее компонентов можно по адресу
Другая реализация реестра ebXML готовится в рамках общественного про- екта EBXMIRR (OASIS ebXML Registry Reference Implementation Project).

Глава 2. Архитектура Web Services
Текущее состояние проекта можно посмотреть на сайте
Язык
для поиска Web-служб
Системы UDDI и ebXML решают не только задачу поиска Web-службы, но и задачи их описания, изменения, интеграции. Это усложняет ведение рее- стра и поиск в нем нужной Web-службы. Если же нужно только отыскать данную Web-службу на конкретном сайте, то лучше воспользоваться други- ми средствами поиска.
Одно такое средство поиска — WS-lnspection — создано фирмами IBM и
Microsoft в 2001 году. Одной из целей создания нового средства было пре- дельное упрощение поиска Web-службы на Web-сайте. При помощи WS-
Inspection эта задача решается так: составляется описание Web-службы на специально разработанном языке
(WS-lnspection Language) — еще од- ной
XML. Оно записывается в файл с расширением и зано- сится в определенный каталог сервера приложений. Сервер, получив за- прос, просматривает все файлы с расширением wsil и находит запрошенную
Web-службу.
Описание Web-службы на языке WSIL выполняется всего одним докумен- том XML с корневым элементом , содержащим несколько вложенных элементов.
В корневой элемент вкладывается необязательное краткое описание Web-службы , служащее комментарием, и одно или несколько описаний Web-услуг и/или одна или несколько ссы- лок на описания
В документе обязательно должен присутствовать
ХОТЯ бы ОДИН Элемент
.
В элементе тоже может быть краткое описание Web-услуги
, одно или несколько имен и обязательно одно или несколько описаний , в которых необязательным атрибу- том location задаются документов XML, содержащих описа- ние Web-службы. Описание обычно выполняется на языке WSDL, но может быть сделано и на другом языке. Пространство имен описания задается вторым атрибутом элемента — атрибутом
В элемент можно вложить описание , служащее комментарием, и один произвольный элемент с дополнительным описани- ем. В этом описании может быть адрес Web-службы — в таком случае оно заменит значение атрибута location.
Элемент внешне отличается от элемента тем, что в нем описания , а атрибуты
И location

124 Разработка Web-служб средствами Java
относятся непосредственно к элементу
Эти атрибуты описывают пространство имен и адрес другого или хранилища UDDI.
Вместо атрибута location можно записать вложенный элемент, в котором указать ссылку на другое описание.
Итак, WSIL-описание строится по следующей схеме:
описание

описание
<пате>Произвольное имя услуги
< ! — дополнительное описание —>


URI"
URI">
KpaTKoe
< ! — дополнительное описание —>

Глава 2. Архитектура Web
В листинге 2.8 показано, как просто выглядит нашей ме- теослужбы.
Листинг 2.8. Описание WSIL метеослужбы •
version="1.0"?>

/>


После того как WSDL-описание сделано, его надо записать в файл с име- нем, например,
а файл поместить в определенный ка- талог сервера приложений. Если обратиться к серверу с браузера со стороны клиента, например, так:
то браузер покажет список всех Web-служб, имеющихся на сервере. Специ- фикация предписывает, чтобы в корневом каталоге сайта,
реализующего WS-Inspection, располагался или создавался динамически файл inspection.wsil. Вы можете набрать в браузере, например, адрес фирмы
IBM http://www.ibm.com/inspection.wsil или адрес http://www.xmethods.com/
inspection.wsil и получить список всех Web-служб, зарегистрированных на этом сайте. При этом файла inspection.wsil на сервере нет, он создается ди- намически по запросу клиента.
Разумеется, сервер приложений должен "понимать" WS-Inspection. Для это- го на нем должна быть сделана реализация спецификации WS-Inspection,
например, установлен пакет интерфейсов и классов WSIL4J, входящий в состав IBM
В пакете WSIL4J разработаны Java-интерфейсы WS-Inspection и сделана их реализация классами Java. Основную работу на сервере выполняет сервлет
Он просматривает все файлы с расширением имени и от- правляет их содержимое клиенту.

126 Разработка Web-служб средствами Java
Если у Web-службы нет то сервлет создает его динамически.
У клиента работает класс
Он запрашивает читает полученные от него и выбирает ссылку на описание
WSDL или другое, какое там есть, описание нужной Web-службы. После этого можно обратиться к найденной Web-службе.
В листинге 2.9 приведен пример поиска нашей метеослужбы посредством
WS-lnspection и пакета WSIL4J. Программа просто выводит полученные от сервера описания метеослужбы.
Листинг 2.9. Поиск метеослужбы с помощью WS-lnspection
import
*;
import com.
import import public class public static void args){
if
< 2){
"Usage:
");
try{
proxy = new wsdlDocs =
for (int k = 0; k <
k++)
e){

Глава 2. Архитектура Web Services 127
Пакет JAXR
Итак, уже разработано несколько различных систем регистрации и поиска
Web-служб:
ebXML,
Есть и другие системы, не ука- занные в этой книге. Все эти системы требуют разных методов доступа к реестру и работы с ним. Для каждой системы приходится создавать своего клиента, работающего с реестром по правилам данной системы поиска
Web-служб.
Фирма Sun решила разработать единую методику доступа к реестрам разных типов и создала набор интерфейсов JAXR (Java API for XML Registries).
Этот набор реализован в пакете Sun WSDP. Там же приведен пример кли- ента JAXR. Это графическая утилита просмотра реестров Registry Browser.
Она вызывается из командной строки просто набором имени командного файла
$
В составе WSDP есть и простой тренировочный реестр, реализованный в виде сервлета
Реестр работает в Web-контейнере
Tomcat и хранит информацию в небольшой базе данных Apache
(произносится, как говорят авторы, "Зин-ди-чи", с итальянским акцентом),
тоже входящей в состав WSDP. Для запуска реестра надо запустить Tomcat и стартовать базу данных:
$
$ startup
$ xindice-start
Для проверки работы реестра и для посылки ему сообщений применяется специальная утилита, работающая из командной строки. Для входа в реестр надо набрать следующую командную строку:
registry-server-test
Для работы с реестром прямо через базу данных Xindice в составе WSDP
есть графическая утилита
Она запускается из командной строки:
$ registry-server-test run-indri
Мы рассмотрим подробнее работу с реестром в главе 5, а пока займемся на- бором интерфейсов JAXR.
Поскольку набор JAXR рассчитан на работу с реестрами самых разных ти- пов, он содержит только интерфейсы, которые должен реализовать постав-
щик услуг (service provider) конкретного реестра. Интерфейсы будут по- разному реализованы поставщиком услуг и поставщиком услуг ebXML, но клиент этого не замечает, он просто связывается с поставщиком

128
Разработка Web-служб средствами Java
услуг и пользуется интерфейсами пакета JAXR. Схема обращения клиента к реестру через поставщика услуг показана на рис. 2.4.
JAXR-клиент реестра Web-служб
Поставщик услуг JAXR
Поставщик услуг
UDDI
Поставщик услуг
Реестр ebXML
Рис. 2.4. Обращение к реестру Web-служб
Набор JAXR СОСТОИТ ИЗ
registry И
Интерфейсы первого пакета применяются клиентом для работы с реестром, интерфейсы второго пакета — поставщи- ком услуг для преобразования информации к виду, пригодному для хране- ния в базе данных реестра.
Для связи с поставщиком услуг клиент пользуется интерфейсом
Экземпляр этого класса клиент получает с помощью класса-фабрики
ConnectionFactory. Сначала статическим методом создается объект этого класса, затем методом setProperties о в него заносятся ха- рактеристики реестра, после этого методом создается объект типа connection.
После того связь с поставщиком услуг установлена, методом интерфейса Connection получаем объект типа в котором сосредоточены методы работы с реестром. На- пример,
() МОЖНО ПОЛУЧИТЬ объект содержащий методы
() получения инфор- мации из реестра.
В листинге 2.10 показано, как можно связаться с реестром и получить из него различную информацию с помощью JAXR.
Листинг
Получение информации из реестра с помощью JAXR
import import j import j

Глава 2. Архитектура Web Services 129
import public class public static void main(String[] args){
// Несколько адресов реестров на выбор.
String queryURL =
if
< 1){
JAXRClient ");
}
JAXRClient jq = new
String httpProxyHost
"localhost";
String httpProxyPort = "8080";
Properties props = new queryURL);
httpProxyHost);
httpProxyPort);
Connection connection = null;
try{
ConnectionFactory factory =
5 Зак. 748

Разработка Web-служб средствами Java
connection =
с реестром установлена");
RegistryService rs =
=
Collection findQualifiers = new
Collection
= new
+ args[0] + " % " ) ;
// Поиск фирмы имени.
response =
namePatterns, null, null, null, null);
Collection orgs =
// Сведения о
Iterator
=
while
()){
Organization org = (Organization)
" +
" +
" +
) ;
// Контактная информация
User
=

Глава 2. Архитектура Web Services 131
if
!= null)(
=
" +
Collection phNums =
Iterator phlter =
while
TelephoneNumber
=
телефона: " +
;
}
Collection eAddrs =
Iterator
=
while eAd =
(EmailAddress)
" +
}
}
// Услуги и доступ к
Collection services =
Iterator
=

Разработка Web-служб средствами Java
while
Service svc = (Service)
услуги: " +
услуги: " +
Collection serviceBindings =
Iterator sblter =
while
ServiceBinding sb
;
" +
) ;
}
}
") ;
}
e){
if (connection != n u l l )
t r y {
je){}

Глава 2. Архитектура Web Services
133
Стек протоколов Web Services
Итак, мы описали архитектуру Web-служб и сделали краткий обзор состав- ляющих ее компонентов. Мы увидели, что архитектуру Web-служб составля- ет масса протоколов и спецификаций. Их можно разбить на четыре части,
образующие стек протоколов, в котором каждый верхний уровень опирается на нижний уровень. Основные протоколы этого стека показаны на рис. 2.5.
ebXML,
WSDL,
SOAP,
WS-Security
Обнаружение
Описание
Создание
Транспорт
Рис. 2.5. Стек протоколов Web Services

ГЛАВА 3
Протокол SOAP и Web Services
Как уже говорилось в предыдущей главе, Web-службы обмениваются ин- формацией с клиентами и между собой, посылая сообщения на языке
Теги этой реализации правила оформления документа XML и поря- док обмена документами определены протоколом SOAP. Протокол SOAP
создан в 1998 году командой разработчиков под руководством Дейва Винера
(Dave Winer), работавшей в корпорации Microsoft и фирме Userland. Назва- ние протокола — "Простой протокол доступа к объектам" — отражает первоначальное назначение — обращаться к методам удаленных объектов.
Назначение протокола изменилось, сейчас это протокол всякого взаимодей- ствия Web-служб и компонентов слабо связанных распределенных прило- жений. Он уже не совсем прост, да и об объектах он ничего не говорит.
Многие разработчики предлагают назвать его "Service Oriented Architecture
Protocol", оставив прежнее сокращение. Чтобы прекратить эти попытки,
в спецификации SOAP 1.2 указано, что слово "SOAP" отныне никак не бу- дет расшифровываться.
В конце 1999 года разработка протокола была передана в консорциум W3C
(http://www.w3.org/).
В мае 2000 года консорциум выпустил свою версию SOAP 1.1. Послание,
написанное по протоколу SOAP, оформляется документом XML, активно использующим пространства имен. Имена элементов XML версии
SOAP 1.1 относятся к пространству имен с идентификатором http://schemas.xmlsoap.org/soap/envelope/.
Черновик второй версии SOAP 1.2 был выпущен в 2001
его простран- ство имен называлось в то время http://www.w3.org/2001/06/soap-envelope.
Заметьте, что именно идентификатор пространства имен, а не номер 1.1
или 1.2 определяет версию SOAP. Сервер не станет рассматривать SOAP- послание и вернет сообщение об ошибке если заметит несоответствие пространства имен.

Глава 3. Протокол SOAP и Web
135
В то время как я пишу эти строки, версия SOAP 1.1 остается рабочей. Вер- сия 1.2 никак не может выйти из подготовительной стадии, но уже исполь- зуется, например, в
Apache SOAP 2.3, Apache Axis. Поэтому в этой главе я буду излагать версию 1.2, отмечая ее отличия от версии 1.1.
Спецификация рабочей версии SOAP всегда хранится по адресу
Документы, лежащие по этому адресу, заме- няются новыми при замене рабочей версии.
Черновая версия SOAP постоянно обновляется, при этом меняется идентификатор пространства имен. Новейший вариант черновой версии на время написания книги хранился по адресу а пространство используемых ею имен называлось
Заметьте, что спецификация SOAP 1.2 состоит из двух частей:
и part2. Вторая часть спецификации — приложение — содержит правила записи слож- ных типов данных. У спецификации есть еще одна часть partO — при- меры посланий, составленных по правилам SOAP 1.2.
Структура SOAP-послания
Спецификация определяет SOAP-послание как документ XML, не содер- жащий объявление типа документа и инструкций по обработке. Корневой элемент этого документа XML называется
У элемента могут быть атрибуты определяющие пространства имен,
и другие атрибуты, снабженные префиксами. В корневой элемент вкладыва- ется один необязательный элемент содержащий заголовок посла- ния, и один обязательный элемент , в который записывается содер- жимое послания. Версия 1.1 позволяла после тела записать произ- вольные элементы, их имена обязательно следовало снабжать префиксами.
Версия 1.2 запрещает писать что-либо после элемента . Короче гово- ря, общая структура SOAP-послания такова:




136 Разработка Web-служб средствами Java
< ! — Содержимое послания —>


Элемент
1   2   3   4   5   6   7   8   9   ...   21


написать администратору сайта