ЛАБОРАТОРНА РОБОТА № 14-15
ТЕХНОЛОГІЯ JAX-WS

 

Мета: набути навичок роботи з API JAX-WS (Java API for XML Web Services).

 

Довідка

Сучасні розподілені програмні системи, призначені для комерційного застосування шляхом реалізації бізнес-процесів підприємств, розробляються, як правило, на основі принципів сервіс-орієнтованої архітектури. Відповідно до цих принципів у якості компонентів названих систем фігурують веб-сервіси або сервіси. Варто відзначити, що на поточному етапі розвитку технологій та засобів створення сервісів та систем на їх основі все суттєвіше виокремлюється тенденція до спрощення та автоматизації безпосередньо процесу розробки сервісів. Актуальним та поширеним засобом для цього є технологія JAX-WS, яку також можна розглядати як набір API (Application Programming Interface) та анотацій для створення та використання веб-сервісів в Java [1, 2]. JAX-WS є складовою платформи Java EE, відомої раніше як J2EE. Ця платформа призначена для створення надійних та масштабованих корпоративних програмних систем.

JAX-WS-сервіс по суті є Java-класом, доповненим JAX-WS-анотаціями, призначеними спростити процес створення та використання сервісу. Такий клас, у свою чергу, містить Java-методи, призначення яких – формування результату виклику сервісу клієнтом з використанням останнім відповідного інтерфейсу. JAX-WS-анотації наведено в табл. 3.1.

 

Таблиця 3.1 – Анотації JAX-WS

Анотації

Призначення

@WebService

позначення класу або інтерфейсу Java як сервісу;

@WebMethod

позначення методу, що входить до складу сервісу;

@WebParam

налаштування параметрів методів сервісів;

@WebResult

керування іменами повідомлень, що є результатами роботи методів, помічених як @WebMethod.

 

Для використання анотацій, наведених в табл. 3.1, необхідно імпортувати однойменні класи пакету javax.jws: WebService, WebMethod, WebParam та WebResult. Типовий шаблон інтерфейсу JAX-WS-сервісу наведено в лістингу 3.1.

 

//Лістинг 3.1. Інтерфейс сервісу

package servicepack;

import javax.jws.WebService;

import javax.jws.WebMethod;

@WebService public interface ServiceInterface {

@WebMethod public int method1(String s);

@WebMethod public String method2();}

 

Для пошуку сервісів в Internet та організації їх взаємодії використовують мову опису сервісів WSDL (Web Services Description Language) на основі XML. Для організації доступу до створеного сервісу останній необхідно розмістити (deploy) на сервері додатків (Application Server), прикладами яких, зокрема, є Apache Tomcat, Oracle GlassFish Server, JBoss Application Server. В роботі будемо використовувати сервер Oracle GlassFish за наступних причин:

– є складовим компонентом NetBeans 8.0 IDE;

– містить вбудовані засоби тестування сервісів.

Сервер додатків варто розглядати як програмну платформу (віртуальну машину), що дозволяє здійснювати керування сервісами.

Для надання сервісів клієнту використовується протокол SOAP (Simple Object Access Protocol) на основі XML, що є засобом організації взаємодії інтерфейсу клієнта із окремим сервісом (рис. 3.1).

 

Рис. 3.1. Схема взаємодії клієнта із JAX-WS-сервісом, розміщеним на сервері додатків

 

На рис. 3.1 наведено наступне:

– для реалізації інтерфейсу клієнта може бути використана Servlet- або JSP-технологія (Java Server Pages). Ці технології дозволяють одержувати веб-сторінки із статичним та динамічним контентом;

JAX-WS-сервіс розміщуються на сервері додатків (у нашому випадку – на сервері GlassFish Server 4);

– обмін інформацією між інтерфейсом клієнта та сервісом здійснюється у форматі SOAP-повідомлень. Інтерфейсом клієнта відправляється запит на одержання сервісу (SOAP-request), в якому містяться значення аргументів методу сервісу. Результат виклику методу сервісу відправляється у зворотному напрямі у форматі повідомлення SOAP-response.

