Web-сервіси Java, частина 3: Зв’язування даних в Axis2 (исходники), Різне, Програмування, статті

Незважаючи на те, що обмін повідомленнями XML лежить в основі Web-сервісів, більшість додатків Web-сервісів не мають відношення до XML. Замість цього додатка обмінюються бізнес-даними, специфічними для кожного конкретного додатка. В даному випадку XML – це просто формат, який використовується для представлення бізнес-даних, що підтримує інтерфейс Web-сервісу. XML відмінно підходить для цієї мети, оскільки він надає переносних незалежне подання даних, яке може оброблятися різними інструментами. Однак додаткам в кінцевому рахунку припадає перетворювати XML у власні внутрішні структури даних, що використовуються в додатку, і назад.


Зв’язуванням даних називають методики перетворення між XML та структурами даних програми. Можна написати власний код зв’язування дані про програму, але більшість розробників вважають за краще працювати з середовищами зв’язування даних, які виконують перетворення типовим образом, застосовним до широкого спектру додатків. Однією з основних сильних сторін середовища Web-сервісів Apache Axis2 є те, що вона з самого початку розроблялася для роботи з безліччю середовищ зв’язування даних. Ви можете вибрати той підхід до зв’язування даних, який найбільше підходить до ваших потреб, і використовувати цей підхід для обробки перетворень між XML та структурами даних, використовуючи при цьому середу Axis2 (і її розширення) для управління роботою власне Web-сервісу.


У цій статті показано, як використовувати гнучкість Axis2 у виборі підходу до зв’язування даних, на прикладах коду, що реалізує один і той же Web-сервіс з допомогою кожного з трьох підтримуваних підходів. Ви дізнаєтеся, чому один спосіб зв’язування даних може бути найкращим за всі інші.


Посилання на Axis2


З попередньої статті цієї серії ви дізналися про модель документів AXIOM, яку Axis2 використовує для обробки повідомлень XML. AXIOM відрізняється від інших моделей документів тим, що вона підтримує формування моделі не тільки цілком, але і за необхідності. При використанні середовища зв’язування даних для перетворення XML в структури даних програми і навпаки пов’язується з даними XML зазвичай є лише частиною моделі документа AXIOM. Модель не розширюється до повної моделі документа до тих пір, поки це не знадобиться з якої-небудь причини (наприклад, для шифрування або підписування документів за допомогою WS-Security).


Для того щоб відокремити додаток від роботи з AXIOM безпосередньо, Axis2 підтримує генерацію коду зв’язку на основі опису сервісу на мові опису Web-сервісів (Web Services Description Language, WSDL). Сформований код зв’язку виконує перетворення структур даних в XML і назад, використовуючи обрану вами середу зв’язування даних, надаючи вашому додатком прямий доступ до структур даних. Крім того, в Axis2 реалізована обмежена підтримка зворотного процесу – формування опису WSDL з існуючого коду.


Axis2 формує код зв’язку як для клієнтів сервісів, так і для сервіс-провайдерів. Клієнтський код зв’язку – свого роду клас-заглушка, що розширює клас org.apache.axis2.client.Stub Axis2. Код зв’язку постачальника (серверний код) приймає форму скелета реалізації конкретного сервісу, з класом-приймачем повідомлень, в якому реалізований інтерфейс org.apache.axis2.engine.MessageReceiver. Формування коду для клієнта і сервера виконується за допомогою інструменту WSDL2Java. Після цього ми розглянемо фактичний код зв’язку, перейдемо до подробиць використання інструменту WSDL2Java і закінчимо цей розділ коротким оглядом способів використання існуючого коду.


Код зв’язку клієнта


Код заглушки (stub) з клієнтської сторони визначає методи доступу, які буде використовувати код вашого додатку для виклику операцій сервісу. Спочатку ми створюємо екземпляр класу заглушки – або за допомогою конструктора за замовчуванням (якщо кінцева точка вашого сервісу завжди буде такою ж, яка визначена в WSDL, що використовується для формування заглушки), або за допомогою конструктора, що приймає в якості строкового параметра іншу кінцеву точку. Після того як ми створили примірник заглушки, ми можемо за бажанням використовувати методи, визначені базовим класом org.apache.axis2.client.Stub, Для налаштування різних параметрів. Після цього ми можемо викликати методи доступу, що залежать від сервісу, для фактичного виклику операцій.


У лістингу 1 показаний приклад створення заглушки зі зміною кінцевої точки сервісу (в порівнянні з вказаною в WSDL) на порт клієнтської системи (localhost) Tcpmon за замовчуванням (8800). Tcpmon – це дуже популярний інструмент моніторингу обміну повідомленнями Web-сервісу, тому наявність такої можливості в клієнтському коді часто буває дуже корисним. Після створення екземпляра заглушки змінюється значення тайм-ауту, яка призначається за замовчуванням (також корисно при налагодженні коду провайдера, оскільки ви можете перевищити стандартне значення в 20 секунд), і викликається метод сервісу.


Лістинг 1. Приклад коду заглушки з клієнтської сторони





