Август 2005


Тема номера: Интеграция: различные аспекты, механизмы, инструменты


Матиас Джерик

Практическое введение в BPEL
(A Hands-on Introduction to BPEL, by Matjaz Juric)

Источник: сайт корпорации Oracle, раздел “Технологические статьи” (Technical Articles), тематический раздел "Developer: J2EE & Web Services”,
http://www.oracle.com/technology/pub/articles/matjaz_bpel1.html

Изучаем, как построить тестовый бизнес-процесс, который включает в себя набор условных туристических Web-сервисов, и как затем развернуть этот бизнес-процесс в среде выполнения Oracle BPEL Process Manager.

Business Process Execution Language for Web Services (BPEL или BPEL4WS – исполнительный язык бизнес-процессов на Web-сервисах) - это язык, используемый для определения и выполнения бизнес-процессов, использующих Web-сервисы. BPEL допускает нисходящую реализацию SOA (Service Oriented Architecture – сервис ориентированная архитектура) посредством построения, оркестровки и координации Web-сервисов. BPEL обеспечивает относительно простой и непосредственный способ для компановки отдельных Web-сервисов в новые комплексные сервисы, называемые бизнес- (деловыми) процессами (business processes).

Загрузите для этой статьи
Sample code
Oracle BPEL Process Manager & Designer

Из этой статьи вы узнаете, как построить учебный бизнес-процесс, который включает в себя условный набор Web-сервисов по организации перевозок, и как затем развернуть этот бизнес-процесс в среде выполнения Oracle BPEL Process Manager.

О BPEL в целом

Сначала несколько общих слов. BPEL построен на основе XML и Web-сервисов. Он использует язык, базируемый на XML, который поддерживает технологический стек Web-сервисов, включая SOAP, WSDL, UDDI, WS-Reliable Messaging (WS-надежная передача сообщений), WS-Addressing (WS-адресация), WS-Coordination (WS-координация) и WS-Transaction (WS-транзакция).

BPEL представляет конвергенцию (convergence) двух более ранних языков автоматизации документооборота (workflow); Язык потоков данных Услуг Web (WSFL) и XLANG. WSFL, разработанный IBM, был основан на концепции ориентированных графов. XLANG, блок-структурированный, был разработан Microsoft. BPEL объединяет оба подхода и обеспечивает богатый словарь для описания бизнес-процессов.

Первая версия BPEL была разработана в августе 2002. С тех пор много основных вендоров (включая Oracle) соединились в разработке модификаций и усовершенствований BPEL, что привело к принятию в марте 2003 версии 1.1. В апреле 2003 BPEL был представлен OASIS (Organization for the Advancement of Structured Information Standards - организация продвижения структурных информационных стандартов) с целью стандартизации, и был сформирован WSBPEL TC (Web Services Business Process Execution Language Technical Committee - технический комитет по исполнительному языку бизнес-процессов на Web-сервисах - WSBPEL TC). Это привело к еще более широкому применению его в промышленности.

На предприятии BPEL используется для стандартизации интеграции приложений предприятия, так как вовлекает в процессы интеграции ранее изолированные системы. Между предприятиями BPEL допускает простую и эффективную интеграцию с партнерами по бизнесу. BPEL стимулирует предприятия в плане дальнейшего определения их бизнес-процессов, что в свою очередь ведет к оптимизации бизнес-процессов, реинженирингу и выбору самых подходящих процессов, далее оптимизируя, таким образом, их организацию. Определения бизнес-процессов, описанных в BPEL, не затрагивают существующие системы, стимулируя, таким образом, обновления. BPEL – это ключевая технология в тех средах, где функциональные возможности (уже или будут) реализовываться через Web-сервисы. С расширением использования Web-сервисов будет также нарастать важность применения BPEL.

Оркестровка против Хореографии

Web-сервисы обычно выполняют операции неких приложений или информационных систем. Следовательно, объединение нескольких Web-сервисов фактически обеспечивает интеграцию основных приложений и их функциональных возможностей.

Web-сервисы могут быть объединены двумя способами:

  • оркестровка (Orchestration)
  • хореография (Choreography)

При оркестровке, которая обычно используется в конфиденциальных (private) бизнес-процессах, центральный процесс (которым может быть, другой Web-сервис) берет под свое управление и координирует выполнение Web-сервисами, участвующими в данной операции, различных действий. Привлекаемые Web-сервисы "не знают" (и не должны знать), что они вовлечены в состав некоего процесса и что они задействованы в бизнес- процессе высокого уровня. Только центральный координатор оркестровки в курсе этой цели, и поэтому оркестровка является централизованным механизмом с явным определением операций и порядком инициирование работы Web-сервисов. (См. рис. 1.)


Рисунок 1: Структура Web-сервисной оркестровки

В хореографии (сhoreography), напротив, нет центрального координатора. Скорее, каждый Web-сервис, задействованный в хореографии точно знает, когда выполнить ее операции и с кем взаимодействовать. Хореография представляет собой совместное действие, сфокусированное на обмене сообщениями в открытых (public) бизнес- процессах. Все участники хореографии должны знать бизнес-процесс, выполняемые операции, сообщения, которыми они обмениваются, и синхронизировать эти обмены сообщениями. (См. рис. 2.)