Із посиланням на сказане варто зазначити, що наведені в табл. 3.1 анотації можуть бути параметризованими. Наприклад, використання анотації @WebService із атрибутом serviceName – @WebService(serviceName = "someName") – дозволить замінити у WSDL-описі сервісу фактичну назву класу сервісу на псевдонім (alias) – значення атрибуту serviceName. Використання такої (параметризованої) анотації дозволить в окремих випадках зробити процес користування сервісом більш інтуїтивним. Формат анотації @WebService не обмежується лише атрибутом serviceName. Через кому, наприклад, або окремо можна (варто) зазначити атрибут endpointInterface, що дасть змогу створити посилання з окремого класу JAX-WS-сервісу, що містить реалізації методів, на відповідний інтерфейс сервісу. Це означає, що із заданим інтерфейсом сервісу маємо змогу асоціювати різні класи, привласнюючи їм при цьому той самий псевдонім. Наприклад, використання анотації вигляду @WebService(endpointInterface="servicepack.ServiceInterface") перед визначенням класу сервісу здійснюється для посилання на інтерфейс ServiceInterface сервісу, розміщений в пакеті servicepack, згідно якого реалізується відповідний клас.

Псевдоніми можна привласнювати не лише сервісам, а й методам сервісів. Для цього анотацію @WebMethod використовують із аргументом operationName. Наприклад, якщо в інтерфейсі лістингу 3.1 перед прототипом методу method1 використати анотацію @WebMethod(operationName = "foo"), названий метод буде наданий клієнту як метод foo.

Використання анотацій @WebParam та @WebResult із параметром name дозволить створити псевдоніми для аргументів та результату роботи методу відповідно. При цьому анотацію @WebResult слід зазначати безпосередньо перед сигнатурою методу, а анотацію @WebParam – перед аргументом методу. Наприклад, для методу method1 інтерфейсу лістингу 3.1 використання таких анотацій може бути наступним:

 

@WebMethod(operationName = "foo")

@WebResult(name = "outputString")

public int method1(@WebParam(name = "inputString") String s);

 

Значення параметрів name анотацій @WebParam та @WebResult формують назви тегів повідомлень SOAP-request та SOAP-response відповідно.

Таким чином, відокремлення інтерфейсу сервісу від класу-контейнеру методів сервісу є запорукою зручності реконфігурування останнього, а використання розглянутих анотацій при цьому є засобом досягнення названої зручності.

Для інтерфейсу, наведеного в лістингу 3.1, відповідний клас JAX-WS-сервісу можна представити лістингом 3.2.

 

//Лістинг 3.2. Реалізація інтерфейсу ServiceInterface

package servicepack;

import javax.jws.WebService;

import java.util.Random;

@WebService(endpointInterface = "servicepack.ServiceInterface")

public class SimpleService implements ServiceInterface {

@Override

public int method1(String s) {

return Integer.bitCount(Integer.parseInt(s));

}

@Override

public String method2() {

return Integer.toBinaryString(

new Random().nextInt(max));

}

private static final int max = 10;}

 

Наступним кроком є розміщення створеного сервісу на сервері додатків GlassFish Server 4, що входить до складу NetBeans 8.0 IDE. Для цього попередньо слід виконати запуск названого сервера: на вкладці Службы в групі Серверы обрати елемент списку GlassFish Server 4, натиск правою клавішею миші на якому дозволить виконати запуск серверу додатків.

Розміщення JAX-WS-сервісу на сервері додатків виконаємо з використанням спеціального класу із main-методом (лістинг 3.3). Для цього імпортуємо клас javax.xml.ws.Endpoint та використаємо статичний метод цього класу publish(String address, Object implementor), де аргумент address – URI інтерфейсу сервісу із вказаним портом доступу (8080), а аргумент implementor – екземпляр класу сервісу, реалізованого згідно зазначеного у першому аргументі інтерфейсу сервісу.

 