LibraryStub stub = new LibraryStub(“http://localhost:8800/axis2/services/library”);
stub.getServiceClient().getOptions().setTimeoutInMilliseconds(10000000);
Types[] types = stub.getTypes();

У лістингу 1 показаний синхронний виклик методу сервісу, при якому клієнтський потік блокується викликом сервісу і не повертається до завершення виклику і отримання результатів. В Axis2 також підтримуються асинхронні виклики за допомогою інтерфейсу зворотного виклику. У лістингу 2 показаний модифікований код лістингу 1, куди доданий звичайний асинхронний виклик (звичайний в тому сенсі, що код додатку просто чекає завершення операції, а не робить нічого корисного).


Лістинг 2. Асинхронний код клієнтської заглушки





LibraryStub stub = new LibraryStub(“http://localhost:8800/axis2/services/library”);
TypesCallback cb = new TypesCallback();
stub.startgetTypes(cb);
Type[] types;
synchronized (cb) {
while (!cb.m_done) {
try {
cb.wait();
} catch (Exception e) {}
}
types = cb.m_result;
if (types == null) {
throw cb.m_exception;
}
}

private static class TypesCallback extends LibraryCallbackHandler
{
private boolean m_done;
private Types[] m_result;
private Exception m_exception;

public synchronized void receiveResultgetTypes(Type[] resp) {
m_result = resp;
m_done = true;
notify();
}

public synchronized void receiveErrorgetTypes(Exception e) {
m_exception = e;
m_done = true;
notify();
}
}


За з’єднанню HTTP, використаному в Лістингу 2, відповідь зазвичай повертається клієнтові негайно. Асинхронні виклики найбільш корисні при роботі з транспорту, який розділяє потоки запиту і відповіді – наприклад, Java ™ Message Service (JMS) або Simple Mail Transfer Protocol (SMTP) -, оскільки між відправленням запиту й одержанням відповіді можуть бути значні тимчасові затримки. Звичайно ж, сервіси, працюють по HTTP, також можуть мати значні затримки обробки. Для роботи з сервісами HTTP з такими затримками можна використовувати WS-Addressing, який дозволяє відокремити відповіді від запитів, а для обробки цих відповідей використовувати асинхронні виклики.


Крім класу заглушки (і класу обробки зворотного виклику, якщо ви використовуєте підтримку асинхронного обміну даними), формується ще один інтерфейс для вашого клієнтського коду. Інтерфейс визначає методи сервісу, відповідні операціями, що визначаються конструкцією WSDL portType. Цей інтерфейс реалізований в заглушці, яка також додає кілька спеціалізованих методів для внутрішнього використання. Ви можете або працювати з заглушкою безпосередньо, як показано в Лістингу 1 і Лістингу 2, Або просто використовувати цей інтерфейс для перегляду методів, що входять до складу опису сервісу. У кожному разі коли ви викликаєте один з методів сервісу, заглушка обробляє перетворення об’єктів даних запитів в XML, а також повернутого XML в об’єкти даних відповідей за допомогою вибраної вами середовища зв’язування даних.


Якщо ви просто хочете працювати з XML на стороні клієнта, вам не потрібно використовувати сформований клієнтський клас stub зовсім; замість цього ви можете використовувати клас org.apache.axis2.client.ServiceClient. Це означає, що для початку нам потрібно налаштувати сервіс і операцію, після чого викликати метод ServiceClient.createClient() для створення org.apache.axis2.client.OperationClient операції. Для зручності інструмент WSDL2Java (буде описуватися пізніше в цій статті) надає можливість створення класу заглушки, навіть якщо ви працюєте безпосередньо з XML. Сформований клас заглушки виглядає здебільшого так само, як і для прикладів зі зв’язуванням даних, з тим лише винятком, що він працює з елементами AXIOM, а не з об’єктами даних.


Серверний код зв’язку


Серверний код зв’язку для Axis2 являє собою приймач повідомлень, визначений в рамках конфігурації сервісу Axis2. У цьому приймачі повідомлень повинен бути реалізований інтерфейс org.apache.axis2.engine.MessageReceiver. В інтерфейсі визначений єдиний метод void receive(org.apache.axis2.context.MessageContext) . Середа Axis2 викликає цей метод при отриманні повідомлення запиту, після чого цей метод виконує всю обробку запиту (в тому числі і формування відповіді, якщо це необхідно).


Якщо ви працюєте безпосередньо з XML (у вигляді елементів AXIOM), ви можете використовувати один із стандартних класів org.apache.axis2.receivers.RawXML*MessageReceiver для зв’язку сервера (тут * описує тип обміну повідомленнями, який використовується сервісом). В іншому випадку ви використовуєте згенерований клас приймача повідомлень, який виконує узгодження інтерфейсу Axis2, побудованого на базі AXIOM, і коду сервісу, що використовує об’єкти даних. Код сервісу формується у вигляді скелетної реалізації, при якій методи сервісу просто видають сигнал винятку. Для завершення серверної обробки вам потрібно додати в цей скелет власний код.


В Лістингу 3 показаний приклад серверного скелета (формат змінено для зручності читання), де метод getBook() залишено в незмінному вигляді, а метод getTypes() передає запит фактичного класу.


Лістинг 3. Приклад серверного скелета





public class LibrarySkeleton
{
private final LibraryServer m_server;

public LibrarySkeleton() {
m_server = new LibraryServer();
}

/** * Автоматичний створена підпис методу
*
* @param isbn
* @return book value
*/
public com.sosnoski.ws.library.Book getBook(java.lang.String isbn) { / / Заповнити необхідної логікою
throw new java.lang.UnsupportedOperationException(“Please implement ” +
this.getClass().getName() + “#getBook”);
}
/** * Отримання типів книг, що входять в бібліотеку.
*
* @return types
*/
public com.sosnoski.ws.library.Type[] getTypes() {
return m_server.getTypes();
}
}


Витрати додавання коду безпосередньо в цей клас полягають в тому, що при зміні інтерфейсу сервісу вам доведеться згенерувати клас ще раз і знову внести зміни. Цього можна уникнути за допомогою окремого класу, який доповнює сформований кістяк, дозволяючи переписувати методи скелета без зміни сформованого коду. Для цього вам потрібно змінити сгенерированное опис сервісу services.xml. Це робиться просто; досить замінити назву класу скелета на назву класу конкретної реалізації. У всіх розглянутих нижче в цій статті прикладах зв’язування даних використовується підхід з окремим класом реалізації. Ці приклади можна побачити в файлах Ant build.xml в розділі файли для завантаження, де показано, як автоматизувати заміну.


Інструменти Axis2


Axis2 надає розробникам ряд інструментів, що полегшують роботу з середовищем. Найбільш важливими з них є інструменти, які дозволяють формувати код зв’язку Java (описаний в попередньому розділі) з визначення сервісу WSDL і формувати визначення сервісу WSDL на основі існуючого коду Java.


Отримання коду з WSDL


До складу Axis2 входить інструмент WSDL2Java, службовець для формування коду з опису сервісу WSDL. Ви можете використовувати цей інструмент безпосередньо, запускаючи клас org.apache.axis2.wsdl.WSDL2Java з програми Java, або за допомогою завдання Ant, що підключається модуля Maven або модулів Eclipse або IDEA. Недолік такого великого числа варіантів полягає в тому, що більшість альтернатив зазвичай відстають від основного додатка Java у реалізації нових можливостей і виправленні помилок, тому краще всього використовувати безпосередній виклик програми Java (описуваний в цій статті).


В інструменті WSDL2Java реалізовано безліч параметрів командного рядка, і їх число постійно зростає. У документації по Axis2 міститься повний список цих параметрів, тому тут ми розглянемо тільки найбільш важливі з їх числа:



Також в WSDL2Java реалізовано кілька параметрів, специфічних для окремих середовищ зв’язування даних. Ви можете побачити частину з цих параметрів, коли перейдете до прикладів зв’язування даних нижче в цій статті.


Формування WSDL з коду


До складу Axis2 також входить інструмент Java2WSDL, який ви можете використовувати для створення визначення сервісу WSDL на основі існуючого коду сервісу. Однак корисність цього інструменту страждає від безлічі обмежень, в тому числі неможливості роботи з класами колекцій Java і відсутності гнучкості при структурування XML, який формується класами Java. Частково ці обмеження пов’язані з недостатнім інтересом до цієї області внаслідок зміни способів розробки Web-сервісів.


Взагалі кажучи, багато авторитети в області Web-сервісів і SOA не схвалюють розробку Web-сервісів на основі існуючого коду. Вони вважають, що використання коду прив’язує структуру повідомлень XML до певної реалізації, тоді як принцип Web-сервісів полягає в тому, що XML не повинен залежати від реалізації. Звичайно ж, у цієї точки зору є деякі підстави, а й у її противників також достатньо аргументів. Один з них полягає в складності написання визначень сервісів WSDL і схем XML з нуля. І WSDL, і схема є досить складні стандарти, і для ефективного застосування існуючих інструментів для роботи з цими визначеннями потрібно добре знання цих стандартів. Якщо їх використовує розробник, не розбирається в стандартах, що виходять опис WSDL і схеми часто бувають значно більш заплутаними, ніж сформовані з коду. Ще одна проблема носить чисто практичний характер. Часто у розробників є код, який реалізує необхідні функції, що має бути виконаний у вигляді Web-сервісу, і вони бажають використовувати цей код без внесення значних змін. Тому формування WSDL на основі коду, ймовірно, буде в найближчому майбутньому залишатися проблемою.


У якості більш потужної альтернативи Java2WSDL ви можете спробувати використовувати розроблений мною інструмент Jibx2Wsdl. Jibx2Wsdl формує повний комплект визначень, що пов’язують WSDL, схеми і JiBX на основі одного або декількох класів. Він підтримує загальні колекції та перерахування Java 5, зберігаючи при цьому сумісність з більш ранніми версіями віртуальних машин Java (JVM), а також автоматично експортує Javadocs з вихідних файлів Java в якості документації для формованих визначень WSDL і схеми. В Jibx2Wsdl також реалізований розширений механізм настройки, що дозволяє управляти тим, як будуть визначатися сервіси і представлення XML з класів Java, що дозволяє використовувати типізовані дані навіть в колекціях Java версій нижче 5. Незважаючи на те, що Jibx2Wsdl спеціально призначений для спрощення розгортання існуючих класів як Web-сервісів за допомогою середовища зв’язування даних JiBX (також створеної мною), сформовані опису WSDL і схеми не залежать від середовища зв’язування даних. Ви можете використовувати їх з іншими середовищами зв’язування даних Java або навіть з іншими платформами – просто сформуйте все, що потрібно, відкиньте зв’язування JiBX і працюйте з іншим.


Ще однією альтернативою для користувачів Java 5 або більш пізніх версій є анотації Java Architecture for XML Binding (JAXB) 2.0 і Java API for XML Web Services (JAX-WS), які дозволяють розгорнути об’єкти даних і сервісні класи в якості Web-сервісів. Ці анотації не надають такого ж рівня можливостей настройки, якими відрізняється Jibx2Wsdl, але вони дозволяють вам вбудувати інформацію про конфігурацію безпосередньо у вихідний код, що деякі розробники знаходять привабливим. В Axis2 реалізована експериментальна підтримка JAXB 2.0 і JAX-WS починаючи з версії 1.2, і в подальших версіях вона буде поліпшуватися. Крім того, в майбутніх версіях Jibx2Wsdl також може бути реалізована підтримка анотацій JAXB 2.0 і JAX-WS у вигляді додаткових налаштувань. (В наступній статті цієї серії будуть детально розглядатися JAXB 2.0 і JAX-WS, і ми ще раз повернемося до питання формування WSDL з коду.)


Порівняння різних підходів до зв’язування даних


В Axis2 (починаючи з версії 1.2) реалізована повна підтримка трьох варіантів зв’язування даних і готується підтримка ще декількох. У цій статті порівнюються приклади коду, що використовують три повністю підтримувані середовища зв’язування даних і розкриваються деякі сильні і слабкі сторони використання кожної з цих середовищ з Axis2.


Приклад коду, показаний в лістингу 4 (також входить до складу прикладів, які можна завантажити в розділі файли для завантаження), реалізує сервіс бібліотеки, в якій зберігається набір книг, організованих за тематикам. У бібліотеці визначено декілька операцій, в тому числі:



У лістингу 4 представлений фрагмент WSDL для цього сервісу, в якому показані тільки частини, які беруть участь в роботі getBook.


Лістинг 4. Сервіс бібліотеки WSDL





<?xml version=”1.0″ encoding=”UTF-8″?>
<wsdl:definitions targetNamespace=”http://ws.sosnoski.com/library/wsdl”
xmlns:wns=”http://ws.sosnoski.com/library/wsdl”
xmlns:tns=”http://ws.sosnoski.com/library/types”
xmlns:wsdl=”http://schemas.xmlsoap.org/wsdl/”
xmlns:wsdlsoap=”http://schemas.xmlsoap.org/wsdl/soap/”>
<wsdl:types>

<schema elementFormDefault=”qualified”
targetNamespace=”http://ws.sosnoski.com/library/wsdl”
xmlns=”http://www.w3.org/2001/XMLSchema”>

<import namespace=”http://ws.sosnoski.com/library/types”/>

<element name=”getBook”>
<complexType>
<sequence>
<element name=”isbn” type=”string”/>
</sequence>
</complexType>
</element>

<element name=”getBookResponse”>
<complexType>
<sequence>
<element name=”getBookReturn” minOccurs=”0″ type=”tns:BookInformation”/>
</sequence>
</complexType>
</element>

</schema>

<schema elementFormDefault=”qualified”
targetNamespace=”http://ws.sosnoski.com/library/types”
xmlns=”http://www.w3.org/2001/XMLSchema”>

<complexType name=”BookInformation”>
<sequence>
<element name=”author” minOccurs=”0″ maxOccurs=”unbounded” type=”string”/>
<element name=”title” type=”string”/>
</sequence>
<attribute name=”type” use=”required” type=”string”/>
<attribute name=”isbn” use=”required” type=”string”/>
</complexType>

</schema>
</wsdl:types>
<wsdl:message name=”getBookRequest”>
<wsdl:part element=”wns:getBook” name=”parameters”/>
</wsdl:message>
<wsdl:message name=”getBookResponse”>
<wsdl:part element=”wns:getBookResponse” name=”parameters”/>
</wsdl:message>

<wsdl:portType name=”Library”>
<wsdl:operation name=”getBook”>
<wsdl:input message=”wns:getBookRequest” name=”getBookRequest”/>
<wsdl:output message=”wns:getBookResponse” name=”getBookResponse”/>
</wsdl:operation>

</wsdl:portType>
<wsdl:binding name=”LibrarySoapBinding” type=”wns:Library”>
<wsdlsoap:binding style=”document” transport=”http://schemas.xmlsoap.org/soap/http”/>
<wsdl:operation name=”getBook”>

<wsdlsoap:operation soapAction=”urn:getBook”/>

<wsdl:input name=”getBookRequest”>
<wsdlsoap:body use=”literal”/>
</wsdl:input>

<wsdl:output name=”getBookResponse”>
<wsdlsoap:body use=”literal”/>
</wsdl:output>

</wsdl:operation>

</wsdl:binding>

</wsdl:definitions>


Фактична код реалізації сервісу простий, він наповнює примірник бібліотеки жорстко зафіксованим списком книг. Клієнтський код виконує наступну послідовність запитів:


  1. getBook
  2. getTypes
  3. Пара запитівaddBook; Другий з них повертає SOAP Fault в результаті спроби додавання дублюючого ідентифікатора книги
  4. getBooksByType

Деталі реалізації різні в різних прикладах, оскільки в кожному з них використовуються об’єкти даних, відповідні об’єктах, які беруть участь у конкретному зв’язуванні даних. Якщо не вказано інше, весь представлений код сумісний з версіями Axis2 1.1.1 і 1.2. Для версії Axis2 1.3, яка готується до виходу на момент публікації цієї статті, потрібно незначна зміна коду внаслідок зміни назв формованих класів винятків, відповідних збоїв у роботі сервісу. Обидві версії коду доступні для завантаження (див. розділ файли для завантаження).

У цій статті ми розглянемо тільки клієнтський код, хоча завантажити можна (див. розділ файли для завантаження) і клієнтський, і серверний код разом з файлами компіляції Ant для всіх прикладів. Після цього ми порівняємо клієнтський код для трьох середовищ зв’язування даних і розглянемо сильні і слабкі сторони кожного підходу.


Axis2 Data Binding


ADB (Зв’язування даних Axis2) – це розширення Axis2 для зв’язування даних. На відміну від інших середовищ зв’язування даних, код ADB можна використовувати тільки разом з Web-сервісами Axis2. Ця обставина значно обмежує використання ADB, однак воно також дає певні переваги. Оскільки ADB інтегровано з Axis2, код може бути оптимізовано під вимоги Axis2. В якості одного з прикладів можна назвати те, що ADB побудовано на моделі документа AXis Object Model (AXIOM), яка є основою Axis2 (як обговорювалося в попередній статті цієї серії). Крім того, в ADB реалізовані деякі корисні функції, відсутні на даний момент в інших середовищах зв’язування даних, у тому числі автоматична обробка вкладень. В WSDL2Java реалізована повна підтримка формування коду ADB, в тому числі формування класів моделі даних, що відповідають компонентам схеми XML.


Підтримка схем в ADB має деякі обмеження. У поточній версії Axis2 1.2 до цих обмежень належать такі можливості роботи зі схемами, як компонувальники з maxOccurs=”unbounded”, Визначення схеми з attributeFormDefault=”qualified” та інші схожі варіації. Однак підтримка схем в ADB Axis2 1.2 значно краще, ніж у версії Axis2 1.1, і ця підтримка, швидше за все, буде продовжувати розвиватися з кожною новою версією середовища Axis2 до тих пір, поки не будуть підтримуватися всі основні функції схем.


У базовому варіанті формування коду ADB використовується пряма модель, в якій кожному вхідних і вихідних повідомлень, використовуваним в кожній операції, призначається окремий клас. В Лістингу 5 показані найбільш цікаві фрагменти клієнтського коду прикладу формування коду ADB таким чином. У клієнтському коді видно взаємодія з класами, створеними ADB, до яких відносяться класи GetBookDocument і GetBookDocument.GetBook, Що використовуються як параметр при виклику методу getBook(), А також класи GetBookResponseDocument і BookInformation, Що використовуються для отримання результатів цього виклику.


Лістинг 5. Клієнтський код ADB




                 / / Створення клієнтської заглушки
AdbLibraryStub stub = new AdbLibraryStub(target);
/ / Отримання директорії книг
String isbn = “0061020052”;
GetBook gb = new GetBook();
gb.setIsbn(isbn);
GetBookResponse gbr = stub.getBook(gb);
BookInformation book = gbr.getGetBookReturn();
if (book == null) {
System.out.println(“No book found with ISBN “” + isbn + “””);
} else {
System.out.println(“Retrieved “” + book.getTitle() + “””);
}
/ / Отримання списку певних типів
GetTypesResponse gtr = stub.getTypes(new GetTypes());
TypeInformation[] types = gtr.getGetTypesReturn();
System.out.println(“Retrieved ” + types.length + ” types:”);
for (int i = 0; i < types.length; i++) {
System.out.println(” “” + types[i].getName() + “” with ” +
types[i].getCount() + ” books”);
}
/ / Додавання нової книги
String title = “The Dragon Never Sleeps”;
isbn = “0445203498”;
try {
AddBook ab = new AddBook();
ab.setType(“scifi”);
ab.setAuthor(new String[] { “Cook, Glen” });
ab.setIsbn(isbn);
ab.setTitle(title);
stub.addBook(ab);
System.out.println(“Added “” + title + “””);
ab.setTitle(“This Should Not Work”);
stub.addBook(ab);
System.out.println(“Added duplicate book – should not happen!”);
} catch (AddDuplicateFaultException e) {
System.out.println(“Failed adding “” + title +
“” with ISBN “” + isbn + “” – matches existing title “” +
e.getFaultMessage().getBook().getTitle() + “””);
}
/ / Створення екземпляра функції зворотного виклику
CallbackHandler cb = new CallbackHandler();
/ / Асинхронне отримання всіх книг заданого типу
GetBooksByType gbbt = new GetBooksByType();
gbbt.setType(“scifi”);
stub.startgetBooksByType(gbbt, cb);
long start = System.currentTimeMillis();
synchronized (cb) {
while (!cb.m_done) {
try {
cb.wait(100);
} catch (Exception e) {}
}
}
System.out.println(“Asynchronous operation took ” +
(System.currentTimeMillis()-start) + ” millis”);
if (cb.m_response != null) {
BookInformation[] books = cb.m_response.getGetBooksByTypeReturn();


В Лістингу 5 використовується формування коду з параметром WSDL2Java-u, призначеним спеціально для ADB. При використанні цього параметра для кожного класу моделі даних та повідомлення формується окремий вихідний файл Java; якщо ви не використовуєте цей параметр, ADB сформує код таким чином, що всі ці класи будуть статичними внутрішніми класами створюваної заглушки. Працювати з окремими класами значно легше, тому, якщо ви використовуєте ADB, вказуйте параметр-u.


Пряма форма генерування коду призводить до створення великої кількості класів для введення і виведення кожної з операцій (незалежно від параметра-u, який просто організує одні й ті ж класи різним чином). У цих сформованих класах повідомлень часто міститься мало (або навіть взагалі не міститься, як у випадку класу GetTypes) Корисних даних, але вони необхідні для сигнатур сформованих методів. На щастя, є альтернативний спосіб формування коду, який можна застосувати до більшості звичайних сервісів.


Розпакований ADB


Часто Web-сервіси розробляються на основі існуючих інтерфейсів API у вигляді виклику методів, і в цьому випадку може бути дуже корисно вбудувати існуючий API в Web-сервіс. Це легко зробити; операції, визначені для сервісу (формально для portType, якщо бути більш точним), по суті еквівалентні викликом методів з визначення інтерфейсу. Єдине значуще відмінність полягає в тому, що вхідні та вихідні дані сервісу є повідомлення XML, замість вхідних і значень виклику. Тому для того, щоб вбудувати існуючий API в опис Web-сервісу, вам досить визначити, як представляти параметри виклику і повертаються значення у вигляді структури повідомлень XML.


На щастя, Microsoft ® давно вже встановила конвенцію в цій галузі, що дозволяє нам не винаходити велосипед. Ця угода називається wrapped document / literal (упакованим документально-літеральние) і є поданням, використовуваним. NET за умовчанням при оголошенні виклику методу операцією Web-сервісу. По суті “упакований” (wrapped) підхід говорить про те, що кожне вхідне повідомлення є елементом XML, який складається тільки з послідовності дочірніх елементів, а кожне вихідне повідомлення є елементом XML з одним дочірнім елементом. У реалізації Microsoft є ще деякі технічні деталі, які насправді не особливо важливі, якщо вам не потрібна повна сумісність с. NET, але ми їх опустимо; скажемо тільки, що повідомлення, використані в прикладі з бібліотекою (фрагмент представлений в Лістингу 4) Слід до цього підходу.


WSDL2Java підтримує розпакування таких документально-літеральних сервісів в рамках формування коду ADB. При використанні розпакування з відповідним визначенням сервісу WSDL, створена клієнтська заглушка (а також серверний скелет) виходить значно більш простою і зрозумілою. В Лістингу 6 показаний код клієнтського додатка, еквівалентний наведеному в Лістингу 5, Але з переданим WSDL2Java параметром uw для створення розпакованого інтерфейсу. Класи повідомлень, на порядок збільшують складність в Лістингу 5, здебільшого виключаються в Лістингу 6 (за винятком класу GetTypes), І тепер методи сервісу приймають параметри і повертають результати безпосередньо, а не вбудованими в класи повідомлень. В процесі роботи ADB як і раніше створює класи повідомлень і використовує їх в сформованому коді, але, як правило, ви можете ігнорувати ці класи і працювати напряму з даними.


Лістинг 6. Розпакований клієнтський код ADB




                 / / Створення клієнтської заглушки
AdbUnwrapLibraryStub stub = new AdbUnwrapLibraryStub(target);
/ / Отримання книги безпосередньо
String isbn = “0061020052”;
BookInformation book = stub.getBook(isbn);
if (book == null) {
System.out.println(“No book found with ISBN “” + isbn + “””);
} else {
System.out.println(“Retrieved “” + book.getTitle() + “””);
}
/ / Отримання списку певних типів
TypeInformation[] types = stub.getTypes(new GetTypes());
System.out.println(“Retrieved ” + types.length + ” types:”);
for (int i = 0; i < types.length; i++) {
System.out.println(” “” + types[i].getName() + “” with ” +
types[i].getCount() + ” books”);
}
/ / Додавання нової книги
String title = “The Dragon Never Sleeps”;
isbn = “0445203498”;
try {
stub.addBook(“scifi”, isbn, new String[] { “Cook, Glen” }, title);
System.out.println(“Added “” + title + “””);
title = “This Should Not Work”;
stub.addBook(“xml”, isbn, new String[] { “Nobody, Ima” }, title);
System.out.println(“Added duplicate book – should not happen!”);
} catch (AddDuplicateFaultException e) {
System.out.println(“Failed adding “” + title +
“” with ISBN “” + isbn + “” – matches existing title “” +
e.getFaultMessage().getBook().getTitle() + “””);
}
/ / Створення екземпляра функції зворотного виклику
BooksByTypeCallback cb = new BooksByTypeCallback();
/ / Асинхронне отримання всіх книг заданого типу
stub.startgetBooksByType(“scifi”, cb);
long start = System.currentTimeMillis();
synchronized (cb) {
while (!cb.m_done) {
try {
cb.wait(100L);
} catch (Exception e) {}
}
}
System.out.println(“Asynchronous operation took ” +
(System.currentTimeMillis()-start) + ” millis”);
if (cb.m_books != null) {
BookInformation[] books = cb.m_books;







 



Оновлення Axis2 1.3
Коли ця стаття готувалася до друку, була практично готова до виходу версія Axis2 1.3. Проблеми розпакування ADB, описані в цьому розділі, були виправлені, тому якщо ви можете почати працювати з кодом Axis2 1.3, робота з ADB здасться вам більш приємною, ніж з ранніми версіями Axis2.
 
Основна проблема підтримки розпакування в ADB полягає в тому, що вона ще не до кінця стабільна. Код, наведений в Лістингу 6, підходить для роботи з Axis2 1.2 і містить кілька великих удосконалень в порівнянні з кодом, який використовувався для розпакування ADB в Axis2 1.1.1. Однак для інструменту WSDL2Java необхідно, щоб була змінена структура документа WSDL, використовуваного з іншими прикладами, – Потрібно перемістити вбудовану в код схему класів даних в окремий документ схеми. Що ще більш важливо, код, наведений в Лістингу 6, не буде працювати; остання частина коду, що використовує асинхронну передачу даних, видасть помилку виклику класу через помилки в сформованому ADB клієнтському коді заглушки.


До моменту виходу версії, наступної за версією Axis2 1.2, проблеми розпакування ADB повинні бути здебільшого усунені. Однак ADB – це не єдина середу зв’язування даних для Axis2, що підтримує розпакування. В JiBX також реалізована підтримка розпакування, і з часу виходу Axis2 1.1.1 версія JiBX стабільна. Побачити клієнтський код JiBX ви зможете трохи нижче в цій статті, після того, як ми розглянемо інші варіанти зв’язування даних Axis2.



XMLBeans


XMLBeans – це загальна середу обробки XML, до складу якої входить шар зв’язування даних. Вона створювалася як проект BEA Systems, а згодом була передана організації Apache Foundation. XMLBeans була першою формою зв’язування даних, підтримуваної Axis2, і продовжує бути найбільш популярним варіантом роботи з Axis2, особливо зі складними визначеннями схем.


В Лістингу 7 показані найбільш цікаві фрагменти клієнтського коду XMLBeans для нашого прикладу. Так само, як і в базовому коді ADB (без розпакування) для введення і виведення кожної операції створюється окремий клас. Однак XMLBeans відрізняється від ADB тим, що в неї додається клас для документа, який містить клас введення або виведення (наприклад, GetBookDocument на додаток до класу GetBook). Сукупний ефект при використанні XMLBeans в порівнянні з ADB полягає в додаванні рівня створення об’єктів. В Axis2 немає підтримки розпакування XMLBeans, тому й немає способу уникнути цього додаткового рівня об’єктів. В результаті класи, сформовані XMLBeans, виходять більш складними для використання, ніж їх еквіваленти в інших середовищах зв’язування даних.


Listing 7. XMLBeans client code




                 / / Створення клієнтської заглушки
XmlbeansLibraryStub stub = new XmlbeansLibraryStub(target);
/ / Отримання книги безпосередньо
String isbn = “0061020052”;
GetBookDocument gbd = GetBookDocument.Factory.newInstance();
GetBookDocument.GetBook gb = gbd.addNewGetBook();
gb.setIsbn(isbn);
gbd.setGetBook(gb);
GetBookResponseDocument gbrd = stub.getBook(gbd);
BookInformation book = gbrd.getGetBookResponse().getGetBookReturn();
if (book == null) {
System.out.println(“No book found with ISBN “” + isbn + “””);
} else {
System.out.println(“Retrieved “” + book.getTitle() + “””);
}
/ / Отримання списку певних типів
GetTypesDocument gtd = GetTypesDocument.Factory.newInstance();
gtd.addNewGetTypes();
GetTypesResponseDocument gtrd = stub.getTypes(gtd);
TypeInformation[] types =
gtrd.getGetTypesResponse().getGetTypesReturnArray();
System.out.println(“Retrieved ” + types.length + ” types:”);
for (int i = 0; i < types.length; i++) {
System.out.println(” “” + types[i].getName() + “” with ” +
types[i].getCount() + ” books”);
}
/ / Додавання нової книги
String title = “The Dragon Never Sleeps”;
isbn = “0445203498”;
try {
AddBookDocument abd = AddBookDocument.Factory.newInstance();
AddBookDocument.AddBook ab = abd.addNewAddBook();
ab.setAuthorArray(new String[] { “Cook, Glen” });
ab.setIsbn(isbn);
ab.setTitle(title);
ab.setType(“scifi”);
stub.addBook(abd);
System.out.println(“Added “” + title + “””);
title = “This Should Not Work”;
ab.setTitle(title);
stub.addBook(abd);
System.out.println(“Added duplicate book – should not happen!”);
} catch (AddDuplicateFaultException e) {
System.out.println(“Failed adding “” + title +
“” with ISBN “” + isbn + “” – matches existing title “” +
e.getFaultMessage().getAddDuplicate().getBook().getTitle() +
“””);
}
/ / Створення екземпляра функції зворотного виклику
BooksByTypeCallback cb = new BooksByTypeCallback();
/ / Асинхронне отримання всіх книг заданого типу
GetBooksByTypeDocument gbtd =
GetBooksByTypeDocument.Factory.newInstance();
gbtd.addNewGetBooksByType().setType(“scifi”);
stub.startgetBooksByType(gbtd, cb);
long start = System.currentTimeMillis();
synchronized (cb) {
while (!cb.m_done) {
try {
cb.wait(100L);
} catch (Exception e) {}
}
}
System.out.println(“Asynchronous operation took ” +
(System.currentTimeMillis()-start) + ” millis”);
if (cb.m_response != null) {
BookInformation[] books =
cb.m_response.getGetBooksByTypeResponse().getGetBooksByTypeReturnArray();







 



Зміни версії Axis2 1.3
Коли ця стаття готувалася до друку, була практично готова до виходу версія Axis2 1.3. Проблема обробки помилок XMLBeans була виправлена ​​у версії Axis2 1.3. Код прикладу для цієї статті для версії 1.3 можна знайти в розділі Матеріали для завантаження.
 
Клієнтський код, наведений в Лістингу 7, і відповідний серверний код, виконуються без помилок у Axis2 1.1.1, однак через проблеми у формуванні коду обробки помилок для XMLBeans у версії 1.2, відбувається збій в тій точці, де очікується обробка виключення при додаванні дубліката ідентифікатора книги. Ця проблема повинна бути виправлена ​​в наступній версії Axis2.


Хоча в XMLBeans заявлена ​​підтримка схеми XML на 100%, точність цієї заяви залежить від трактування. Вірно, що майже для всіх конструкцій схеми XMLBeans формує набір Java-класів, які можуть бути використані для читання і запису документів, що відповідають схемі. Однак, на відміну від інших середовищ зв’язування даних, описаних в цій статті, XMLBeans за замовчуванням практично нічого не робить для забезпечення дотримання схеми. Наприклад, якщо ви закомментіруете рядок, який встановлює назву додається книги в коді Лістингу 7, XMLBeans буде успішно прочитувати і зберігати документи без обов’язкового елемента , які тому не будуть відповідати схемою. У лістингу 8 показано це зміна коду разом з XML, відправленим на сервер для додавання запиту і XML, який був отриманий з сервера при запиті книг. У разі відповіді на запит в документі міститься елемент <title>, але використовується атрибут <CODE>xsi:nil=”true”</CODE>, Не дозволений схемою, і документ знову оформлений не за правилами.</P><br /> <P><B>Лістинг 8. Невірний документ і код XMLBeans</B><br /> <TABLE class=borderall cellSpacing=0 cellPadding=2 width="100%" bgColor=#d8d8d8><br /> <TBODY><br /> <TR><br /> <TD><PRE><br /> AddBookDocument abd = AddBookDocument.Factory.newInstance();<br /> AddBookDocument.AddBook ab = abd.addNewAddBook();<br /> ab.addAuthor(“Cook, Glen”);<br /> ab.setIsbn(isbn);<br /> ab.setType(“scifi”);<br /> // ab.setTitle(title);<br /> System.out.println(“Validate returned ” + abd.validate());<br /> stub.addBook(abd);<br /> …<br /> <addBook xmlns=”http://ws.sosnoski.com/library/wsdl”><br /> <type>scifi</type><br /> <isbn>0445203498</isbn><br /> <author>Cook, Glen</author><br /> </addBook></p> <p> <getBooksByTypeResponse xmlns=”http://ws.sosnoski.com/library/wsdl”><br /> …<br /> <getBooksByTypeReturn isbn=”0445203498″ type=”scifi”><br /> <author xmlns=”http://ws.sosnoski.com/library/types”>Cook, Glen</author><br /> <title xmlns=”http://ws.sosnoski.com/library/types” xmlns:xsi=”http://www.w3.org/2001<br /> /XMLSchema-instance” xsi:nil=”true”/><br /> </getBooksByTypeReturn><br /> </getBooksByTypeResponse><br /> </PRE></TD></TR></TBODY></TABLE><br /> <P>Це простий приклад опущеного визначення обов’язкового значення. Для більш складних схем інтерфейс API, сформований XMLBeans, може приховувати більш серйозні помилки. В ході недавніх дискусій в списку розсилки XMLBeans розглядався випадок, в якому, щоб сформувати правильний висновок, значення було необхідно додавати в два різних списку в різному порядку. Тому для роботи з XMLBeans розробник повинен знати і схему, і те, як сформований код відповідає схемі, щоб забезпечити формування кодом програми коректних документів XML. Одне з основних переваг середовищ зв’язування даних зазвичай полягає в тому, що такі подробиці схеми ховаються від розробників, і XMLBeans безумовно програє на цьому фронті.</P><br /> <P>Ви можете уникнути проблем обробки та формування не відповідають правилам документів XML при роботі з XMLBeans, викликаючи метод <CODE>validate()</CODE>, Включений в сформовані класи. Якщо ви працюєте з XMLBeans, вам слід як мінімум перевіряти цим методом всі документи на етапах тестування і розробки. Однак перевірка надає значний негативний вплив на продуктивність (а, як ви побачите з наступної статті цієї серії, XMLBeans і так працює досить повільно, навіть без виклику <CODE>validate()</CODE> для кожного документа), тому в робочих програмах слід уникати витрат, пов’язаних з перевіркою. Крім того, перевірка обмежена в плані інформативності результату. Щоб з’ясувати причину провалу перевірки, вам доведеться запустити для помилкового документа стандартний інструмент перевірки схеми.</P><br /> <H4>JiBX</H4><br /> <P>JiBX (також розроблена мною) являє собою середу зв’язування даних, яка головним чином фокусується на роботі з існуючими Java-класами, а не з кодом, сформованим на основі схеми. При використанні JiBX спочатку потрібно створити опис зв’язування, що визначає, як об’єкти Java будуть перетворюватися в XML і назад, після чого скомпілювати це зв’язування за допомогою інструменту, що доповнює файли класу даних новими методами (у вигляді байт-коду), що реалізують перетворення. Після цього інтерактивна середу JiBX використовує ці додані методи для перетворення даних в XML і назад.</P><br /> <P>Підхід JiBX має свої сильні і слабкі сторони. До плюсів можна віднести те, що JIBX дозволяє працювати безпосередньо з існуючими класами у випадках, коли до існуючого коду сервісу додаються нові інтерфейси Web-сервісу. Для цієї мети особливо корисний інструмент Jibx2Wsdl, оскільки він формує все, що потрібно для простого розгортання існуючого коду як сервісу Axis2. Ви можете визначити кілька зв’язування для одного класу, щоб одночасно працювати з різними версіями документів XML, використовуючи одну модель даних. Модифікувавши зв’язування, ви можете навіть зберегти подання XML при зміні класів даних.</P><br /> <P>В Лістингу 9 показані найбільш цікаві фрагменти клієнтського коду JiBX, що використовує класи, відповідні елементам повідомлень. Цей код схожий на його еквівалент для ADB, наведений в <strong>Лістингу 5</strong>, Тому я не буду вдаватися в деталі. Єдине помітне відміну викликано тим, що і класи даних, і класи повідомлень знаходяться під управлінням користувача, і тому при використанні JiBX дуже просто додавати класам допоміжні конструктори (як у випадку з <CODE>AddBookRequest</CODE>) Та інші додаткові методи.</P><br /> <P><B>Лістинг 9. Кліенскій код JIBX</B><br /> <TABLE class=borderall cellSpacing=0 cellPadding=2 width="100%" bgColor=#d8d8d8><br /> <TBODY><br /> <TR><br /> <TD><PRE> / / Створення екземпляра сервера<br /> JibxLibraryStub stub = new JibxLibraryStub(target);<br /> / / Отримання директорії книги<br /> String isbn = “0061020052”;<br /> GetBookResponse bresp = stub.getBook(new GetBookRequest(isbn));<br /> Book book = bresp.getBook();<br /> if (book == null) {<br /> System.out.println(“No book found with ISBN “” + isbn + “””);<br /> } else {<br /> System.out.println(“Retrieved “” + book.getTitle() + “””);<br /> }<br /> isbn = “9999999999”;<br /> bresp = stub.getBook(new GetBookRequest(isbn));<br /> book = bresp.getBook();<br /> if (book == null) {<br /> System.out.println(“No book found with ISBN “” + isbn + “””);<br /> } else {<br /> System.out.println(“Retrieved “” + book.getTitle() + “””);<br /> }<br /> / / Отримання списку певних типів<br /> GetTypesResponse tresp = stub.getTypes(new GetTypesRequest());<br /> Type[] types = tresp.getTypes();<br /> System.out.println(“Retrieved ” + types.length + ” types:”);<br /> for (int i = 0; i < types.length; i++) {<br /> System.out.println(” “” + types[i].getName() + “” with ” +<br /> types[i].getCount() + ” books”);<br /> }<br /> / / Додавання нової книги<br /> String title = “The Dragon Never Sleeps”;<br /> isbn = “0445203498”;<br /> try {<br /> AddBookRequest abr = new AddBookRequest(“scifi”, isbn, title,<br /> new String[] { “Cook, Glen” });<br /> stub.addBook(abr);<br /> System.out.println(“Added “” + title + “””);<br /> title = “This Should Not Work”;<br /> abr = new AddBookRequest(“scifi”, isbn, title,<br /> new String[] { “Nobody, Ima” });<br /> System.out.println(“Added duplicate book – should not happen!”);<br /> } catch (AddDuplicateFaultException e) {<br /> System.out.println(“Failed adding “” + title +<br /> “” with ISBN “” + isbn + “” – matches existing title “” +<br /> e.getFaultMessage().getBook().getTitle() + “””);<br /> }<br /> / / Створення екземпляра зворотного виклику<br /> BooksByTypeCallback cb = new BooksByTypeCallback();<br /> / / Асинхронне отримання всіх книг заданого типу<br /> stub.startgetBooksByType(new GetBooksByTypeRequest(“scifi”), cb);<br /> long start = System.currentTimeMillis();<br /> synchronized (cb) {<br /> while (!cb.m_done) {<br /> try {<br /> cb.wait(100);<br /> } catch (Exception e) {}<br /> }<br /> }<br /> System.out.println(“Asynchronous operation took ” +<br /> (System.currentTimeMillis()-start) + ” millis”);<br /> if (cb.m_response != null) {<br /> Book[] books = cb.m_response.getBooks();<br /> </PRE></TD></TR></TBODY></TABLE><br /> <P>У лістингу 10 показаний еквівалентний код JiBX з розпакуванням. Як і у випадку з кодом ADB з розпакуванням, розпаковану форму викликів сервісу набагато простіше розуміти і використовувати, ніж пряму. Єдина значна різниця між версіями JiBX і ADB полягає в тому, що в разі JiBX вам не потрібно створювати об’єкт, коли значення не передається, як це було для виклику <CODE>getTypes()</CODE> в ADB. Крім того, підтримка розпаковування в JiBX також більш стабільна, ніж у версії ADB, оскільки вона повністю підтримується починаючи з версії Axis2 1.1.1.</P><br /> <P><B>Лістинг 10. Клієнтський код JIBX з розпакуванням</B><br /> <TABLE class=borderall cellSpacing=0 cellPadding=2 width="100%" bgColor=#d8d8d8><br /> <TBODY><br /> <TR><br /> <TD><PRE> / / Створення екземпляра сервера<br /> JibxUnwrapLibraryStub stub = new JibxUnwrapLibraryStub(target);<br /> / / Отримання директорії книги<br /> String isbn = “0061020052”;<br /> Book book = stub.getBook(isbn);<br /> if (book == null) {<br /> System.out.println(“No book found with ISBN “” + isbn + “””);<br /> } else {<br /> System.out.println(“Retrieved “” + book.getTitle() + “””);<br /> }<br /> / / Отримання списку певних типів<br /> Type[] types = stub.getTypes();<br /> System.out.println(“Retrieved ” + types.length + ” types:”);<br /> for (int i = 0; i < types.length; i++) {<br /> System.out.println(” “” + types[i].getName() + “” with ” +<br /> types[i].getCount() + ” books”);<br /> }<br /> / / Додавання нової книги<br /> String title = “The Dragon Never Sleeps”;<br /> isbn = “0445203498”;<br /> try {<br /> stub.addBook(“scifi”, isbn, new String[] { “Cook, Glen” }, title);<br /> System.out.println(“Added “” + title + “””);<br /> title = “This Should Not Work”;<br /> stub.addBook(“xml”, isbn, new String[] { “Nobody, Ima” }, title);<br /> System.out.println(“Added duplicate book – should not happen!”);<br /> } catch (AddDuplicateFaultException e) {<br /> System.out.println(“Failed adding “” + title +<br /> “” with ISBN “” + isbn + “” – matches existing title “” +<br /> e.getFaultMessage().getBook().getTitle() + “””);<br /> }<br /> / / Створення екземпляра зворотного виклику<br /> BooksByTypeCallback cb = new BooksByTypeCallback();<br /> / / Асинхронне отримання всіх книг заданого типу<br /> stub.startgetBooksByType(“scifi”, cb);<br /> long start = System.currentTimeMillis();<br /> synchronized (cb) {<br /> while (!cb.m_done) {<br /> try {<br /> cb.wait(100L);<br /> } catch (Exception e) {}<br /> }<br /> }<br /> System.out.println(“Asynchronous operation took ” +<br /> (System.currentTimeMillis()-start) + ” millis”);<br /> if (cb.m_books != null) {<br /> Book[] books = cb.m_books;<br /> </PRE></TD></TR></TBODY></TABLE><br /> <P>Підтримка розпакування в JiBX також відрізняється від ADB з точки зору використовуваних класів. При використанні розпакування в ADB класи для всіх елементів повідомлень і раніше створюються і використовуються непомітно для користувача. В JiBX при використанні прямої форми, як в <strong>Лістингу 9</strong>;, Необхідно визначити класи для всіх елементів повідомлень; при роботі з розпакованої формою потрібно визначати і включати в визначення зв’язування тільки класи, передані у вигляді значень. У будь-якому випадку перед запуском інструменту Axis2 WSDL2Java необхідно створити визначення зв’язування JiBX і передати його в параметрі командного рядка <CODE>-Ebindingfile</CODE>.</P><br /> <P>Найбільшим недоліком підходу JiBX до зв’язування, щонайменше, щодо Web-сервісів, ймовірно, є те, що на сьогоднішній день в JiBX слабо реалізована підтримка роботи з визначеннями схеми XML. І навіть ця слабка підтримка роботи зі схемою, у вигляді інструменту Xsd2Jibx, не інтегрована в інструмент формування коду Axis2 WSDL2Java. Це означає, що перед запуском WSDL2Java для формування коду зв’язку Axis2 вам потрібно створити визначення зв’язування і класів даних Java. Крок модифікації байт-коду, необхідний в JiBX, також може викликати проблеми в деяких середовищах, оскільки його, загалом випадку, необхідно виконувати під час складання програми, крім того, він призводить до появи коду в класах, які не мають вихідного коду.</P><br /> <P>Зв’язування даних за допомогою JiBX має ряд унікальних переваг, які обговорювалися на початку цього розділу. Щодо використання Axis2 JiBX також надає перевагу над іншими середовищами, яке полягає в тому, що він підтримується разом з виправленнями, які можуть бути додані в Axis2 для виправлення проблем, знайдених після виходу версії. Єдиним способом отримання виправлень в інших середовищах є перехід на щоночі збірку версій Axis2, що часто може викликати інші проблеми. У майбутньому очікується реалізація в JiBX ефективного формування коду і зв’язування на підставі схеми. Коли це буде зроблено, JiBX обіцяє стати відмінною універсальної альтернативою зв’язування даних для Axis2. До цього часу вона швидше підходить для роботи з існуючим кодом Java, де відмінно працює інструмент Jibx2Wsdl.</P><br /> <H3>Резюме</H3><br /> <P>На сьогоднішній день в Axis2 реалізована повна підтримка трьох різних середовищ зв’язування даних:</P><br /> <UL><br /> <LI><B>ADB</B> розроблений спеціально для Axis2 і може бути використаний тільки в середовищі Axis2. Станом на момент виходу версії Axis2 1.3 в ній реалізована хороша підтримка формування коду на підставі схеми – -, Яка продовжує удосконалюватися. У ній також підтримуються зручні розпаковані методи сервісу та автоматична обробка вкладень, що робить її оптимальним вибором при роботі з існуючими WSDL-визначеннями сервісів.<br /> <LI><B>XMLBeans</B> пропонує більш повну підтримку структур моделювання схеми в сформованому коді Java. Однак вона створює більш складну модель для заданої схеми і не підтримує розпакованих методів сервісів, що спрощують інтерфейс. За умовчанням вона не виконує контролю дотримання навіть базових правил структури схеми ні у вхідних, ні у вихідних документах XML, що підвищує ймовірність випадкового створення або прийому на обробку документів XML з помилками.<br /> <LI><B>JiBX</B> – Це єдиний варіант, що підтримує роботу з існуючими Java-класами. Крім того, в ній реалізована відмінна підтримка розпакованих методів сервісу. Однак підтримка JiBX, інтегрована в Axis2, не забезпечує формування коду на підставі схеми, і навіть формування коду, реалізоване окремо в інструменті JiBX, на сьогоднішній день пропонує лише обмежену підтримку схем. </LI></UL><br /> <P>Те, що в Axis2 є можливість вибору середовищ зв’язування даних, чудово, оскільки немає єдиного варіанту, оптимально відповідного всім вимогам. У майбутньому в Axis2 буде також реалізована повна підтримка JAXB 2.0, про який я розповім в рамках цієї серії, у статті про JAX-WS 2.0. Знання сильних і слабких сторін кожної з середовищ може допомогти вам зробити оптимальний вибір, відповідний вашим потребам, і попередить про можливі проблеми до того, як ви зустрінетеся з ними в роботі. У наступній статті цієї серії ви дізнаєтеся про ще один аспект порівняння середовищ зв’язування даних в Axis2: продуктивності.</P></p> <p></p> <div class="ad-top2"> <!-- Top article #956715 --> <script>(function(e){var t="DIV_DA_"+e+"_"+parseInt(Math.random()*1e3); document.write('<div id="'+t+'" class="directadvert-block directadvert-block-'+e+'"></div>'); if("undefined"===typeof loaded_blocks_directadvert){loaded_blocks_directadvert=[]; function n(){var e=loaded_blocks_directadvert.shift(); var t=e.adp_id; var r=e.div; var i=document.createElement("script"); i.type="text/javascript"; i.async=true; i.charset="windows-1251"; i.src="//code.directadvert.ru/data/"+t+".js?async=1&div="+r+"&t="+Math.random(); var s=document.getElementsByTagName("head")[0]||document.getElementsByTagName("body")[0]; s.appendChild(i); var o=setInterval(function(){if(document.getElementById(r).innerHTML&&loaded_blocks_directadvert.length){n(); clearInterval(o)}},50)} setTimeout(n)}loaded_blocks_directadvert.push({adp_id:e,div:t})})(956715)</script> </div> <div style="float:right"> <div class="yashare-auto-init" data-yashareL10n="ua" data-yashareType="icon" data-yashareQuickServices="yaru,vkontakte,facebook,twitter,odnoklassniki,moimir,lj,moikrug,gplus"></div> </div> <h4>Схожі статті:</h4><ul><li><a href="http://easy-code.com.ua/2011/04/chastina-3-kriptografiya/" title="Частина 3 - Криптографія">Частина 3 - Криптографія</a> (0)</li><li><a href="http://easy-code.com.ua/2011/03/peremishhennya-informaci%d1%97-koristuvacha-v-vista/" title="Переміщення інформації користувача в Vista">Переміщення інформації користувача в Vista</a> (0)</li><li><a href="http://easy-code.com.ua/2011/03/pershi-kroki-z-ca-erwin-process-modeler-chastina-6/" title="Перші кроки з CA ERwin Process Modeler. Частина 6">Перші кроки з CA ERwin Process Modeler. Частина 6</a> (0)</li><li><a href="http://easy-code.com.ua/2011/03/i-stvorennya-windows-dodatku-metodami-vizualnogo-programuvannya/" title="I Створення Windows додатку методами візуального програмування">I Створення Windows додатку методами візуального програмування</a> (0)</li><li><a href="http://easy-code.com.ua/2011/02/12-nalashtuvan-windows-vista-dlya-zbilshennya-produktivnosti/" title="12 налаштувань Windows Vista для збільшення продуктивності">12 налаштувань Windows Vista для збільшення продуктивності</a> (0)</li><li><a href="http://easy-code.com.ua/2011/03/stvorennya-3d-obyektiv/" title="Створення 3D об'єктів">Створення 3D об'єктів</a> (0)</li><li><a href="http://easy-code.com.ua/2011/02/zbir-i-publikaciya-proektnix-metrik-v-procesi-rozrobki-programnogo-zabezpechennya-na-bazi-shtatnix-zasobiv-ibm-rational-clearcase/" title="Збір і публікація проектних метрик в процесі розробки програмного забезпечення на базі штатних засобів IBM Rational ClearCase.">Збір і публікація проектних метрик в процесі розробки програмного забезпечення на базі штатних засобів IBM Rational ClearCase.</a> (0)</li></ul> <!--for paginate posts--> <hr/> <p><strong><em> Сподобалася стаття? Ви можете <a href="#comments"> залишити відгук </a> або <a href = "http://easy-code.com.ua/feed/" > підписатися на RSS </a>, щоб автоматично отримувати інформацію про нові статтях. </em></strong></p> <!--Post Meta--> <div class="post-meta"> <strong>Метки: </strong><a href="http://easy-code.com.ua/tag/system/" rel="tag">System</a>, <a href="http://easy-code.com.ua/tag/xmlbeans/" rel="tag">XMLBeans</a>, <a href="http://easy-code.com.ua/tag/vikoristovuvati/" rel="tag">використовувати</a>, <a href="http://easy-code.com.ua/tag/listingu/" rel="tag">лістингу</a>, <a href="http://easy-code.com.ua/tag/servisu/" rel="tag">сервісу</a>, <a href="http://easy-code.com.ua/tag/formuvannya/" rel="tag">формування</a>, <a href="http://easy-code.com.ua/tag/yazuvannya/" rel="tag">язування</a><br /> <strong>Рубрики:</strong> <a href="http://easy-code.com.ua/category/rizne/" rel="category tag">Різне</a> </div> <!--include comments template--> <div id="comments-wrap"> <p>Коментарів поки що немає.</p> <!-- <p><a href="http://easy-code.com.ua/2012/08/web-servisi-java-chastina-3-zvyazuvannya-danix-v-axis2-isxodniki-rizne-programuvannya-statti/feed/">RSS-стрічка коментарів.</a> <a href="http://easy-code.com.ua/2012/08/web-servisi-java-chastina-3-zvyazuvannya-danix-v-axis2-isxodniki-rizne-programuvannya-statti/trackback/" rel="trackback">Адреса для трекбек</a> </p> --> <h3 class="postcomment">Ваш отзыв</h3> <p>Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <code><a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> </code></p> <form action="http://easy-code.com.ua/wp-comments-post.php" method="post" id="commentform"> <p> <input type="text" name="author" id="author" class="textarea" value="" size="28" tabindex="1" /> <label for="author">Им'я</label> * </p> <p> <input type="text" name="email" id="email" value="" size="28" tabindex="2" /> <label for="email">E-mail</label> * </p> <p> <input type="text" name="url" id="url" value="" size="28" tabindex="3" /> <label for="url">Сайт</label> </p> <p> <label for="comment">Повідомлення</label> <br /> <textarea name="comment" id="comment" cols="60" rows="10" tabindex="4"></textarea> </p> <p> <input name="submit" id="submit" type="submit" tabindex="5" value="відправити" /> <input type="hidden" name="comment_post_ID" value="17563" /> <input type="hidden" name="redirect_to" value="/2012/08/web-servisi-java-chastina-3-zvyazuvannya-danix-v-axis2-isxodniki-rizne-programuvannya-statti/" /> </p> <p style="display: none;"><input type="hidden" id="akismet_comment_nonce" name="akismet_comment_nonce" value="2e5ca3e691" /></p><p style="display: none;"><input type="hidden" id="ak_js" name="ak_js" value="19"/></p></form> </div> <!--do not delete--> <!--single.php end--> </div> <!--include sidebar--> <!--sidebar.php--> <div id="sidebar"> <div class="sidebar-rss"> <h3>Подписка через RSS</h3> <p><a href="http://easy-code.com.ua/feed/"><img src="http://easy-code.com.ua/wp-content/themes/elegantblue/images/rss.jpg" alt="Подписка на RSS" ></img></a>Якщо вам сподобалася інформація на нашому сайті, ви можете підписатися на оновлення через RSS.</p> </div> <BR> <div class="something"> <a href='http://easy-code.com.ua/tag/download/' class='tag-link-563 tag-link-position-1' title='648 topics' style='font-size: 12.328358208955pt;'>Download</a> <a href='http://easy-code.com.ua/tag/microsoft/' class='tag-link-66 tag-link-position-2' title='772 topics' style='font-size: 13.522388059701pt;'>Microsoft</a> <a href='http://easy-code.com.ua/tag/oracle/' class='tag-link-18322 tag-link-position-3' title='357 topics' style='font-size: 8.4477611940299pt;'>Oracle</a> <a href='http://easy-code.com.ua/tag/windows/' class='tag-link-18319 tag-link-position-4' title='1,383 topics' style='font-size: 17.253731343284pt;'>Windows</a> <a href='http://easy-code.com.ua/tag/internet/' class='tag-link-132 tag-link-position-5' title='366 topics' style='font-size: 8.5970149253731pt;'>Інтернет</a> <a href='http://easy-code.com.ua/tag/merezhi/' class='tag-link-143 tag-link-position-6' title='438 topics' style='font-size: 9.7910447761194pt;'>Мережі</a> <a href='http://easy-code.com.ua/tag/modeli/' class='tag-link-530 tag-link-position-7' title='360 topics' style='font-size: 8.5970149253731pt;'>моделі</a> <a href='http://easy-code.com.ua/tag/mozhete/' class='tag-link-3 tag-link-position-8' title='569 topics' style='font-size: 11.582089552239pt;'>можете</a> <a href='http://easy-code.com.ua/tag/mozhut/' class='tag-link-311 tag-link-position-9' title='384 topics' style='font-size: 9.044776119403pt;'>можуть</a> <a href='http://easy-code.com.ua/tag/dopomogoyu/' class='tag-link-273 tag-link-position-10' title='731 topics' style='font-size: 13.074626865672pt;'>допомогою</a> <a href='http://easy-code.com.ua/tag/dozvolyaye/' class='tag-link-542 tag-link-position-11' title='664 topics' style='font-size: 12.477611940299pt;'>дозволяє</a> <a href='http://easy-code.com.ua/tag/kompani%d1%97/' class='tag-link-554 tag-link-position-12' title='546 topics' style='font-size: 11.283582089552pt;'>компанії</a> <a href='http://easy-code.com.ua/tag/koristuvachiv/' class='tag-link-137 tag-link-position-13' title='337 topics' style='font-size: 8.1492537313433pt;'>користувачів</a> <a href='http://easy-code.com.ua/tag/potribno/' class='tag-link-18 tag-link-position-14' title='566 topics' style='font-size: 11.432835820896pt;'>потрібно</a> <a href='http://easy-code.com.ua/tag/programi/' class='tag-link-387 tag-link-position-15' title='1,547 topics' style='font-size: 18pt;'>програми</a> <a href='http://easy-code.com.ua/tag/prosto/' class='tag-link-99 tag-link-position-16' title='328 topics' style='font-size: 8pt;'>просто</a> <a href='http://easy-code.com.ua/tag/vikoristannya/' class='tag-link-690 tag-link-position-17' title='368 topics' style='font-size: 8.7462686567164pt;'>використання</a> <a href='http://easy-code.com.ua/tag/vikoristovuvati/' class='tag-link-890 tag-link-position-18' title='427 topics' style='font-size: 9.6417910447761pt;'>використовувати</a> <a href='http://easy-code.com.ua/tag/znachennya/' class='tag-link-198 tag-link-position-19' title='1,003 topics' style='font-size: 15.164179104478pt;'>значення</a> <a href='http://easy-code.com.ua/tag/roboti/' class='tag-link-123 tag-link-position-20' title='1,104 topics' style='font-size: 15.761194029851pt;'>роботи</a> <a href='http://easy-code.com.ua/tag/rozrobki/' class='tag-link-1235 tag-link-position-21' title='328 topics' style='font-size: 8pt;'>розробки</a> <a href='http://easy-code.com.ua/tag/sistemi/' class='tag-link-476 tag-link-position-22' title='1,131 topics' style='font-size: 15.910447761194pt;'>системи</a> <a href='http://easy-code.com.ua/tag/upravlinnya/' class='tag-link-556 tag-link-position-23' title='760 topics' style='font-size: 13.373134328358pt;'>управління</a> <a href='http://easy-code.com.ua/tag/server/' class='tag-link-197 tag-link-position-24' title='650 topics' style='font-size: 12.328358208955pt;'>сервер</a> <a href='http://easy-code.com.ua/tag/stvorennya/' class='tag-link-439 tag-link-position-25' title='460 topics' style='font-size: 10.089552238806pt;'>створення</a> <a href='http://easy-code.com.ua/tag/tablici/' class='tag-link-496 tag-link-position-26' title='469 topics' style='font-size: 10.238805970149pt;'>таблиці</a> <a href='http://easy-code.com.ua/tag/tilki/' class='tag-link-6 tag-link-position-27' title='1,295 topics' style='font-size: 16.805970149254pt;'>тільки</a> <a href='http://easy-code.com.ua/tag/fajliv/' class='tag-link-293 tag-link-position-28' title='410 topics' style='font-size: 9.3432835820896pt;'>файлів</a> <a href='http://easy-code.com.ua/tag/funkci%d1%97/' class='tag-link-218 tag-link-position-29' title='439 topics' style='font-size: 9.7910447761194pt;'>функції</a> <a href='http://easy-code.com.ua/tag/informaci%d1%97/' class='tag-link-24 tag-link-position-30' title='368 topics' style='font-size: 8.7462686567164pt;'>інформації</a></div> <!--l_sidebar.php--> <div id="l_sidebar"> <ul> <br> <!--favorite posts--> <li> <h2>Нове на сайті</h2> <ul> <li><a href='http://easy-code.com.ua/2015/11/keruyuchi-klavishi-i-menyu-informix/'>Керуючі клавіші і меню INFORMIХ</a></li> <li><a href='http://easy-code.com.ua/2015/10/vipushheno-reliz-fastreport-fmx/'>Випущено реліз FastReport FMX</a></li> <li><a href='http://easy-code.com.ua/2015/10/oracle/'>Oracle</a></li> <li><a href='http://easy-code.com.ua/2015/09/func-hgi-35i-vertolit-z-keruvannyam-vid-iphone/'>Func HGI-35i: вертоліт з керуванням від iPhone</a></li> <li><a href='http://easy-code.com.ua/2015/08/faq-po-grafiku-i-animaciyu-dlya-web/'>FAQ по графіку і анімацію для Web</a></li> <li><a href='http://easy-code.com.ua/2015/07/funkciya-viznachennya-kilkosti-robochix-dniv/'>Функція визначення кількості робочих днів</a></li> <li><a href='http://easy-code.com.ua/2015/07/inshi-mozhlivosti-obyednannya-fajliv/'>Інші можливості об’єднання файлів</a></li> <li><a href='http://easy-code.com.ua/2015/07/oglyad-navushnikiv-z-aktivnim-shumozaglushennyam-asus-nc1/'>Огляд навушників з активним шумозаглушенням ASUS NC1</a></li> <li><a href='http://easy-code.com.ua/2015/06/net-service-oriented-architecture-soa/'>.NET: Service Oriented Architecture (SOA)</a></li> <li><a href='http://easy-code.com.ua/2015/06/oglyad-behold-betab-7004/'>Огляд Behold BeTAB 7004</a></li> </ul> </li> <li> <h2>Реклама</h2> <ul> <div class="adcontentcen1"> <!-- Sidebar 160x600 #956693 --> <script>(function(e){var t="DIV_DA_"+e+"_"+parseInt(Math.random()*1e3); document.write('<div id="'+t+'" class="directadvert-block directadvert-block-'+e+'"></div>'); if("undefined"===typeof loaded_blocks_directadvert){loaded_blocks_directadvert=[]; function n(){var e=loaded_blocks_directadvert.shift(); var t=e.adp_id; var r=e.div; var i=document.createElement("script"); i.type="text/javascript"; i.async=true; i.charset="windows-1251"; i.src="//code.directadvert.ru/data/"+t+".js?async=1&div="+r+"&t="+Math.random(); var s=document.getElementsByTagName("head")[0]||document.getElementsByTagName("body")[0]; s.appendChild(i); var o=setInterval(function(){if(document.getElementById(r).innerHTML&&loaded_blocks_directadvert.length){n(); clearInterval(o)}},50)} setTimeout(n)}loaded_blocks_directadvert.push({adp_id:e,div:t})})(956693)</script> </div> </ul> </li> </ul> </div> <!--l_sidebar.php end--> <!--r_sidebar.php--> <div id="r_sidebar"> <ul> <br> <li> <h2>Популярне</h2> <ul> <!-- 2017-09-21 10:45:04 --> <li><a href="http://easy-code.com.ua/2010/10/klasifikaciya-veb-resursiv/">Класифікація веб-ресурсів (8)</a></li> <li><a href="http://easy-code.com.ua/2012/08/analiz-ta-proektuvannya-vizualne-modelyuvannya-uml-rational-rose-case-zasobi-modelyuvannya-programuvannya-statti/">Аналіз та проектування. Візуальне моделювання (UML) Rational Rose, CASE-засоби (моделювання), Програмування, статті (10)</a></li> <li><a href="http://easy-code.com.ua/2012/09/yak-vidaliti-numeraciyu-storinok-ms-office-programni-kerivnictva-statti/">Як видалити нумерацію сторінок, MS Office, Програмні керівництва, статті (8)</a></li> <li><a href="http://easy-code.com.ua/2012/08/oblikova-politika-vnutrishnofirmovi-standarti-upravlinskogo-obliku-komerciya-rizne-statti/">Облікова політика. Внутрішньофірмові стандарти управлінського обліку, Комерція, Різне, статті (16)</a></li> <li><a href="http://easy-code.com.ua/2012/08/yak-zminiti-mizhbukvenij-interval-ms-office-programni-kerivnictva-statti/">Як змінити міжбуквений інтервал, MS Office, Програмні керівництва, статті (26)</a></li> <li><a href="http://easy-code.com.ua/2014/07/stvorennya-panelej-instrumentiv-i-menyu/">Створення панелей інструментів і меню (8)</a></li> <li><a href="http://easy-code.com.ua/2011/08/svitovij-rinok-sistem-elektronnogo-dokumentoobigu/">Світовий ринок систем електронного документообігу (6)</a></li> <li><a href="http://easy-code.com.ua/2012/08/modelyuvannya-texnichnix-sistem-c-allfusion-process-modeler-ranishe-bpwin-komerciya-rizne-statti/">Моделювання технічних систем c AllFusion Process Modeler (раніше BPwin), Комерція, Різне, статті (10)</a></li> <li><a href="http://easy-code.com.ua/2011/04/panel-instrumentiv-formi-u-word/">Панель інструментів ФОРМИ у Word (18)</a></li> <li><a href="http://easy-code.com.ua/2011/03/corel-draw-redaguvannya-i-vidilennya/">Corel Draw: Редагування і виділення (7)</a></li> <li><a href="http://easy-code.com.ua/2011/03/robota-z-fajlami-v-komandnomu-ryadku-operacijnix-sistem/">Робота з файлами в командному рядку операційних систем. (13)</a></li> <li><a href="http://easy-code.com.ua/2012/08/case-zasobi-zagalna-xarakteristika-i-klasifikaciya-komerciya-rizne-statti/">CASE-засоби. Загальна характеристика і класифікація, Комерція, Різне, статті (12)</a></li> <li><a href="http://easy-code.com.ua/2012/08/vstavka-i-peremishhennya-zobrazhen-v-word-2010-ms-office-programni-kerivnictva-statti/">Вставка і переміщення зображень в Word 2010, MS Office, Програмні керівництва, статті (15)</a></li> <li><a href="http://easy-code.com.ua/2011/01/recenzuvannya-dokumentiv-u-word/">Рецензування документів у Word (22)</a></li> <li><a href="http://easy-code.com.ua/2012/08/yak-vstaviti-alfavitnij-predmetnij-pokazhchik-v-dokument-ms-office-programni-kerivnictva-statti/">Як вставити алфавітний (предметний) покажчик в документ, MS Office, Програмні керівництва, статті (11)</a></li> <li><a href="http://easy-code.com.ua/2010/12/programuvannya-na-movi-delphi-glava-7-proekt-programi/">Програмування на мові Delphi. Глава 7. Проект програми (16)</a></li> <li><a href="http://easy-code.com.ua/2012/08/gibernaciya-son-i-gibridnij-splyachij-rezhim-v-windows-7-pitannya-i-vidpovidi-windows-operacijni-sistemi-statti/">Гібернація, сон і гібридний сплячий режим в Windows 7 – питання і відповіді, Windows, Операційні системи, статті (9)</a></li> <li><a href="http://easy-code.com.ua/2012/09/zasobi-rozrobki-dodatkiv-rizne-programuvannya-statti/">Засоби розробки додатків, Різне, Програмування, статті (9)</a></li> <li><a href="http://easy-code.com.ua/2012/07/opis-biznes-procesiv-sadt-idef0-idef3-dfd-uml-aris-case-zasobi-modelyuvannya-programuvannya-statti/">Опис бізнес-процесів: SADT, IDEF0, IDEF3, DFD, UML, ARIS, CASE-засоби (моделювання), Програмування, статті (20)</a></li> <li><a href="http://easy-code.com.ua/2012/08/nalashtuvannya-ekrannix-zastavok-v-windows-7-za-dopomogoyu-reyestru-windows-operacijni-sistemi-statti/">Налаштування екранних заставок в Windows 7 за допомогою реєстру, Windows, Операційні системи, статті (26)</a></li> <!-- 2017-09-21 10:45:04 --></ul> </li> </ul> </div> <!--r_sidebar.php end--> </div> <!--sidebar.php end--><!--include footer--> </div> <div id="footer"> <p> При використанні матеріалів даного сайту пряме і явне посилання на сайт <a href="http://www.easy-code.com.ua/"> www.easy-code.com.ua </a> є обов'язковим. </p> <!--footer.php--> <div id="footer-wrap"> <noindex> <!--LiveInternet counter--><script type="text/javascript"><!-- document.write("<a href='http://www.liveinternet.ru/click' "+ "target=_blank><img src='//counter.yadro.ru/hit?t19.6;r"+ escape(document.referrer)+((typeof(screen)=="undefined")?"": ";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth? screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+ ";"+Math.random()+ "' alt='' title='LiveInternet: показано число просмотров за 24"+ " часа, посетителей за 24 часа и за сегодня' "+ "border='0' width='88' height='31'><\/a>") //--></script><!--/LiveInternet--> <!-- Yandex.Metrika counter --> <div style="display:none;"><script type="text/javascript"> (function(w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounter10604395 = new Ya.Metrika({id:10604395, enableAll: true}); } catch(e) { } }); })(window, "yandex_metrika_callbacks"); </script></div> <script src="//mc.yandex.ru/metrika/watch.js" type="text/javascript" defer="defer"></script> <noscript><div><img src="//mc.yandex.ru/watch/10604395" style="position:absolute; left:-9999px;" alt="" /></div></noscript> <!-- /Yandex.Metrika counter --> <script type="text/javascript" src="//yandex.st/share/share.js" charset="utf-8"></script> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"> {lang: 'ru'} </script> </noindex> <BR><strong>ЕasyСode</strong> <!--necessary--> <script type='text/javascript' src='http://easy-code.com.ua/wp-content/plugins/akismet/_inc/form.js?ver=3.3'></script> <script type='text/javascript' src='http://easy-code.com.ua/wp-includes/js/wp-embed.min.js?ver=4.7.6'></script> <script type='text/javascript' src='http://easy-code.com.ua/wp-includes/js/jquery/jquery.js?ver=1.12.4'></script> <script type='text/javascript' src='http://easy-code.com.ua/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.4.1'></script> <script type='text/javascript' src='http://easy-code.com.ua/wp-content/plugins/easy-fancybox/fancybox/jquery.fancybox-1.3.8.min.js?ver=1.5.8.2'></script> <script type='text/javascript' src='http://easy-code.com.ua/wp-content/plugins/easy-fancybox/js/jquery.easing.min.js?ver=1.3.2'></script> <script type='text/javascript' src='http://easy-code.com.ua/wp-content/plugins/easy-fancybox/js/jquery.mousewheel.min.js?ver=3.1.12'></script> <script type="text/javascript"> jQuery(document).on('ready post-load', function(){ jQuery('.nofancybox,a.pin-it-button,a[href*="pinterest.com/pin/create/button"]').addClass('nolightbox'); }); jQuery(document).on('ready post-load',easy_fancybox_handler); jQuery(document).on('ready',easy_fancybox_auto);</script> </div> </div> <div class="soc-buttons"> <div class="yashare-auto-init" data-yashareL10n="ru" data-yashareQuickServices="vkontakte,facebook,twitter,odnoklassniki,moimir,gplus" data-yashareTheme="counter"></div> </div> <script>!window.jQuery && document.write('<script src="http://yastatic.net/jquery/2.1.3/jquery.min.js"><\/script>');</script> <script src="http://easy-code.com.ua/wp-content/themes/elegantblue/js/jquery.hc-sticky.min.js"></script> <script> jQuery(document).ready(function($){ $('.soc-buttons').hcSticky({ top: 25, bottomEnd: 90, wrapperClassName: 'sidebar-sticky2', noContainer: false }); }); </script> <script type="text/javascript" src="//yastatic.net/share/share.js" charset="utf-8"></script> </body> </html>