Рисунок 2: Структура Web-сервисной хореографии

Если смотреть с позиции перспективы построения Web-сервисов, реализующих бизнес-процессы, то оркестровка - более гибкая парадигма, она имеет следующие преимущества перед хореографией:

  • координация составляющих процессов централизованно осуществляется известным координатором.
  • Web-серсисы могут быть задействованы без ведома, что они были знают о своем участии в большем бизнес-процессе.
  • Если имеют место ошибки, могут быть задействованы альтернативные сценарии.

BPEL поддерживает два различных способа описания бизнес-процессов, которые поддерживают оркестровку и хореографию:

  • Выполнимые процессы (Executable processes) позволяют определять точную детализацию бизнес-процессов. Они находятся в парадигме оркестровки и могут быть выполнены механизмом оркестровки.
  • Абстрактные бизнес-протоколы (Abstract business protocols) допускают спецификацию общего обмена сообщения только между сторонами. Они не включают внутренние детали потока процессов и не являютмя выполнимыми. Они находятся в парадигме хореографии.

Теперь, давайте посмотрим на создание выполнимой BPEL-программы бизнес-процесса; код для нее может быть загружен и развернут в Oracle BPEL Process Manager. Мы предположим, что Oracle BPEL Process Manager был успешно установлен согласно инструкции по его инсталляции и что он использует заданный по умолчанию порт 9700. Если в течение инсталляции был выбран другой порт, соответственно должны измениться и наши примеры.

Формирование бизнес-процесса

BPEL-процесс определяет точный порядок, в котором должны быть вызваны - последовательно или параллельно - задействованные Web-сервисы. На BPEL можно выразить условные переходы. Например, обращение к Web-сервису может зависеть от значения предыдущего вызова. Можно также создавать циклы, объявлять переменные, копировать и назначить значения, определить обработчики ошибки и так далее. Комбинируя все эти конструкции, вы можете алгоритмическим образом определять сложные бизнес-процессы. Фактически, поскольку бизнес-процессы – это, по существу, графы действий, могло бы быть полезным выразить их в виде диаграмм активности (activity diagrams) UML (Unified Modeling Language - унифицированный язык моделирования).

В типичном случае BPEL-бизнес-процесс получает запрос. Чтобы его выполнить, процесс вызывает задействованные Web-сервисы и затем отвечает своему вызвавшему его абоненту. Поскольку BPEL-процесс связывается с другими Web-сервисами, то он в значительной степени полагается на WSDL-описание Web-сервисов, вызванных структурным Web-сервисом (WSDL - Web Services Description Language - язык описания Web-сервисов).

Давайте рассмотрим пример. BPEL-процесс состоит из шагов; каждый шаг является "activity" (активность, действие, функция). BPEL поддерживает как примитивные (primitive), как и структурные действия (structure activities). Примитивные действия представляют собой основные конструкции, которые используются для общих задач, как например, следующая:

  • Вызов других Web-сервисов, используя <invoke>
  • Ожидание клиента, чтобы вызвать бизнес-процесс посредством посылки сообщения, используя <receive> (получение запроса)
  • Генерация ответа для синхронных операций, используя <reply>
  • Управление переменными данных, используя <assign>
  • Индикация ошибок и исключений, используя <throw>
  • Ожидание в течение некоторого времени, используя <wait>
  • Завершение всего процесса, используя <terminate>

В этом случае мы можем комбинировать эти и другие примитивные действия, чтобы определить сложные алгоритмы, которые точно определяют шаги бизнес-процессов. Чтобы комбинировать примитивные действия, BPEL поддерживает несколько структурных действий. Наиболее важными являются:

  • Последовательность (<sequence>), которая позволяет нам определение набора действий, которые будут вызваны в упорядоченной последовательности ;
  • Поток (<flow>) для определения параллельно вызываемых набора действий;
  • Конструкция переключателя (<switch>) для определения ветвей (branch);
  • Пока (<while>) для определения циклов (loop);
  • Возможность выбора одного из нескольких альтернативных путей, используя <pick>.

Каждый BPEL-процесс также определяет партнерские связи, используя <partnerLink>, и декларирует переменные, используя <variable>.

Чтобы понять, как в BPEL описываются бизнес-процессы, определим упрощенный бизнес-процесс организации командировок служащих: клиент вызывает бизнес- процесс, определяет имя служащего, адресат, дату отъезда и дату возвращения. Бизнес-процесс BPEL, предполагая, что существует Web-сервис, посредством которого такие проверки могут быть сделаны, сперва проверяет командировочный статус служащего. Затем BPEL-процесс проверит цену билета на рейсы двух авиалиний: American Airlines и Delta Airlines. Опять же предположим, что обе авиакомпании обеспечивают Web-сервис, посредством которого такие проверки могут быть сделаны. Наконец, BPEL-процесс выберет рейс за более низкую цену и сообщит клиенту план командировки.