//Лістинг 3.3. Засіб розміщення сервісу на сервері

package servicepack;

import javax.xml.ws.Endpoint;

public class ServicePublisher {

public static void main(String[] args) {

Endpoint.publish("http://localhost:8080/

WebApplication2/ServiceInterface",

new servicepack.SimpleService()); }}

 

У лістингу 3.3 формат URI інтерфейсу наступний: спочатку вказується IP-адреса або доменне ім'я, порт доступу (http://localhost:8080/); потім зазначається назва веб-проекту NetBeans IDE для JAX-WS-сервісів (WebApplication2/); потім – назва інтерфейсу сервісу (ServiceInterface).

У результаті запуску на виконання – F6 – проекту, що містить інтерфейс та класи, наведені в лістингах 3.1 – 3.3 (при умові, що сервер додатків GlassFish Server 4 вже запущено), у веб-браузері за адресою http://localhost:8080/WebApplication2/ з'явиться веб-сторінка із наступним контентом: TODO write content. Така сторінка створюється автоматично при створенні веб-проекту Java: Ctrl+Shift+N > Java Web > Веб-додаток. Наведений контент є опосередкованим свідченням того, що створений сервіс розміщено на сервері додатків. Для доступу до сервісу (перегляду його WSDL-опису у веб-браузері) необхідно модифікувати адресу веб-сторінки наступним рядком, в якому також слід вказати назву класу сервісу, доповнену ключовим словом Service:

 

– http://localhost:8080/WebApplication2/

SimpleServiceService?wsdl

 

Фрагмент результату виконання такого запиту (фрагмент WSDL-опису JAX-WS-сервісу) наведено в лістингу 3.4.

 

//Лістинг 3.4. Фрагмент WSDL-опису сервісу

<definitions targetNamespace="http://servicepack/"

name="SimpleServiceService"> ...

<service name="SimpleServiceService">

<port name="SimpleServicePort"

binding="tns:SimpleServicePortBinding"><soap:address location="http://localhost:8080/WebApplication2/SimpleServiceService"/></port></service></definitions>

 

Аби безпосередньо пересвідчитися, що створений сервіс розміщено на сервері додатків, можна скористатися портом 4848 та командою (адресою) http://localhost:4848/common/index.jsf – для переходу до панелі адміністрування серверу. На цій панелі у групі Deployment слід обрати елемент List Deployed Applications, що дозволяє перейти до панелі керування та перегляду статусу сервісу (рис. 3.2).

 

Рис. 3.2. Панель керування сервісами

 

Для тестування сервісу можна скористатися вбудованими засобами серверу додатків GlassFish Server 4. Для цього у веб-браузері необхідно ввести наступну команду:

 

– http://localhost:8080/WebApplication2/SimpleServiceService?Tester

 

Змістове навантаження цієї команди полягає у використанні ключового слова Tester. Результатом успішної обробки команди буде динамічно згенерована веб-сторінка, що надає засоби тестування кожного із методів сервісу (рис. 3.3).

 

Рис. 3.3. Інтерфейс тестування сервісу

 

На рис. 3.3 у вигляді елементів керування представлено методи сервісу, сигнатури яких визначаються сигнатурами методів інтерфейсу, наведеного в лістингу 3.1. Наприклад, ввівши в якості аргументу методу method1 сервісу значення 7, одержимо результат роботи методу (3 як кількість бітів, встановлених у значення 1) у форматі SOAP-повідомлення (лістинг 3.5).

 

//Лістинг 3.5. SOAP-повідомлення

//SOAP-запит із передачею аргументу

<S:Envelope ... >

<SOAP-ENV:Header/>

<S:Body>

<ns2:method1 xmlns:ns2="http://servicepack/">

<arg0>7</arg0>

</ns2:method1>

</S:Body>

</S:Envelope>

//SOAP-відповідь із результатом роботи методу

<S:Envelope ... >

<SOAP-ENV:Header/>

<S:Body>

