среда, 6 июля 2011 г.

Динамическая маршрутизация в Oracle Service Bus


В Oracle Service Bus (OSB) используются следующие концепции:

  • Business Service осуществляет связь между тем сервисом, который необходимо вызвать, и шиной;

  • Proxy Service осуществляет связь между клиентом и шиной;

  • Message Flow поток обработки сообщений, осуществляет связь между Proxy Service и одним или несколькими Business Service. Поток обработки сообщений может быть довольно сложным и включать в себя маршрутизацию, трансформацию, параллельное исполнение и другие действия. Физически Message Flow описывается в Proxy Service.





Сегодня мы рассмотрим как настроить такое действие потока обработки сообщений, как динамическая маршрутизация. Под динамической маршрутизацией в OSB понимается маршрутизация, основанная на содержимом сообщения - т.н. Content-based Routing. Данный тип маршрутизации является альтернативой т.н. статической маршрутизации - типу маршрутизации, при котором маршрут сообщения задается на этапе разработки.

Создание сервисов, к которым будет осуществляться маршрутизация


Для демонстрации использования динамической маршрутизации создадим с помощью Oracle SOA Suite два простых сервиса: сервис, принимающий запросы для России, - SomeServiceRu и сервис, принимающий запросы для Англии, - SomeServiceEng. Оба сервиса создаются в IDE JDeveloper и представляют собой BPEL-процессы, принимающие на вход сообщение, описываемое следующей схемой:



Композит, инкапсулирующий в себя BPEL-процесс, реализующий бизнес-логику сервиса, выглядит следующим образом:



Схема самого BPEL процесса довольно проста: на входящее сообщение формируется ответ, содержащий константу ENG для сервиса SomeServiceEng и константу RU для сервиса SomeServiceRu.



Создание OSB-проекта в Oracle Enterprise Pack for Eclipse


Для настройки динамической маршрутизации нам нужно создать проект CountryRouter, в котором определить Business Service BusinessServiceEng.biz для сервиса SomeServiceEng, Business Service BusinessServiceRu.biz для сервиса SomeServiceRu и Proxy Service CountryProxyService.proxy, в котором настроить динамическую маршрутизацию.

Подробно создание проекта для Oracle Service Bus в среде Oracle Enterprise Pack for Eclipse описано в статье Создаем Hello World на Oracle Service Bus с использованием Oracle Enteprise Pack for Eclipse. В данной же заметке сосредоточимся только на создании Proxy Service.

Прежде всего необходимо создать WSDL-описание для данного сервиса. WSDL-описание можно создать с помощью стандартного мастера, входящего в Eclipse и доступного из пункта меню File -> New -> WSDL.



На первом шаге мастера необходимо выбрать расположение создаваемого файла и указать его имя.



На втором шаге мастера необходимо указать, что нам нужен скелет WSDL-файла и задать целевое пространство имен и префикс к нему.