Далее мы сформируем асинхронный BPEL-процесс. Мы предполагаем, что Web-сервис “Обслуживание командированных служащих” синхронен. Это разумно, потому что такие данные должы быть получены и возвращены в вызывающую программу немедленно. А для того, чтобы узнать цену на самолетный билет, мы воспользуемся асинхронными вызовами. Это - опять же разумный подход, потому что может потребоваться немного больше времени, чтобы подобрать график движения самолетов. Чтобы упростить наш пример, предположим, что обе авиакомпании предлагают Web-сервисы и эти Web-сервисы идентичны (то есть, обеспечивают эквивалентные типы и операции перевозок).

В реальных сценариях обычно нет выбора конкретных Web-сервисов, а нужно пользоваться любыми услугами, которые предлагают ваши партнеры. Если предоставляется такая роскошная возможность, как одновременная разработка Web-сервисов и BPEL-процессов, то, естественно, хочется выяснить, какой интерфейс лучше. Обычно считается, что асинхронные сервисы надо использовать для длительных операций, а синхронные сервисы - для операций, которые должны предоставить результат в относительно короткое время. Если используются асинхронные Web-сервисы, то и BPEL-процесс также обычно является асинхронным.

Когда в BPEL определяется бизнес-процесс, то, по существу, определяется и новый Web-сервис, который является составным объектом из существующих сервисов. Интерфейс нового BPEL-составленного Web-сервиса использует набор типов портов, через которые он осуществляет операции, как и любой другой Web-сервис. Для того, чтобы вызывать бизнес-процесс, описанный BPEL, нужно вызвать результирующийся составной Web-сервис. Рисунок 3 показывает схематическое представление нашего процесса.


Рисунок 3: Пример BPEL-процесса для организации командировок

  • Хорошо ознакомиться с привлекаемыми Web-сервисами
  • Определить WSDL-описание BPEL-процесса
  • Определить типы партнерских связей
  • Разработать BPEL-процесс:
    • Определить партнерские связи
    • Декларировать переменные
    • Написать определение логики процесса.

Шаг 1: Инвентаризация привлекаемых Web-сервисов

Еще до начала написания определения BPEL-процесса, необходимо хорошо ознакомиться с Web-сервисами, участвующими в нашем бизнес-процессе. Эти сервисы называются partner Web services (партнерские Web-сервисы). Этот пример предполагает наличие имеющих идентичные WSDL-описания Web-сервисов Employee Travel Status (Обслуживание командированных служащих) в наборе Web-сервисов авиакомпаний, как American, так и Delta Airlines. (Напомним, что Web-сервисы, используемые в этом примере, являются вымышленными.)

Web-сервис “Обслуживание командированных служащих” (Employee Travel Status). Web-сервис "Обслуживание командированных служащих” предусматривает использование порта типа EmployeeTravelStatusPT, через который при помощи операции EmployeeTravelStatus может быть проверен статус командированного служащего. Операция возвратит транспортный класс, который дозволен служащему, а именно, эконом- , бизнес- или первый класс. (См. рисунок 4.)


Рисунок 4: Web-сервис “Обслуживание командированных служащих” (Employee Travel Status)

Web-сервис “Авиалиния” (Airline). Web-сервис “Авиалиния” является асинхронным; поэтому он определяет два типа портов: первый – это FlightAvailabilityPT, который использует операцию FlightAvailability, чтобы проверить наличие рейса. А для того, чтобы вернуть результат, Web-сервис определяет порт второго типа - FlightCallbackPT. Этот тип порта определяет операцию FlightTicketCallback.

Хотя Web-сервис “Авиалиния” определяет два типа портов, он реализует только FlightAvailabilityPT. FlightCallbackPT реализуется BPEL-процессом, который является клиентом этого Web-сервиса. Архитектура Web-сервиса схематично показана на рисунке 5.


Рисунок 5. Web-сервис “Авиалиния”

Шаг 2. Определение WSDL-описания BPEL-процесса

Далее мы должны представить на BPEL бизнес-командировку как Web-сервис. Поэтому второй шаг должен определить для него WSDL-описание. Процесс должен получать от своих клиентов сообщения и полученные результаты. Он должен показать порт типа TravelApprovalPT, который определяет входное сообщение. Он также должен объявить порт типа ClientCallbackPT, используемый для отправки результата клиенту (асинхронно, используя callback - возвращение). Этот процесс показан на рисунке 6.


Рисунок 6: WSDL-описание BPEL-процесса

Шаг 3. Определение партнерских связей

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

В нашем примере есть три различных партнера: клиент, Web-сервис “Обслуживание командированных служащих” и Web-сервис “Авиалиния”. Идеальный случай, когда каждый Web-сервис определяет соответствующие типы партнерских связей (в WSDL). (В реальной жизни этого может не быть.) Тогда мы можем свернуть (wrap) партнерский Web-сервис при помощи WSDL, что импортирует WSDL-описание Web-сервиса и определит типы партнерских связей. Альтернативно, мы можем определить все партнерские связи в WSDL-описании BPEL-процесса. Однако такой подход не рекомендуется, поскольку он нарушает принцип инкапсуляции (encapsulation).