<ns2:method1Response xmlns:ns2="http://servicepack/">

<return>3</return>

</ns2:method1Response>

</S:Body>

</S:Envelope>

 

Альтернативним шляхом тестування сервісів є створення інтерфейсу клієнта. При цьому можна виділити дві варіації:

– створення консольного додатку;

– створення веб-додатку на основі Servlet- або JSP-технології.

За умови використання NetBeans 8.0 IDE процес створення інтерфейсу клієнта суттєво спрощується. Він полягає у наступному:

крок 1 - створюється новий проект – Ctrl+Shift+N > (Java > Додаток Java) або (Java Web > Веб-додаток);

крок 2 - слідом за натиском правої клавіші на створеному проекті треба обрати опцію Новий > Клієнт веб-служби… Призначенням такого кроку є одержання WSDL-опису цільового сервісу, згідно якого будуть згенеровані фрагменти коду інтерфейсу клієнта. При цьому можна виділити два шляхи:

– синтез WSDL-опису на основі класу сервісу – обирається опція Проект, де вказується клас проекту сервісу, на основі якого автоматично буде синтезовано WSDL-опис;

– одержання вже синтезованого WSDL-опису сервісу – обирається опція Локальний файл або опція WSDL URL;

крок 3 - у результаті успішного здійснення попереднього кроку у проекті інтерфейсу клієнта (консольного чи веб) буде створено каталог Посилання на веб-служби (рис. 3.4);

 

Рис. 3.4. Структура синтезованого контенту

 

крок 4 - переміщення (шляхом перетягування) елементів дерева ієрархій, наведеного на рис. 3.4, до тіла класу (у контексті консольного додатку), що знаходиться в каталозі Пакети вихідних кодів проекту інтерфейсу клієнта, дозволить згенерувати так звані стаби (заглушки) – методи-засоби виклику методів сервісу, які безпосередньо можна використовувати при створенні інтерфейсу клієнта. Стаб для методу method1() наведено в лістингу 3.6;

 

//Лістинг 3.6. Стаб методу сервісу

private static int method1(java.lang.String arg0) {

servicepack.SimpleServiceService service = new

servicepack.SimpleServiceService();

servicepack.ServiceInterface port =

service.getSimpleServicePort();

return port.method1(arg0);}

 

крок 5 - використання одержаних стабів. Для випадку консольного інтерфейсу це можна здійснити наступним чином:

 

public static void main(String[] args) {

System.out.println(method1(args[0]));}

 

В результаті виконання кроку 5 одержимо той самий результат, що і при користуванні вбудованими засобами серверу додатків GlassFish Server 4.

При створенні веб-інтерфейсу клієнта на основі JSP- або Servlet-технології є певні нюанси.

Для випадку JSP-технології в каталозі Веб-сторінки нового веб-проекту слід створити нову JSP-сторінку – Новий > JSP…, яку можна назвати як index.jsp. В цьому файлі буде автоматично згенеровано контекст, наведений в лістингу 3.7. З названого каталогу слід також видалити однойменну HTML-сторінку index.html.

 

//Лістинг 3.7. Незаповнена JSP-сторінка

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type"

content="text/html; charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<h1>Hello World!</h1>

</body>

</html>

 

Вміст JSP-сторінки, як і у розглянутому випадку створення консольного інтерфейсу, необхідно доповнити аналогічним шляхом – перетягти елемент-представлення потрібного методу з ієрархічної структури (рис. 3.4) до області між тегами <body> та </body> JSP-сторінки. Відповідний стаб матиме вигляд, наведений в лістингу 3.8.

 

//Лістинг 3.8. Додатковий фрагмент коду JSP-сторінки

<% try {

servicepack.SimpleServiceService service = new

servicepack.SimpleServiceService();

servicepack.ServiceInterface port =

service.getSimpleServicePort();

java.lang.String arg0 = "";

int result = port.method1(arg0);

out.println("Result = "+result);

} catch (Exception ex) {}

%>

 

