Донецкий техникум промышленной автоматики

Поради з програмування Web-сервісів: Вивчення шаблонів проектування Web-сервісів, Частина 1

  1. Серія контенту:
  2. Цей контент є частиною серії: Поради з програмування Web-сервісів
  3. Шаблон асинхронного запиту
  4. Малюнок 1. Шаблон асинхронного запиту
  5. Проектування інтерфейсу сервісу
  6. Лістинг 1. AsyncService.wsdl
  7. Лістинг 2. Обмін повідомленнями AsyncService
  8. Лістинг 3. JNDIListenerServlet.java
  9. Лістинг 4. JNDIHelper.java
  10. Лістинг 5. AsyncService.java
  11. висновки
  12. Ресурси для скачування

Поради з програмування Web-сервісів

Асинхронні операції Web-сервісів з використанням JMS

Серія контенту:

Цей контент є частиною # з серії # статей: Поради з програмування Web-сервісів

https://www.ibm.com/developerworks/ru/library/?series_title_by=**auto**

Слідкуйте за виходом нових статей цієї серії.

Цей контент є частиною серії: Поради з програмування Web-сервісів

Слідкуйте за виходом нових статей цієї серії.

Якщо уявити собі реалізацію Web-сервісів з SOAP, швидше за все, вам прийдуть в голову прості синхронні операції типу запит-відповідь. Насправді Service-Oriented Architecture (SOA) може охоплювати набагато більший діапазон моделей обміну повідомленнями та стратегій проектування. В даному документі ми сфокусуємось на застосуванні основних шаблонів проектування Web-додатків з використанням Web-сервісів. Подані шаблони не є новими, вони використовуються в традиційних Web-додатках вже багато років, проте багато розробників навіть не підозрюють про те, як реалізувати такі методики в області Web-сервісів або ж не до кінця розуміють, як їх застосовувати. Автор ставить перед собою завдання уявлення набору простих, відкритих альтернатив проектування моделі запит-відповідь. Для вивчення прикладу вам необхідно мати хоча б основні уявлення про реалізацію Web-сервісів в середовищі J2EE.

Шаблон асинхронного запиту

Щоб відкинути зайве, ми досліджуємо реалізацію асинхронних операцій запитів і відповідей з метою розбиття тривалих операцій, і для того щоб уникнути тайм-аутів або довгих відбою при виконанні коду. Якщо ви маєте досвід реалізації асинхронних запитів в традиційних Web-додатках HTTP і HTML, застосовуваний шаблон повинен бути вам знаком.

Малюнок 1. Шаблон асинхронного запиту

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

  1. Запитуюча Сторона передає запит до постачальника сервісу, той ставить повідомлення в чергу і повертає ID кореляції, який запитує, сторона пізніше може використовувати для перевірки статусу запиту.
  2. Оброблювач запиту видаляє запит з черги і обробляє його. Зазвичай обробка запиту є тривалим процесом. Після завершення обробки процесор ставить в чергу повідомлення відповіді.
  3. У певний невизначений момент часу, яка запитує сторона опитує постачальника сервісу на предмет готовності запиту. Якщо запит знаходиться в черзі, постачальник повертає його назад. Якщо запит недоступний, постачальник повідомляє про це запитуючої сторони, яка може вибрати - скасувати запит або чекати відповіді, опитуючи постачальника через певні проміжки часу на наявність готового запиту.

Про застосування даного шаблону в додатках сервлетів J2EE для Java Ranch (Web-сайту Java-розробників) написана чудова стаття, автором якої є Kyle Brown (Див. Ресурси по темі ). У даній статті, крім усього іншого, обговорюються мотивації і основні питання проектування щодо базової реалізації даного шаблону. Тож не дивно, що реалізація не сильно змінилася в шаблоні, застосовне для Web-сервісів.

Проектування інтерфейсу сервісу

Для ілюстрування шаблону асинхронного запиту ми реалізуємо простий приклад Web-сервісу, який поза цього прикладу не має особливого практичного значення. Даний сервіс виконує просте перетворення трьох вхідних значень типу String з нижнього регістра в верхній після застосування 10-ти секундної затримки (для симуляції тривалих процесів).

Для реалізації даного сервісу доступні дві операції: submitRequest і checkResponse. Дія цих операцій не вимагає пояснення. В лістингу 1 представлений WSDL, що описує інтерфейс сервісу.