В нашем примере мы определяем три типа партнерских связей, каждая в соответствущем WSDL-описании Web-сервиса:

  • travelLT: используется, чтобы описать взаимодействие между BPEL-процессом клиента и собственно BPEL-процессом. Это взаимодействие является асинхронным. Этот тип партнерской связи определяется в WSDL-описанием BPEL-процесса.
  • employeeLT: используется, чтобы описать взаимодействие между BPEL-процессом Web-сервисом “Обслуживание командированных служащих”. Это синхронное взаимодействие. Этот тип партнерской связи определен в WSDL-описании Web-сервиса служащего.
  • flightLT: описывает взаимодействие между BPEL-процессом и Web-сервисом “Авиалиния”. Это взаимодействие является асинхронным, и Web-сервис “Авиалиния” использует возврат (callback - обратный вызов) к BPEL-процессу. Этот тип партнерской связи определен в WSDL Web-сервиса “Авиалиния”.

Каждый тип партнерской связи может иметь одну или две роли, и для каждой роли мы должны определить portType, который ее использует. Для синхронных операций есть единственная роль для каждого типа партнерской связи, поскольку операция вызывается только в единственном смысле. Например, BPEL-процесс вызывает операцию EmployeeTravelStatus в Web-сервисе “Обслуживание командированных служащих”. Поскольку это являтся синхронным действием, BPEL-процесс ждет его завершения и получает ответ только после того, как операция закончилась.

Для асинхронных операций возращения, нужно определить две роли. Первая роль описывает вызов операции клиентом. Вторая роль описывает вызов возвращения (callback). В нашем примере есть асинхронное отношение между BPEL-процессом и Web-сервисом “Авиалиния”.

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

Типы партнерких связей определены в WSDL-описании в специальном пространстве имен (namespace): http://schemas.xmlsoap.org/ws/2003/05/partner-link/ . Давайте сначала определим тип связей travelLT в WSDL BPEL-процесса, используемой клиентами для вызова BPEL-процесса. Первая требуемая роль - роль бюро обслуживания (то есть, наш BPEL-процесс). Клиент использует тип порта TravelApprovalPT, чтобы связаться с BPEL-сервисом. Вторая роль, travelServiceCustomer, описывает клиента, которому BPEL-процесс вернет вызов по порту типа ClientCallbackPT:

<plnk:partnerLinkType name="travelLT">

  <plnk:role name="travelService">
    <plnk:portType name="tns:TravelApprovalPT" />
  </plnk:role>

  <plnk:role name="travelServiceCustomer">
    <plnk:portType name="tns:ClientCallbackPT" />
</plnk:role>

</plnk:partnerLinkType>

Второй тип связи - employeeLT. Она используется, чтобы описать связь между BPEL-процессом и Web-сервисом “Обслуживание командированных служащих”, и определяется в WSDL-описании Web-сервиса служащего. Взаимодействие синхронно, так что нам нужна единственная роль, названная employeeTravelStatusService. BPEL-процесс использует EmployeeTravelStatusPT в Web-сервисе служащего:

<plnk:partnerLinkType name="employeeLT">

  <plnk:role name="employeeTravelStatusService">
    <plnk:portType name="tns:EmployeeTravelStatusPT" />
</plnk:role>

</plnk:partnerLinkType>

Последний тип партнерской связи, flightLT, используется, чтобы описать связь между BPEL-процессом и Web-сервисом “Авиалиния”. Эта связь является асинхронной. BPEL-процесс вызывает асинхронную операцию с Web-сервисом “Авиалиния”. Web-сервис, завершив запрос, производит возврат к BPEL-процессу. Поэтому нам нужны две роли. Первая роль описывает участие Web-сервиса “Авиалиния” в BPEL-процессе, который предоставляет обслуживание авиалинией (airlineService). BPEL-процесс использует тип порта FlightAvailabilityPT, чтобы выполнить асинхронное обращение. Вторая роль описывает участие BPEL-процесса в Web-сервисе “Авиалиния”. Для Web-сервиса “Авиалиния” BPEL-процесс является клиентом авиалинии. Следовательно, роль имеет имя airlineCustomer. Web-сервис “Авиалиния” использует тип порта FlightCallbackPT, чтобы выполнить возврат. Этот тип партнерской связи определен в WSDL-описнии Web-сервиса “Авиалиния”:

<plnk:partnerLinkType name="flightLT">

  <plnk:role name="airlineService">
    <plnk:portType name="tns:FlightAvailabilityPT" />
  </plnk:role>

  <plnk:role name="airlineCustomer">
    <plnk:portType name="tns:FlightCallbackPT" />
  </plnk:role>

</plnk:partnerLinkType>

Понимание типов партнерских связей являются критическим для разработки спецификации BPEL-процесса. Иногда это помогает сделать диаграмму всех взаимодействий. Определением типов партнерских связей заканчивается стадия подготовки.

Шаг 4: Создание бизнес-процесса