Далі необхідно ініціалізувати змінну java.lang.String arg0 значенням аргументу методу method1 – рядком "7". Результат запуску клієнтського JSP-проекту буде тим самим, що і у випадку консольного додатку, але виводитися він буде у веб-браузері.

Для створення Servlet-інтерфейсу клієнта також необхідно створити веб-проект Java: Ctrl+Shift+N > Java Web > Веб-додаток:

– в каталозі Пакети вихідних кодів слід створити новий пакет із довільною назвою, в якому, в свою чергу, створити Servlet-клас: Новий > Сервлет…;

– до тіла синтезованого Servlet-класу слід перетягти елемент-представлення потрібного методу ієрархічної структури (рис. 3.4). Синтезований при цьому додатковий код сервлету наведено в лістингу 3.9;

 

//Лістинг 3.9. Додатковий контент сервлету

@WebServiceRef(wsdlLocation = "WEB-INF/wsdl/localhost_

8080/WebApplication2/SimpleServiceService.wsdl")

private SimpleServiceService service;

...

private int method1(java.lang.String arg0) {

servicepack.ServiceInterface port =

service.getSimpleServicePort();

return port.method1(arg0);}

 

– коли шаблонний сервлет буде доповнений кодом, подібним до контенту лістингу 3.9, можна переходити до наступного кроку – виклику синтезованого методу-стабу method1 в області між рядками out.println("<body>"); та out.println("</body>"); сервлету. Це можна зробити, наприклад, шляхом додавання наступного рядка:

 

out.println("<h1>Result: " + method1("7") + "</h1>");

 

– запуск одержаного сервлету слід виконувати через опцію Виконати файл (Shift+F6).

 

Порядок виконання роботи

1 Створення JAX-WS-сервісу із кількома методами та розміщення сервісу на сервері додатків GlassFish Server 4.

1.1 Створити новий веб-проект Java: Ctrl+Shift+N > Java Web > Веб-додаток. В проекті створити інтерфейс сервісу, що містить прототипи трьох методів (на прикладі лістингу 3.1). Прототипи задати згідно варіанту.

Варіант 1:

public int method11(String s11);

public String method12(String s12);

public String method13(String s13);

Варіант 2:

public String method21(String s21);

public boolean method22(String s22);

public String method23(String s23);

1.2 Створити клас JAX-WS-сервісу (на прикладі лістингу 3.2), в якому реалізувати методи інтерфейсу згідно варіанту.

Варіант 1:

а) method11 – повертає кількість одиниць у бінарному коді, переданому у вигляді рядка;

б) method12 – заміщує символи 'a' рядка символами '_';

в) method13 – обчислює бінарний код суми десяткових чисел, представлених у вигляді рядка. Наприклад, на основі рядка "123" має бути сформовано рядок "110";

Варіант 2:

а) method21 – повертає рядок символів у зворотній послідовності. Наприклад, на основі рядку "abc" має формуватися рядок "cba";

б) method22 – на основі числової послідовності, представленої у вигляді рядка, повертає булеве значення true, якщо сума двох перших десяткових цифр дорівнює сумі двох останніх десяткових цифр. В іншому випадку метод має повертати значення false. Наприклад, для рядка "13922" результатом роботи метода має бути значення true;

в) method23 – заміщує символьну послідовність "12" у складі вхідного рядка послідовністю "(12)". Наприклад, для рядка "ab12cd" результатом роботи методу має бути рядок "ab(12)cd".

Зауваження: для реалізації методів згідно варіанту можна скористатися Java-методами, наведеними в додатку Б.

1.3 Створити параметризовані unit-тести для реалізованих методів сервісу, що підтверджують правильність роботи останніх, шляхом використання бібліотеки Junit. На основі unit-тестів створити suite-тест, за допомогою якого виконати перевірку методів.

1.4 Створити клас (на прикладі лістингу 3.3), призначення якого – розміщення сервісу із трьома методами, реалізованими згідно варіанту, на сервері додатків GlassFish Server 4.