Текст WSDL-описания для Proxy Service следующий:

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>

  2. <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.tsretail.ru/integration/proxy" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="CountryProxyService" targetNamespace="http://www.tsretail.ru/integration/proxy">

  3.   <wsdl:types>

  4.     <xsd:schema targetNamespace="http://www.tsretail.ru/integration/proxy">

  5.       <xsd:element name="sendMessage">

  6.         <xsd:complexType>

  7.           <xsd:sequence>

  8.             <xsd:element name="country">

  9.                 <xsd:simpleType>

  10.                     <xsd:restriction base="xsd:string">

  11.                         <xsd:maxLength value="3"/>

  12.                     </xsd:restriction>

  13.                 </xsd:simpleType>

  14.             </xsd:element>

  15.             <xsd:element name="header" type="xsd:string"/>

  16.             <xsd:element name="body" type="xsd:string"/>          

  17.           </xsd:sequence>

  18.         </xsd:complexType>

  19.       </xsd:element>

  20.       <xsd:element name="sendMessageResponse">

  21.         <xsd:complexType>

  22.           <xsd:sequence>

  23.             <xsd:element name="result" type="xsd:string"/>

  24.           </xsd:sequence>

  25.         </xsd:complexType>

  26.       </xsd:element>

  27.     </xsd:schema>

  28.   </wsdl:types>

  29.   <wsdl:message name="sendMessageRequest">

  30.     <wsdl:part element="tns:sendMessage" name="parameters"/>

  31.   </wsdl:message>

  32.   <wsdl:message name="sendMessageResponse">

  33.     <wsdl:part element="tns:sendMessageResponse" name="parameters"/>

  34.   </wsdl:message>

  35.   <wsdl:portType name="CountryProxyService">

  36.     <wsdl:operation name="sendMessage">

  37.       <wsdl:input message="tns:sendMessageRequest"/>

  38.       <wsdl:output message="tns:sendMessageResponse"/>

  39.     </wsdl:operation>

  40.   </wsdl:portType>

  41.   <wsdl:binding name="CountryProxyServiceSOAP" type="tns:CountryProxyService">

  42.     <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

  43.     <wsdl:operation name="sendMessage">

  44.       <soap:operation soapAction="http://www.tsretail.ru/integration/proxy/sendMessage"/>

  45.       <wsdl:input>

  46.         <soap:body use="literal"/>

  47.       </wsdl:input>

  48.       <wsdl:output>

  49.         <soap:body use="literal"/>

  50.       </wsdl:output>

  51.     </wsdl:operation>

  52.   </wsdl:binding>

  53.   <wsdl:service name="CountryProxyService">

  54.     <wsdl:port binding="tns:CountryProxyServiceSOAP" name="CountryProxyServiceSOAP">

  55.       <soap:address location="http://www.tnsretail.ru"/>

  56.     </wsdl:port>

  57.   </wsdl:service>

  58. </wsdl:definitions>

  59.  



Теперь можно создать сам Proxy Service. После создания нужно задать тип сервиса - WSDL Web Service и указать в качестве используемого WSDL-описания созданный на предыдущем этапе файл CountryProxyService.wsdl.



На вкладке Message Flow настраивается поток обработки сообщений. Для динамической маршрутизации в поток необходимо добавить узел (Node) Route, в который в свою очередь - действие (Action) Dynamic Routing.



Настраиваются параметры динамической маршрутизации на вкладке Dynamic Routing в виде Properties. Данная вкладка содержит единственный параметр Service, в котором задаются выражения, описывающие как будет происходить маршрутизация.



Если нажать на ссылку, расположенную напротив параметра Service, то откроется окно редактирования этих выражений. Данное окно состоит из четырех вкладок:

  • Expression - позволяет задавать настройки, используя строковые константы и XQuery-выражения. Напоминает активность Assign в BPEL;

  • XQuery Resources - позволяет указать файл, содержащий XQuery-преобразования;

  • XSLT Resources - позволяет указать файл, содержащий XSLT-преобразования;

  • Dynamic XQuery - позволяет описать динамический XQuery-запрос и настроить связывание параметров запроса со значениями переменных.





Так как мы будем использовать довольно простое правило маршрутизации: путь к вызываемому Business Service определяется статическим префиксом CountryRouter/BusinessServices/BusinessService, к которому добавляется значение тега country из запроса, то проще всего воспользоваться непосредственным указанием выражения на вкладке Expression.

Выражение маршрутизации представлят собой XML, содержащий теги service - путь к вызываемому сервису и operation - наименование вызываемой операции. У тега service есть атрибут isProxy. Если вызываемый сервис является Proxy Service, то значение данного атрибута нужно установить в true, что позволит OSB оптимизировать такие запросы.

Текст в окне Expression интерпретируется как константа. Части текста, являющиеся XQuery-выражениями, необходимо заключать в фигурные скобки.