Теперь вы готовы к тому, чтобы написать определение BPEL-процесса. Как правило, BPEL-процесс ждет входного сообщения от клиента, который начинает выполнение бизнес-процесса. В нашем примере клиент начинает BPEL-процесс с посылки входного сообщения: TravelRequest. Тогда BPEL-процесс вызывает Web-сервис “Обслуживание командированных служащих”, посылая сообщение EmployeeTravelStatusRequest. Поскольку это обращение синхронно, поцесс ждет сообщение EmployeeTravelStatusResponse. Тогда BPEL-процесс делает параллельное асинхронное обращение к обоим Web-сервисам “Авиалиния”, посылая им сообщение FlightTicketRequest. Каждый Web-сервис “Авиалиния” делает возврат, посылая сообщение TravelResponse. Тогда BPEL-процесс выбирает более приемлемую авиалинию и возвращает клиенту сообщение TravelResponse.

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

<process name="BusinessTravelProcess" ... >
   
   <partnerLinks>
      <! -- Определение партнерских связей -->
   </partnerLinks>

   <variables>
      <!-- Определение переменных -->
   </variables>

   <sequence>
      <!-- Определение основной части BPEL бизнес-процесса -->
   </sequence>

</process>

Сначала давайте добавим требуемые пространства имен (namespaces). Здесь нужно определить целевое (target) пространство имен и пространства имен (namespaces) для доступа к WSDL-описаниям “Служащего” (Employee), “Авиалинии” (Airline) и BPEL-процесса. Также нужно объявить пространство имен для всех BPEL-тэгов активности (здесь для пространство имен берется значение по умолчанию, так что не нужно квалифицировать каждое имя BPEL-тэга). Пространство имен BPEL-активности должно быть http://schemas.xmlsoap.org/ws/2003/03/business-process/:

<process name="BusinessTravelProcess" 
         targetNamespace="http://packtpub.com/bpel/travel/" 
         xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
         xmlns:trv="http://packtpub.com/bpel/travel/"
         xmlns:emp="http://packtpub.com/service/employee/"
         xmlns:aln="http://packtpub.com/service/airline/" >
...

Партнерские связи (Partner Links). Далее нужно определить partner links (партнерские связи), которые определяют различных участников, взаимодействующих в BPEL- процессе. Каждая партнерская связь соотносится с определенным partnerLinkType, который характеризует ее. Каждая партнерская связь также специфицирует один или два атрибута:

  • myRole: указывает роль собственно бизнес-процесса.
  • partnerRole: указывает роль партнера.

Партнерская связь может определить единственную роль, которая обычно имеет место в случае синхронных операций запрос/ответ. Для асинхронных операций связь определяет две роли. В нашем примере надо определить четыре роли. Первая партнерская связь называется клиентом и характеризуется типом партнерской связи travelLT. Клиент вызывает бизнес-процесс. Нужно определить, что атрибут myRole описывает роль BPEL-процесса (travelService). Нужно определить и вторую роль: partnerRole. Здесь это - travelServiceCustomer, который задает клиента BPEL-процесса.

Вторая партнерская связь называется employeeTravelStatus, она характеризуется типом партнерской связи employeeLT. Это - синхронное отношение запрос/ответ между BPEL-процессом и Web-сервисом; здесь снова определяется только одна роль. На сей раз это - partnerRole, потому что описывается роль Web-сервиса, который является партнером для BPEL-процесса.

Последние две партнерские связи сответствуют Web-сервисам авиалиний. Поскольку они используют тот же самый тип Web-сервиса, мы определяем две партнерские связи, основанные на едином типе партнерской связи, flightLT. Здесь имеется асинхронная возвратная (callback) связь, так что есть потребность в двух ролях. Роль BPEL-процесса (myRole) к Web-сервису “Авиалиния” - это airlineCustomer, тогда как роль авиалинии (partnerRole) - airlineService:

   <partnerLinks>
      <partnerLink name="client" 
                   partnerLinkType="trv:travelLT"
                   myRole="travelService"
                   partnerRole="travelServiceCustomer"/>

      <partnerLink name="employeeTravelStatus" 
                   partnerLinkType="emp:employeeLT"
                   partnerRole="employeeTravelStatusService"/>

      <partnerLink name="AmericanAirlines" 
                   partnerLinkType="aln:flightLT"
                   myRole="airlineCustomer"
                   partnerRole="airlineService"/>
                   
      <partnerLink name="DeltaAirlines" 
                   partnerLinkType="aln:flightLT"
                   myRole="airlineCustomer"
                   partnerRole="airlineService"/>
   </partnerLinks>

Переменные (Variables). Переменные в BPEL-процессах используются, чтобы хранить, повторно форматировать и преобразовывать сообщения. Обычно для каждого сообщения, посланного партнерам и принятого от них, требуется переменная. В нашем процессе нужно семь переменных. Давайте назовем их TravelRequest, EmployeeTravelStatusRequest, EmployeeTravelStatusResponse, FlightDetails, FlightResponseAA, FlightResponseDA и TravelResponse.