Лістинг 1. AsyncService.wsdl
<? Xml version = "1.0&quot; encoding = "UTF-8"?> <Wsdl: definitions targetNamespace = "http://one.wspattern.developerworks.ibm.com" xmlns: impl = "http: //one.wspattern .developerworks.ibm.com "xmlns: intf =" http://one.wspattern.developerworks.ibm.com "xmlns: wsdl =" http://schemas.xmlsoap.org/wsdl/ "xmlns: wsdlsoap =" http : //schemas.xmlsoap.org/wsdl/soap/ "xmlns: xsd =" http://www.w3.org/2001/XMLSchema "> <wsdl: types> <schema targetNamespace =" http: // one. wspattern.developerworks.ibm.com "xmlns =" ​​http://www.w3.org/2001/XMLSchema "xmlns: impl =" http://one.wspattern.developerworks.ibm.com "xmlns: intf =" http : //one.wspattern.developerworks.ibm.com "xmlns: wsdl =" http://schemas.xmlsoap.org/wsdl/ "xmlns: xsd =" http://www.w3.org/2001/XMLSchema " > <complexType name = "ResponseCheck"> <sequence> <element name = "correlationID" nillable = "true" type = "xsd: string" /> </ sequence> </ complexType> <element name = "ResponseCheck" nillable = "true" type = "impl: ResponseCheck" /> <complexType name = "Response"> <sequence> <element name = "type" type = "xsd: int" / > <Element name = "correlationID" nillable = "true" type = "xsd: string" /> <element name = "refresh" type = "xsd: int" /> <element name = "a" nillable = "true" type = "xsd: string" /> <element name = "b" nillable = "true" type = "xsd: string" /> <element name = "c" nillable = "true" type = "xsd: string" / > </ sequence> </ complexType> <element name = "Response" nillable = "true" type = "impl: Response" /> <complexType name = "Request"> <sequence> <element name = "a" nillable = "true" type = "xsd: string" /> <element name = "b" nillable = "true" type = "xsd: string" /> <element name = "c" nillable = "true" type = "xsd: string "/> </ sequence> </ complexType> <element name =" Request "nillable =" true "type =" impl: Request "/> </ schema> </ wsdl: types> <wsdl: message name =" submitRequestRequest "> <wsdl: part name =" request "type =" intf: Request "/> </ wsdl: message> <wsdl: message name =" checkResponseResponse "> <wsdl: part name =" checkResponseReturn "type =" intf : Response "/> </ wsdl: message> <wsdl: message name =" checkResponseRequest "> <wsdl: part name =" check "type =" intf: ResponseCheck "/> </ Wsdl: message> <wsdl: message name = "submitRequestResponse"> <wsdl: part name = "submitRequestReturn" type = "intf: Response" /> </ wsdl: message> <wsdl: portType name = "AsyncService"> <wsdl: operation name = "checkResponse" parameterOrder = "check"> <wsdl: input message = "intf: checkResponseRequest" name = "checkResponseRequest" /> <wsdl: output message = "intf: checkResponseResponse" name = "checkResponseResponse" / > </ wsdl: operation> <wsdl: operation name = "submitRequest" parameterOrder = "request"> <wsdl: input message = "intf: submitRequestRequest" name = "submitRequestRequest" /> <wsdl: output message = "intf: submitRequestResponse "name =" submitRequestResponse "/> </ wsdl: operation> </ wsdl: portType> <wsdl: binding name =" AsyncServiceSoapBinding "type =" intf: AsyncService "> <wsdlsoap: binding style =" rpc "transport =" http : //schemas.xmlsoap.org/soap/http "/> <wsdl: operation name =" checkResponse "> <wsdlsoap: operation soapAction =" "/> <wsdl: input name =" checkResponseRequest "> <wsdlsoap: body namespace = "http://one.wspattern.developerworks.ibm .com "use =" literal "/> </ wsdl: input> <wsdl: output name =" checkResponseResponse "> <wsdlsoap: body namespace =" http://one.wspattern.developerworks.ibm.com "use =" literal "/> </ wsdl: output> </ wsdl: operation> <wsdl: operation name =" submitRequest "> <wsdlsoap: operation soapAction =" "/> <wsdl: input name =" submitRequestRequest "> <wsdlsoap: body namespace = "http://one.wspattern.developerworks.ibm.com" use = "literal" /> </ wsdl: input> <wsdl: output name = "submitRequestResponse"> <wsdlsoap: body namespace = "http: / /one.wspattern.developerworks.ibm.com "use =" literal "/> </ wsdl: output> </ wsdl: operation> </ wsdl: binding> <wsdl: service name =" AsyncServiceService "> <wsdl: port binding = "intf: AsyncServiceSoapBinding" name = "AsyncService"> <wsdlsoap: address location = "http: // localhost: 9080 / WSPattern1 / services / AsyncService" /> </ wsdl: port> </ wsdl: service> </ wsdl: definitions>