1.5 Протестувати методи JAX-WS-сервісу, розміщеного на сервері додатків, з використанням вбудованих засобів GlassFish Server 4 та ключового слова Tester. Переконатися, що результати такого тестування співпадають із результатами, одержаними при проведенні suite-тестування.

Зауваження: при формуванні рядку-запиту до веб-браузера назва Java-класу сервісу має бути доповнена рядком Service, тобто, наприклад, для класу SimpleService відповідний рядок-запит матиме наступний вигляд:

 

– http://localhost:8080/projectname/SimpleServiceService?Tester

 

1.6 Переглянути WSDL-опис сервісу, що на сервері додатків.

1.7 Доповнити параметризовану анотацію @WebService, зазначену при визначенні класу сервісу, аргументом serviceName, ініціалізованим значенням псевдоніму сервісу. Заново розмістити сервіс на сервері додатків, після чого знову переглянути WSDL-опис сервісу, але вже з використанням псевдоніму. Рядки WSDL-опису, що при цьому зазнали змін, занести до звіту.

Зауваження: при формуванні рядку-запиту до веб-браузера із використанням псевдоніму сервісу вже не потрібно здійснювати конкатенацію псевдоніму із рядком Service.

1.8 В інтерфейсі класу сервісу для кожного із трьох методів замінити непараметризовані анотації @WebMethod на анотації із параметром operationName. Заново розмістити сервіс на сервері додатків та переглянути WSDL-опис сервісу. Рядки WSDL-опису, що при цьому зазнали змін, занести до звіту.

1.9 В інтерфейсі класу сервісу для кожного із трьох методів застосувати параметризовані анотації @WebParam та @WebResult.

Заново розмістити сервіс на сервері додатків та здійснити тестування методів із використанням ключового слова Tester. Занести до звіту рядки (теги) SOAP-повідомлень SOAP-request та SOAP-response, що зазнали змін у результаті використання зазначених анотацій.

2 Створення інтерфейсу клієнта для одержання останнім результатів роботи методів JAX-WS-сервісу, розміщеного на сервері додатків GlassFish Server 4.

2.1 Створити консольний інтерфейс клієнта, за допомогою якого викликати кожний із трьох методів сервісу.

2.2 Створити веб-інтерфейс клієнта, за допомогою якого викликати кожний із трьох методів сервісу.

Варіант 1. Створити інтерфейс за Servlet-технологією.

Варіант 2. Створити інтерфейс за JSP-технологією.

 

Питання для самостійної перевірки

1. Технологія JAX-WS. Призначення.

2. Анотації @WebService та @WebMethod. Приклад.

3. Анотації @WebParam та @WebResult. Приклад.

4. Схема взаємодії клієнта із JAX-WS-сервісом.

5. Інтерфейс та класи, створені при виконання роботи. Призначення.

6. Призначення серверу додатків.

7. Тестування JAX-WS-сервісу вбудованими засобами серверу додатків GlassFish Server 4. Приклад.

8. Протокол SOAP. Формат SOAP-повідомлень.

9. Послідовність дій при створенні клієнтського веб-інтерфейсу на основі Servlet-технології.

10. Послідовність дій при створенні клієнтського веб-інтерфейсу на основі JSP-технології.

 

Протокол

1. Титульний лист.

2. Мета роботи.

3. Результати виконання завдань 3.2.1.7, 3.2.1.8 та 3.2.1.9 із супутніми коментарями та поясненнями.

4. Відповіді на контрольні питання.

 

Список рекомендованих інформаційних джерел

1. Гонсалвес Э. Изучаем Java EE 7 / Э. Гонсалвес; пер. с англ. Е. Зазноба [и др.]. – СПб.: Питер, 2014. – 640 с.

2. Vohra, D. Java 7 JAX-WS Web Services: A practical, focused mini book for creating Web Services in Java 7 / D. Vohra. – Birmingham-Mumbai.: Packt Publishing, 2012. – 64 p.