Для каждой переменной требуется определить ее тип. Можно воспользоваться типом сообщений WSDL, простым тип XML Schema, а также элементом XML Schema. В нашем примере использованы для всех переменных типы WSDL-сообщений:

   <variables>
      <!-- input for this process -->      
      <variable name="TravelRequest" 
                messageType="trv:TravelRequestMessage"/>
      <!-- input for the Employee Travel Status Web service -->
      <variable name="EmployeeTravelStatusRequest" 
                messageType="emp:EmployeeTravelStatusRequestMessage"/>
      <!-- output from the Employee Travel Status Web service -->
      <variable name="EmployeeTravelStatusResponse" 
                messageType="emp:EmployeeTravelStatusResponseMessage"/>
      <!-- input for American and Delta Web services -->
      <variable name="FlightDetails" 
                messageType="aln:FlightTicketRequestMessage"/>
      <!-- output from American Airlines -->
      <variable name="FlightResponseAA" 
                messageType="aln:TravelResponseMessage"/>
      <!-- output from Delta Airlines -->
      <variable name="FlightResponseDA" 
                messageType="aln:TravelResponseMessage"/>
      <!-- output from BPEL process -->
      <variable name="TravelResponse" 
                messageType="aln:TravelResponseMessage"/>
   </variables>

Основная часть BPEL-процесса (BPEL Process Main Body). Основная часть процесса определяет порядок, в котором вызываются партнерские Web-сервисы. Обычно старт начинается с <sequence>, которая определяет несколько действий, которые будут выполнены последовательно. В этой последовательности надо сначала определит входное сообщение, которое запускает бизнес-процесс. Это делается с помощью конструкции <receive>, которая ждет соответствующего сообщения, в нашем случае – это сообщение TravelRequest. В конструкции <receive> нельзя непосредственно определить сообщение. Скорее, мы определяем партнерскую связь, тип порта, имя операции и, возможно, переменную, которая соотносится с полученным сообщение для проведения последовательных действий.

Мы по получении сообщения связываемся с клиентом партнера и ждем выполнения операции TravelApproval, которая будет вызвана по типу порта TravelApprovalPT. Мы храним полученное сообщение в переменной TravelRequest:

<sequence>

      <!—Получение от клиента начального сообщения о командировке  -->
      <receive partnerLink="client" 
               portType="trv:TravelApprovalPT" 
               operation="TravelApproval" 
               variable="TravelRequest"
               createInstance="yes" />
...

<receive> ждет клиента, чтобы вызвать операцию TravelApproval и хранит поступающее сообщение и данные о командировке в переменной TravelRequest. Здесь имя переменной то же самое, что и имя сообщения, но это не необходимо.

Далее надо вызвать Web-сервис “Обслуживание командированных служащих”. Однако, перед этим мы должны подготовить вход для этого Web-сервиса. Посмотрим на WSDL-описание и увидим, что нужно послать сообщение, которое содержит часть сведений о служащем. Поэтому можно построить такое сообщение, копируя часть сведений о служащем из сообщения, которое прислал клиент. В результате будет написано соответствующее назначение:

...
      <!-- Prepare the input for the Employee Travel Status Web Service -->
      <assign>
        <copy>
          <from variable="TravelRequest" part="employee"/>
          <to variable="EmployeeTravelStatusRequest" part="employee"/>
        </copy>
      </assign>
...

Теперь можно вызвать Web-сервис “Обслуживание командированных служащих”. Мы производим синхронное обращение, для которого используется активность (activity) <invoke>. Применяется партнерская связь employeeTravelStatus и вызывается операция EmployeeTravelStatus типу порта EmployeeTravelStatusPT. Вы подготовили входное сообщение в переменной EmployeeTravelStatusRequest. Поскольку это - синхронное обращение, то запрос ждет ответа и хранит его в переменной EmployeeTravelStatusResponse:

...
      <!-- Synchronously invoke the Employee Travel Status Web Service -->
      <invoke partnerLink="employeeTravelStatus" 
              portType="emp:EmployeeTravelStatusPT" 
              operation="EmployeeTravelStatus"
              inputVariable="EmployeeTravelStatusRequest" 
              outputVariable="EmployeeTravelStatusResponse" />
...

Следующий шаг должен вызвать Web-сервисы обеих авиалиний. Снова сначала подготовим требуемое входное сообщение (которое является идентичным для обоих Web-сервисов). Сообщение FlightTicketRequest состоит из двух частей:

  • flightData: Эта часть взята из сообщения от клиента (TravelRequest).
  • travelClass: Эта часть взята из переменной EmployeeTravelStatusResponse.

Поэтому напишем назначение с двумя скопированными элементами:

...
      <!-- Prepare the input for AA and DA -->
      <assign>
        <copy>
          <from variable="TravelRequest" part="flightData"/>
          <to variable="FlightDetails" part="flightData"/>
        </copy>
        <copy>
          <from variable="EmployeeTravelStatusResponse" part="travelClass"/>
          <to variable="FlightDetails" part="travelClass"/>
        </copy>
      </assign>
...