Описание используемого нами правила маршрутизации выглядит следующим образом:

  1. <ctx:route>

  2.     <ctx:service isProxy='false'>CountryRouter/BusinessServices/BusinessService{$body/prox:sendMessage/country}</ctx:service>

  3.     <ctx:operation>process</ctx:operation>

  4. </ctx:route>



Тестирование динамической маршрутизации


После создания необходимых Business Service'ы, Proxy Service и настройки правил маршрутизации проект следует развернуть на сервере OSB. После успешного завершения данной операции можно протестировать созданный Proxy Service.

Для этого необходимо воспользоваться консолью управления OSB. Все проекты, развернутые на сервере OSB, перечислены в списке Project Explorer.



Для тестирования Proxy Service необходимо перейти в каталог ProxyServices проекта CountryRouter. Доступные Proxy Service'ы будут перечислены в таблице Resources.



Для тестирования Proxy Service необходимо нажать на кнопку Launch Test Console. Появится окно, в котором необходимо ввести параметры тестового запроса.



Укажем в качестве значения тега country - Eng и нажмем кнопку Execute. После выполнения запроса, сопровождающегося отображением заставки Oracle Service Bus, появится окно с результатами.



Видно, что вызов завершился успешно и что в результате вернулось ENG.

В Enterprise Manager можно увидеть, что был создан новый экземпляр сервиса SomeServiceEng.



Теперь укажем в качестве значения тега country - Ru и нажмем кнопку Execute.



В качестве результата выполнения запроса вернется строка RU.



В Enterprise Manager можно увидеть, что был создан новый экземпляр сервиса SomeServiceRu.



Если в качестве значения тега country ввести значение, для которого нет соответствующего сервиса, например Fr, то будет сгенерировано сообщение об ошибке - Error preparing message for dispatch.



Следует отметить, что хотя сервисы SomeServiceEng и SomeServiceRu вызываются корректно, на них отправляется сообщение, описаное в WSDL Proxy Service, а не в схеме, по которой созданы данные сервисы. Т.е. вместо сообщения message, у которого country передается в атрибуте, отправляется сообщение sendMessage, у которого country передается в отдельном теге. Мы уже разбирались, что такие сообщения будут обрабатываться корректно до тех пор, пока в BPEL процессе не потребуется обратиться к значению атрибута country. Чтобы на сервисы SomeServiceEng и SomeServiceRu отправлялись сообщения в правильном для этих сервисов формате нам необходимо настроить трансформацию в потоке обработки сообщения CountryProxyService. Однако, это уже тема другого разговора.

Оставайтесь на связи.

Понравилось сообщение - подпишитесь на блог

5 комментариев:

Михаил комментирует...

Почему ругается в этой строке ?

CountryRouter/BusinessServices/BusinessService{$body/prox:sendMessage/country}

line 2, column 87: "prox": prefix not defined in static context

Unknown комментирует...

Вероятно потому что вы скопировали строчку $body/prox:sendMessage/country. Нужно или перетащить выражение с правой части редактора, или зайти на вкладку Namespaces свойств и зарегистрировать там пространство имен, указав ему префикc prox.

Михаил комментирует...

Проект собрался без ошибок. На тестовое собщение получаю такую ошибку (кусок ответа xml):

BEA-382612
Error preparing message for dispatch

RouteNode1
request-pipeline


Unknown комментирует...

Данная ошибка свидетельствует либо о неверно написанном выражении для маршрутизации, либо о том, что используемые в выражении переменные не инициализированы. Трудно что-то сказать сходу, может быть вы пришлете ваш проект, а я посмотрю?

Unknown комментирует...

Доброго времени суток. Я настроил сервисы передачи данных при помощи Oracle Service Bus consol. Файлы бегают между FTP серверами. Подскажите пожалуйста, как настроить, чтобы файлы передавались вместе с папками или чтобы забор файлов производился с переменного пути. Ну допустим использовал для сканирования папку формата DDMMYY, ориентируясь и выбирая наименование папки, относительно текущей даты. Заранее благодарю.

Отправить комментарий

Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!