Тут слід зазначити кілька моментів:

  1. Сервіс використовує стиль написання коду RPC / Literal.
  2. Обидві операції submitRequest і checkResponse повертають об'єкт з ім'ям Response. Існує два різновиди Response, що визначаються властивістю типу (type property). Значення властивості типу рівне 0 вказує на Refresh Response, а значення 1 - на Request Response. Refresh Response вказує на те, що відповідь ще не доступний і яка запитує сторона повинна підтвердити нову операцію checkResponse не раніше, ніж зазначено в значенні властивості поновлення (еквівалентно механізму HTTP META Refresh, обговорюваного в статті Kyle Brown). Request Response містить три рядки введення в верхньому регістрі і представляє завершення обробки запиту.
  3. Refresh Response містить властивість Correlation ID, чиє значення використовується в якості введення для операції checkResponse. Даний ідентифікатор є єдиним засобом для зіставлення клієнтом початкового запиту з відповіддю. Існують також і інші способи для цієї реалізації, про які буде розказано пізніше.

В лістингу 2 представлений типовий обмін повідомленнями для даного сервісу.

Лістинг 2. Обмін повідомленнями AsyncService
<I> Initial Request </ i> <SOAP-ENV: Envelope xmlns: SOAP-ENV = "http://schemas.xmlsoap.org/soap/envelope/" xmlns: SOAP-ENC = "http: // schemas. xmlsoap.org/soap/encoding/ "xmlns: xsi =" http://www.w3.org/2001/XMLSchema-instance "xmlns: xsd =" http://www.w3.org/2001/XMLSchema "> <SOAP-ENV: Body> <m: submitRequest xmlns: m = "http://one.wspattern.developerworks.ibm.com"> <request> <a> String </a> <b> String </ b> <c> String </ c> </ request> </ m: submitRequest> </ SOAP-ENV: Body> </ SOAP-ENV: Envelope> <i> submitRequest Response Відповідь submitRequest </ i> <soapenv: Envelope xmlns : soapenv = "http://schemas.xmlsoap.org/soap/envelope/" xmlns: soapenc = "http://schemas.xmlsoap.org/soap/encoding/" xmlns: xsd = "http: // www. w3.org/2001/XMLSchema "xmlns: xsi =" http://www.w3.org/2001/XMLSchema-instance "> <soapenv: Header /> <soapenv: Body> <p155: submitRequestResponse xmlns: p155 =" http://one.wspattern.developerworks.ibm.com "> <submitRequestReturn> <type> 0 </ type> <correlationID> 1097517621904 </ correlationID> <refresh> 10000 </ refresh> <a xsi: nil =" true "/> <B xsi: nil =" true "/> <c xsi: nil =" true "/> </ submitRequestReturn> </ p155: submitRequestResponse> </ soapenv: Body> </ soapenv: Envelope> <i> Initial checkResponse attempt, no response available, submitted after 10000 miliseconds Первинна спроба checkResponse, відповідь не надійшла, виконується після затримки в 10000 мс </ i> <soapenv: Envelope xmlns: soapenv = "http://schemas.xmlsoap.org/soap / envelope / "xmlns: soapenc =" http://schemas.xmlsoap.org/soap/encoding/ "xmlns: xsd =" http://www.w3.org/2001/XMLSchema "xmlns: xsi =" http: //www.w3.org/2001/XMLSchema-instance "> <soapenv: Header /> <soapenv: Body> <p155: checkResponseResponse xmlns: p155 =" http://one.wspattern.developerworks.ibm.com "> <checkResponseReturn> <type> 0 </ type> <correlationID> 1097517621904 </ correlationID> <refresh> 10000 </ refresh> <a xsi:nil="true"/> <b xsi: nil = "true" /> < c xsi: nil = "true" /> </ checkResponseReturn> </ p155: checkResponseResponse> </ soapenv: Body> </ soapenv: Envelope> <i> Second check Response attempt, submitted after 10000 miliseconds Друга спроба checkResponse, виконується після затримки в 10000 мс </ i> <soapenv: Envelope xmlns: soapenv = "http://schemas.xmlsoap.org/soap/envelope/" xmlns: soapenc = " http://schemas.xmlsoap.org/soap/encoding/ "xmlns: xsd =" http://www.w3.org/2001/XMLSchema "xmlns: xsi =" http://www.w3.org/2001 / XMLSchema-instance "> <soapenv: Header /> <soapenv: Body> <p155: checkResponseResponse xmlns: p155 =" http://one.wspattern.developerworks.ibm.com "> <checkResponseReturn> <type> 1 </ type> <correlationID xsi: nil = "true" /> <refresh> 0 </ refresh> <a> STRING </a> <b> STRING </ b> <c> STRING </ c> </ checkResponseReturn> < / p155: checkResponseResponse> </ soapenv: Body> </ soapenv: Envelope>