Входные данные включают сведения, которые нужно Web-сервисам авиакомпаний. Поскольку они заданы в одном и том же формате, их можно передать непосредственно (используя простую копию). В реальном же мире обычно нужно выполнить преобразование. Это можно было бы сделать, или использовав XPath с выражением <assign>, или использовав сервис преобразования (типа механизма XSLT), или использовав возможность преобразования, обеспеченную определенными BPEL- серверами.

Теперь мы готовы вызвать Web-сервисы обеих авиалиний. Сделаем параллельные асинхронные обращения; для выражения параллелизма в BPEL применяется активность <flow>. Обращение к каждому Web-сервису осуществляется в два шага:

  • Активность <invoke> используется при асинхронных обращених.
  • Активность <receive> используется для ожидания возврата (callback).

Надо использовать <sequence>, чтобы сгруппировать оба действия. Эти два обращения отличаются только по имени партнерской связи: AmericanAirlines - для одной и DeltaAirlines - для другой. Обе вызывают операцию FlightAvailability по типу порта FlightAvailabilityPT, посылая сообщение из переменной FlightDetails.

Возврат осуществляется с использованием активности <receive>. Снова используются оба имени партнерских связей. <receive> ждет операцию FlightTicketCallback, которая вызывается по типу порта FlightCallbackPT. Результируюшие сообщения будут сохранены в переменных FlightResponseAA и FlightResponseDA, соответственно:

...
      <!-- Сделать параллельное обращение к AA и DA -->
      <flow>
      
        <sequence>
          <! --Асинхронный вызов Web-сервиса от AA Web и ожидание возврата -->
        
          <invoke partnerLink="AmericanAirlines" 
              portType="aln:FlightAvailabilityPT" 
              operation="FlightAvailability"
              inputVariable="FlightDetails" />

          <receive partnerLink="AmericanAirlines" 
              portType="aln:FlightCallbackPT" 
              operation="FlightTicketCallback"
              variable="FlightResponseAA" />

        </sequence>

        <sequence>
          <!-- Асинхронный вызов Web-сервиса от DA Web и ожидание возврата -->
        
          <invoke partnerLink="DeltaAirlines" 
              portType="aln:FlightAvailabilityPT" 
              operation="FlightAvailability"
              inputVariable="FlightDetails" />

          <receive partnerLink="DeltaAirlines" 
              portType="aln:FlightCallbackPT" 
              operation="FlightTicketCallback"
              variable="FlightResponseDA" />

        </sequence>

      </flow>
...

На этой стадии процесса имеется два заявленных предложения. В следующем шаге нужно будет выбрать одно из них. Чтобы сделать это, используем активность <switch>.

...
      <!-- Выбор лучшего варианта и построение TravelResponse -->
      <switch>
              
        <case condition="bpws:getVariableData('FlightResponseAA',
                         'confirmationData','/confirmationData/Price') 
                   <= bpws:getVariableData('FlightResponseDA',
                         'confirmationData','/confirmationData/Price')">
                    
           <!-- Вариант от American Airlines -->
           <assign>
             <copy>

               <from variable="FlightResponseAA" />
               <to variable="TravelResponse" />
             </copy>
           </assign>
        </case>
                    
        <otherwise>
           <!-- Вариант Delta Airlines -->
           <assign>
             <copy>
               <from variable="FlightResponseDA" />
               <to variable="TravelResponse" />
             </copy>
           </assign>
        </otherwise>
      </switch>
...

В элементе <case> производится провера, одинаково ли предложение от American Airlines (FlightResponseAA) или оно лучше, чем предложение от Delta Airlines (FlightResponseDA). Используем BPEL-функцию getVariableData и определим имя переменной для этой цели. Цена билета нахолдится в разделе confirmationData сообщения, который является единственной частью сообщения, но это все же требуется определить. Также нужно определить выражение вопроса, чтобы задать местонахождение элемента цены. Здесь это делается простым выражением XPath 1.0.

Если предложение от American Airlines лучше чем от Delta, копия переменной FlightResponseAA помещается в переменную TravelResponse (которая, наконец-то, возвращается клиенту). Иначе копируется переменная FlightResponseDA.

Итак, мы прибыли на заключительный шаг бизнес-процесса BPEL – возвращение сведений (callback) клиенту, используя активность <invoke>. Для этого мы используем клиентскую партнерскую связь и вызовем операцию ClientCallback по типу порта ClientCallbackPT. TravelResponse – это переменная, которая содержит сообщение ответа:

...
      <!-- Make a callback to the client -->
      <invoke partnerLink="client" 
              portType="trv:ClientCallbackPT" 
              operation="ClientCallback"
              inputVariable="TravelResponse" />
   </sequence>
</process>

Следующие шаги

Скачайте доступную главу “Oracle BPEL Process Manager” из моей с соавторами книги “Business Process Execution Language for Web Services

Посетите сайт Центра WEB-сервисных технологий Visit the Web Services Technology Center

На этом месте мы закончили нашу первую спецификацию бизнес-процесса на BPEL. Вы увидили, что BPEL очень не сложен и позволяет относительно легко и естественно специфицировать бизнес-процессы.

Шаг 5: Развертывание и тестирование

Каждый BPEL-процесс, который развертывается в среде Oracle BPEL Process Manager, требует описателя процесса (process descriptor). Этот описатель процесса не охвачен BPEL-стандартом и специфичен по отношению к BPEL-серверу. Разработка описателя процесса – это единственная часть реализации процесса, которая должна быть переписана на данной платформе, чтобы сделать управление процессом возможным на различных механизмах BPEL. Описатель Oracle-процесса представляет собой XML-файл, специфицирующий следующие детали о BPEL-процессе: имя исходного BPEL-файла, BPEL-название (ID) процесса, WSDL-описание локализирует все партнерские связи Web-сервисов, а также дополнительные особенности конфигурации. По умолчанию имя файла описателя процесса - bpel.xml, но можно использовать любое другое имя:

<BPELSuitcase>

  <BPELProcess src="Travel.bpel" id="TravelProcessCh4">
    <partnerLinkBindings>

      <partnerLinkBinding name="client">
        <property name="wsdlLocation">
          Travel.wsdl
        </property>
      </partnerLinkBinding>

      <partnerLinkBinding name="employeeTravelStatus">
        <property name="wsdlLocation">
          http://localhost:9700/orabpel/default/Employee/Employee?wsdl
        </property>
      </partnerLinkBinding>

      <partnerLinkBinding name="AmericanAirlines">
        <property name="wsdlLocation">
    http://localhost:9700/orabpel/default/AmericanAirline/AmericanAirline?wsdl
        </property>
      </partnerLinkBinding>

      <partnerLinkBinding name="DeltaAirlines">
        <property name="wsdlLocation">
          http://localhost:9700/orabpel/default/DeltaAirline/DeltaAirline?wsdl
        </property>
      </partnerLinkBinding>

    </partnerLinkBindings>
  </BPELProcess>
</BPELSuitcase>

Теперь пришло время старта BPEL Process Manager. Это можно сделать из Start-меню (если используется Windows) или выполнить скрипт startOraBPEL, который находится в директории c:\orabpel\bin (при условии, что Oracle BPEL Process Manager был установлен в c:\orabpel). Рекомендуется, чтобы эта директория была включена в путь доступа для облегчения действий.

Oracle BPEL Process Manager включает утилиту Ant, названную obant, который Вы можете использовать для конфигурирования сложной компиляции и сценариев развертывания. Obant представляет собой только свертку стандартной утилиты Ant Муравья, которая выстраивает окружающую среду, а затем вызывает стандартную Java-задачу Ant. Для того, чтобы ее задействовать, надо подготовить соответствующий проектный файл, обычно называемый build.xml. Такой проектный файл для нашего процесса обслуживания командировок похож на следующее:

<?xml version="1.0"?>
<project name="TravelProcessCh4" default="main" basedir=".">

    <property name="deploy" value="default"/>
    <property name="rev" value="1.0"/>
       
    <target name="main">
        <bpelc home="${home}" rev="${rev}" deploy="${deploy}"/>        
    </target>    

</project>

Для того, чтобы скомпилировать и развернуть наш BPEL-процесс, надо просто стартовать obant из командной строки.

Далее, если BPEL-процесс успешно развернут в среде Oracle BPEL Process Manager, наступает время выполнять его. Oracle BPEL Process Manager предоставляет BPEL-консоль, посредством которой можно выполнять, контролировать, управлять и производить отладку BPEL-процессов в домене BPEL Server. BPEL-консоль доступна по адресу http://localhost:9700/BPELConsole/. Нужно щелкнуть по имени процесса, заполнить следующую форму и щелкнуть по кнопке Post XML Message:


Рисунок 7: BPEL-консоль

Появляется экран, уведомляющий, что экземпляр (instance) процесса выполняется асинхронно. Можно выбрать визуальное отображение выполнения потока, аудит (auditing) или отладку (debugging) экземпляра, или случая. Визуальное отображение потока экземпляра графически показывает, как выполняется экземпляр BPEL-процесса. Вы можете контролировать выполнение и состояние процесса (функционирование (running), завершение (completed), прекращение (canceled) или потеря актуальности (stale)):


Рисунок 8: Графическое представление потока экземпляра

Заключение

Теперь, когда вы познакомились с основными понятиями соединения Web-серверов с BPEL, можно более глубоко покопаться в более продвинутых случаях. В моей следующей статье, я расскажу о продвинутых возможностях BPEL, как-то: обработка ошибок, области действия, коррекция, параллельные действия и обработка событий.

Часть 2: Продвинутый BPEL

[От редакции OM/RE: перевод второй части статьи Matjaz B. Juric предполагается опубликовать в следующем выпуске нашего журнала.]

Матиас B. Джерик (Matjaz B. Juric) - доктор философии по компьютерным наукам и информатике. Он - автор книги Business Process Execution Language for Web Services (Packt Publishing). Он также является соавтором Professional J2EE EAI, Professional EJB, J2EE Design Patterns Applied, and VB.NET Serialization Handbook (издательство Wrox Press). Матиас активно участвует в Java Developer's Journal, Java Report, Java World и другие изданиях.

E-mail this page