Реалізація сервісу

Реалізацією сервісу асинхронного шаблону запиту є застосування Java Messaging Service. Для ілюстрації прикладу тут використовується OpenJMS - реалізація постачальника JMS з відкритим вихідним кодом (див. Ресурси по темі ) І IBM® WebSphere® Application Server V5 (сервер додатків). У прикладі використовується конфігурація OpenJMS, визначена за замовчуванням, а також реалізація Web-сервісу J2EE, сумісного з JSR-109. Код для даного прикладу написаний з використанням WebSphere Studio Application Developer (Application Developer) V5.1, який можна завантажити за посиланням з сайту developerWorks (див. Ресурси по темі ). Тут також додається EAR-файл (див. Ресурси по темі ) На той випадок, якщо у вас немає доступу до Application Developer.

На стороні сервера необхідно реалізувати два компонента - обробник запитів і реалізація Web-сервісу. Завданням обробника запитів є зняття запитів з черги і виконання 10-секундної затримки процесу по перетворенню нижнього регістру символів в верхній. Завданням реалізації сервісу є отримання запитів від клієнтів Web-сервісу і постановка їх в чергу для обробки і для доставки відповідей клієнтам, слідуючи операції checkResponse.

У типовому додатку J2EE, згідно специфікації JMS, обробник запитів повинен бути реалізований як Message Driven Bean (компонент, керований повідомленнями). В даному прикладі використовується простий HTTP-сервлет, який реалізує JMS-інтерфейс MessageListener. Сервлет налаштований на ініціалізацію при завантаженні сервера, що дозволяє слухачеві бути доступним для всіх можливих вхідних запитів. Після постановки запиту в чергу той доставляється сервлету-слухачеві.

Лістинг 3. JNDIListenerServlet.java
package com.ibm.developerworks.wspattern.one.helper; import java.util.Enumeration; import java.util.Hashtable; import javax.jms.JMSException; import javax.jms.MapMessage; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueReceiver; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.naming.Context; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; public class JNDIListenerServlet extends HttpServlet implements Servlet, MessageListener {private Context context; private QueueConnection connection; private QueueSession session; private Queue queue; private QueueReceiver receiver; public void init () throws ServletException {super.init (); try {context = JNDIHelper.getInitialContext (); connection = JNDIHelper.getConnection (context); session = JNDIHelper.getSession (connection); queue = JNDIHelper.getQueue (context); receiver = JNDIHelper.getQueueReceiver (session, queue); receiver.setMessageListener (this); System.out.println ( "Listener servlet is Listening"); } Catch (Exception e) {}} public void destroy () {try {connection.close (); } Catch (Exception e) {}} public void onMessage (Message message) {try {System.out.println ( "Processing message" + message.getJMSCorrelationID ()); Thread.sleep (10 * 1000); // sleep for ten seconds Queue responseQueue = JNDIHelper.getResponseQueue (context); QueueSender sender = JNDIHelper.getQueueSender (session, responseQueue); MapMessage request = (MapMessage) message; MapMessage response = session.createMapMessage (); response.setJMSCorrelationID (request.getJMSCorrelationID ()); for (Enumeration e = request.getMapNames (); e.hasMoreElements ();) {String name = (String) e.nextElement (); try {response.setString (name, request.getString (name) .toUpperCase ()); } Catch (Exception ex) {}} sender.send (response); } Catch (Exception e) {System.out.println ( "=================="); try {System.out.println ( "THERE WAS AN ERROR PROCESSING THE MESSAGE!" + message.getJMSCorrelationID ()); } Catch (Exception ex) {} e.printStackTrace (System.out); System.out.println ( "=================="); }}}

Сервлет JNDIListenerServlet і реалізація сервісу використовують один простий допоміжний клас, створений для цього додатка, який приховує деталі ініціалізації JMS-з'єднання і сесії.

Лістинг 4. JNDIHelper.java
package com.ibm.developerworks.wspattern.one.helper; import java.util.Hashtable; import javax.jms.JMSException; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; import javax.jms.QueueReceiver; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.jms.Session; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; public class JNDIHelper {private static Context context; public static Context getInitialContext () throws NamingException {if (context == null) {Hashtable properties = new Hashtable (); properties.put (Context.INITIAL_CONTEXT_FACTORY, "org.exolab.jms.jndi.InitialContextFactory"); properties.put (Context.PROVIDER_URL, "rmi: // localhost: 1099"); context = new InitialContext (properties); } Return context; } Public static QueueConnection getConnection (Context context) throws NamingException, JMSException {QueueConnectionFactory factory = (QueueConnectionFactory) context.lookup ( "JmsQueueConnectionFactory"); QueueConnection connection = factory.createQueueConnection (); connection.start (); return connection; } Public static QueueSession getSession (QueueConnection connection) throws JMSException {QueueSession session = connection.createQueueSession (false, Session.AUTO_ACKNOWLEDGE); return session; } Public static Queue getQueue (Context context) throws NamingException {Queue queue = (Queue) context.lookup ( "queue1"); return queue; } Public static Queue getResponseQueue (Context context) throws NamingException {Queue queue = (Queue) context.lookup ( "queue2"); return queue; } Public static QueueSender getQueueSender (QueueSession session, Queue queue) throws JMSException {QueueSender sender = session.createSender (queue); return sender; } Public static QueueReceiver getQueueReceiver (QueueSession session, Queue queue) throws JMSException {QueueReceiver receiver = session.createReceiver (queue); return receiver; } Public static QueueReceiver getQueueReceiver (QueueSession session, Queue queue, String selector) throws JMSException {QueueReceiver receiver = session.createReceiver (queue, selector); return receiver; }}

Після створення сервлету відредагуйте файл Web-додатки web.xml таким чином, щоб сервлет ініціалізувати при завантаженні сервера. При ініціалізації сервлет створює JMS-з'єднання і реєструє себе в якості слухача в черзі повідомлень OpenJMS, заданої за замовчуванням.

Другим кроком є ​​створення реалізації сервісу. Тут може стати в нагоді робота з Application Developer, який може допомогти в генеруванні різних артефактів для отримання працюючого JSR-109 Web-сервісу. Тепер сфокусуємось виключно на класі реалізації сервісу. Для ілюстрації інших різних файлів конфігурацій Java і XML до даного документу додається вихідний код, який може бути завантажений за посиланням в кінці документа.

Лістинг 5. AsyncService.java
package com.ibm.developerworks.wspattern.one; import javax.jms.MapMessage; import javax.jms.Message; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueReceiver; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.naming.Context; import com.ibm.developerworks.wspattern.one.helper.JNDIHelper; public class AsyncService {public Response submitRequest (Request request) {Response response = null; try {Context context = JNDIHelper.getInitialContext (); QueueConnection connection = JNDIHelper.getConnection (context); QueueSession session = JNDIHelper.getSession (connection); Queue queue = JNDIHelper.getQueue (context); QueueSender sender = JNDIHelper.getQueueSender (session, queue); MapMessage message = session.createMapMessage (); String corrID = Long.toString (System.currentTimeMillis ()); message.setJMSCorrelationID (corrID); message.setString ( "one", request.getA ()); message.setString ( "two", request.getB ()); message.setString ( "three", request.getC ()); sender.send (message); response = new Response (); response.setType (Response.TYPE_REFRESH); response.setCorrelationID (corrID); response.setRefresh (10 * 1000); return response; } Catch (Exception e) {response = new Response (); response.setType (Response.TYPE_RESPONSE); response.setA (e.getMessage ()); } Return response; } Public Response checkResponse (ResponseCheck check) {String corrID = check.getCorrelationID (); Response response = null; try {Context context = JNDIHelper.getInitialContext (); QueueConnection connection = JNDIHelper.getConnection (context); QueueSession session = JNDIHelper.getSession (connection); Queue queue = JNDIHelper.getResponseQueue (context); String selector = "JMSCorrelationID = '" + corrID + "'"; QueueReceiver receiver = JNDIHelper.getQueueReceiver (session, queue, selector); Message message = receiver.receiveNoWait (); if (message == null) {response = new Response (); response.setType (Response.TYPE_REFRESH); response.setRefresh (10 * 1000); response.setCorrelationID (corrID); } Else {MapMessage resp = (MapMessage) message; response = new Response (); response.setType (Response.TYPE_RESPONSE); response.setA (resp.getString ( "one")); response.setB (resp.getString ( "two")); response.setC (resp.getString ( "three")); }} Catch (Exception e) {} return response; }}

У цьому лістингу немає нічого незвичайного. Метод submitRequest готує JMS MapMessage на базі вхідних параметрів. Це повідомлення складається з трьох строкових значень. Після цього повідомлення відправляється в чергу і готується Refresh Response містить ID кореляції, після чого той повертається клієнтові.

Операція checkResponse приймає ID кореляції з вхідних параметрів і встановлює з'єднання з чергою відповіді, запитуючи доставку будь-яких повідомлень з відповідним ID кореляції. Якщо таких повідомлень не існує, операція не чекає їх, а готує інший Refresh Response з новим періодом інтервалу оновлення і повертає його назад запитуючої сторони. Якщо повідомлення доставлено, операція готує і повертає відповідний Request Response.

Для запуску Web-сервісу асинхронного шаблону запиту необхідно розмістити Web-сервіс і запустити сервери OpenJMS і WebSphere.

висновки

Основною перевагою шаблону асинхронних запитів є можливість кореляції запитів і відповідей клієнтом Web-сервісів і постачальником сервісу. У представленому тут прикладі було розглянуто простий ID кореляції одноразового використання та механізм поновлення таймера, властивого цьому окремому наприклад додатки. Для цієї ж мети можна використовувати, наприклад, кілька комбінацій WS- * специфікацій. WS-Addressing Endpoint Reference або WS-Transaction Coordination Context також можуть містити ID кореляції і оновлювати значення таймера. Використання даного шаблону індивідуально для окремих додатків, і незалежно від того, чи використовуєте ви стандартні елементи заголовка SOAP і різні WS- * специфікації, поведінка кожної реалізації операції повинно бути чітко визначено та задокументовано.

У реалізованому тут прікладі для відправкі Запитів и Отримання Відповідей вікорістовується традіційній шаблон обміну повідомленнями SOAP типу запит-відповідь. В якості альтернативи можна використовуват шаблон в стилі REST, в Якій Предложения відправляються сервлету методом HTTP POST, а ВІДПОВІДІ вітягуються з Використання методу HTTP GET. КОЖЕН з ціх підходів є в рівній мірі допустимим и володіє Власний перевага и недолікамі. Вибір підходу здійснюється в залежності від вимоги вашого! Застосування. Наприклад, якщо операція checkResponse вимагатиме використання аутентифікації WS-Security, то в використання моделі взаємодії в стилі REST немає сенсу.

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

Ресурси для скачування

Схожі тими

  • Оригінальна стаття "Learn simple, practical Web services design patterns, Part 1"
  • Інші документи з серії "Практичне навчання використанню шаблонів Web-сервісів":
  • Стаття, що розповідає про шаблон асинхронних запитів "Asynchronous Queries in J2EE" , Де представлені теоретичні основи, необхідні для обговорення шаблонів асинхронних запитів. Опублікувати на сайті Java Ranch , Автор Kyle Brown.
  • Посилання на завантаження програми WebSphere Studio Application Developer , Використовуваної для написання даного прикладу програми.
  • Посилання на інформацію про програму з відкритим вихідним кодом OpenJMS provider .
  • Книжковий магазин Developer Bookstore , Що містить сотні книг про Web-сервісах .
  • Безліч інформативних статей і посібників з розробки додатків Web-сервісів в розділі SOA і Web-сервіси на developerWorks Росія.
  • ПОСИЛАННЯ по темі:
    Вивчення шаблонів проектування Web-сервісів, Частина 2
    Вивчення шаблонів проектування Web-сервісів, Частина 3
    Прості і корисні моделі проектування Web-служб, частина 4

Підпішіть мене на ПОВІДОМЛЕННЯ до коментарів

Com/developerworks/ru/library/?
Quot; encoding = "UTF-8"?