Как я упоминал в предыдущих статьях и статьях , одной из сильных сторон платформы JBoss SOA является большое количество поддерживаемых интеграций. Некоторые из этих интеграций принимают форму поддержки JBoss и сторонних поставщиков JMS и UDDI или поддержки нескольких JDK и баз данных. Платформа SOA также поддерживает интеграцию с jBPM для управления бизнес-процессами и JBDS для разработки приложений.
В этой статье я хочу взглянуть на интеграцию платформы SOA с правилами JBoss. В предыдущем посте в блоге я обсуждал использование правил для реализации маршрутизации на основе контента через JBossESB. В этом посте мы рассмотрим еще один аспект интеграции JBossESB-Rules; создание сервисов на основе правил.
Прежде чем мы подробно рассмотрим эту интеграцию, давайте кратко рассмотрим правила JBoss.
Слюни и правила
JBoss Rules в комплекте с платформой SOA — это коммерческая версия проекта с открытым исходным кодом «Drools». (Вы можете узнать больше о Drools на веб-сайте проекта здесь: http://www.jboss.org/drools/ ) Drools — это унифицированное и интегрированное решение для бизнес-правил, управления бизнес-процессами и обработки событий. Проект Drools состоит из нескольких подпроектов. Когда мы ссылаемся на правила JBoss в платформе SOA, мы говорим о субпроекте Drools «Эксперт». Этот подпроект состоит из API правил, механизма правил и инструментов редактирования и отладки правил.
Основанное на правилах программирование, как следует из его названия, построено на способности определять точки принятия решений и отделять их от другой логики программы. Хорошо, звучит интересно, но зачем мне это использовать? Другими словами, в чем дело? Вот две причины, почему это важно:
- Во-первых, это позволяет отделить бизнес-логику вашего приложения и обработку точек принятия решения от кода приложения. Это означает, что ваши специалисты по бизнес-процессам могут сосредоточиться на правилах бизнес-логики, а ваши программисты — на коде приложения. Это делает разработку и обслуживание приложений проще и эффективнее.
- Во-вторых, и не воспринимайте это как личную критику ваших навыков программирования или моих, но поскольку механизм правил разработан и оптимизирован для обработки правил, он более эффективен, чем любое массивное утверждение «если-то-еще», которое вы можете написать , Таким образом, производительность вашего приложения может быть улучшена. Движок JBoss Rules использует алгоритм Rete http://en.wikipedia.org/wiki/Rete_algorithm для эффективной обработки правил.
Когда вы определяете правило, вы следуете не «если-то-еще», а «когда» и «тогда». Две конструкции, которые вы используете в правиле:
- Условие — это левая часть правила и охватывает аспекты правила «когда».
- Следствие — это правая часть правила и охватывает «тогда» аспекты правила.
Правила написаны на языке правил Drools (drl). Этот язык может быть расширен до предметно-ориентированного языка (dsl) для поддержки требований, специфичных для приложения, таких как медицинские или финансовые процедуры и терминология.
Общий шаблон для правила:
rule “a simple rule”
when (LHS)
you need a rules-based app
then (RHS)
build it with JBoss Rules
Как правило получает доступ к информации? Через рабочую память Правил. Информация, которую правила выполняют операции, принимает форму Java-бинов, которые называются «фактами». (Доступ к элементам этих фактов осуществляется через методы получения и установки.) Что происходит, когда факты вставляются в рабочую память, обновляются в рабочей памяти или удаляются из рабочей памяти, эти изменения фактов в рабочей памяти могут вызывать правила «когда» условия должны быть истинными и правила должны быть выполнены.
Важно отметить, что в отличие от процедурного программирования, изменения фактов могут привести к тому, что более одного правила могут прийти к истинным выводам и быть доступными для одновременного выполнения. Что происходит потом? Что ж, вместо жесткого кодирования последовательности правил механизм правил добавляет каждое соответствующее правило в свою «повестку дня» правил, которые должны быть выполнены. Если повестка дня включает в себя более одного правила, механизм правил выполняет разрешение конфликтов для правил и определяет последовательность, в которой должны выполняться правила. Это разрешение конфликтов основано на значимости правил (вы определяете это как свойство при написании правил), как часто правило срабатывает в прошлом, сложность (чем сложнее правило, тем более вероятно, что механизм правил его будет учитывать применить к текущей ситуации) и порядок загрузки правил.
Правила вызова из службы JBossESB на платформе SOA
Правила — интеграция JBossESB в платформу SOA позволяет получить доступ к правилам из действий службы. Это поддерживается классами действий org.jboss.soa.esb.actions.BusinessRuleProcessor и org.jboss.soa.esb.actions.DroolsRuleService.
Класс BusinessRuleProcessor использует правила, загруженные из файлов правил. Как правило, этот класс используется для простых служб правил, поскольку загрузка большого количества правил из большого количества файлов правил затруднительна и неэффективна.
Для производственных сред, где у вас будут сложные сервисы правил, которые работают с сотнями или даже тысячами правил, лучше использовать DroolsRuleService. Эта служба использует RuleAgent для доступа к пакетам правил из файлов или из системы управления бизнес-правилами (BRMS).
Платформа JBoss BRMS ( http://www.jboss.com/products/platforms/brms/ ) объединяет центральное хранилище для правил с веб-интерфейсом создания правил и управлением правилами, которое обеспечивает импорт / экспорт / архивирование, контрольный журнал или изменения, журнал ошибок, автоматизированная разработка и выполнение тестов, анализ правил, отслеживание состояния и контроль версий. Разработка правил BRMS Platform «управляемый редактор» позволяет непрограммистам легче создавать правила, а платформа облегчает администраторам правил возможность поддерживать большое количество правил и контролировать их разработку и использование пользователями.
Вот скриншот:
Платформа SOA поддерживает службы правил, которые не имеют состояния или сохраняют состояние. В модели без сохранения состояния сообщения, отправляемые сервисам, содержат все факты, которые необходимо вставить в рабочую память механизма правил перед выполнением правил. В модели с состоянием, где выполнение правил может происходить в сеансе в течение длительного периода времени, несколько сообщений могут отправляться в службу правил, и правила могут запускать и обновлять либо сообщение, либо факты до окончательного сообщения. заставляет сервис завершать сеанс. Лучший способ объяснить и проиллюстрировать Правила — интеграция JBossESB в платформу SOA — это одна из примеров программ «быстрого запуска» платформы. Давайте взглянем.
Правила Службы в Действии — Быстрый Старт
Я не устаю говорить, что одной из замечательных особенностей платформы SOA является ее обширный и постоянно растущий набор программ «быстрого запуска». Эти программы выходят далеко за рамки простых примеров, поскольку они ясно иллюстрируют различные функции, поддерживаемые платформой. Они также служат отличным ресурсом для написания ваших собственных приложений. В нашем примере мы рассмотрим краткий старт «business_rules_service». Прежде чем мы пройдемся по настройке и выполнению быстрого запуска, давайте взглянем на его (3) файлы правил. Важно отметить, что правила на самом деле используются несколькими способами в этом кратком обзоре, поскольку он имитирует покупателя, совершающего покупку на сайте электронной коммерции. Быстрый старт использует Правила для:
- Рассчитать приоритет входящего заказа клиента
- Рассчитать скидку, которая будет применена к заказу
- И направить заказ на соответствующую услугу, исходя из содержания заказа
Также важно отметить, что быстрый старт иллюстрирует, как можно изменить сообщение, когда оно обрабатывается с помощью конвейера действий JBossESB платформы SOA. Начнем с файла «MyBusinessRules.drl», так как он устанавливает приоритет заказа. (Ой, подождите. Здесь мы немного прыгнем вперед и объясним, что по умолчанию каждый входящий ордер имеет значение приоритета «1».)
package com.jboss.soa.esb.routing.cbr
#list any import classes here.
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.format.MessageType;
import org.jboss.soa.esb.samples.quickstart.businessrules.dvdstore.OrderHeader;
import org.jboss.soa.esb.samples.quickstart.businessrules.dvdstore.Customer;
global java.util.List destinations;
rule "Logging"
when
order: OrderHeader()
customer: Customer()
then
System.out.println("Customer Status: " + customer.getStatus());
System.out.println("Order Total: " + order.getTotalAmount());
end
rule "Customer Platinum Status"
when
customer: Customer(status > 50)
order: OrderHeader(totalAmount > 50)
then
System.out.println("Platinum Customer - High Priority");
order.setOrderPriority(3);
end
rule "Customer Gold Status"
when
customer: Customer(status > 10, status <= 50)
order: OrderHeader(totalAmount > 25)
then
System.out.println("Gold Customer - Medium Priority ");
order.setOrderPriority(2);
end
Давайте посмотрим на этот файл правил построчно:
- Строка 1 — Подобно Java, пакет представляет собой связанный набор правил.
- Строки 4-7 — Эти операции импорта выполняют ту же функцию, что и импорт языка Java. Обратите внимание, что мы импортируем как пакеты, связанные с сообщениями платформы SOA, так и пакеты, содержащиеся в самом быстром запуске.
- Строка 9 — Запомните это глобальное определение, так как оно будет использоваться другими файлами правил и быстрым стартом для маршрутизации на основе контента.
- Строка 13-14 — название первого правила и начало его предложения «когда».
- Строка 15 — при этом создается переменная правила с именем «order» и инициализируется значением факта OrderHeader (org.jboss.soa.esb.samples.quickstart.businessrules.dvdstore.OrderHeader), который представляется в правиле.
- Строка 16 делает то же самое для переменной Rule с именем customer и фактом Customer. Обратите внимание, что в этих назначениях нет ничего условного. Правило будет соответствовать каждому OrderHeader и Клиенту. Это сопоставление на самом деле является важной концепцией, которую необходимо учитывать как часть каждого предложения «когда» включает попытку сопоставления фактов, переданных в правила.
- Строка 20 — Правило всегда должно иметь конечный оператор.
- Строка 22 — Это правило устанавливает статус для клиентов с наивысшим приоритетом («Platinum»).
- Строка 24-25. Обратите внимание на различия в этих операторах по сравнению со строками 15 и 16. Правило будет выполнено только в том случае, если:
- Строка 24 — статус клиента больше 50. Если это не так, то переменная клиента, которую мы установили в строке 16, не будет изменена, и
- Строка 25 — Общая сумма заказа также превышает 50. Если это не так, то переменная заказа, которую мы установили в строке 15, не будет изменена.
- Строка 28 — Помните, как я сказал, что приоритет по умолчанию для каждого заказа был установлен на «1». Вот где мы устанавливаем приоритет. Обратите внимание, что мы устанавливаем значение в переменной правила «order».
- Строки 31-38 — это правило устанавливает статус для клиентов 2-го наивысшего приоритета («золото»). В этом правиле интересна строка 33, так как она включает два критерия, которые должны быть соблюдены, чтобы факт соответствовал правилу.
Следующий файл правил, на который мы посмотрим, обнаружит, где остановился MyBusinessRules.drl. Этот файл правил называется: MyBusinessRulesDiscount.drl
package com.jboss.soa.esb.routing.cbr
#list any import classes here.
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.samples.quickstart.businessrules.dvdstore.OrderHeader;
import org.jboss.soa.esb.samples.quickstart.businessrules.dvdstore.Customer;
global java.util.List destinations;
rule "Logging"
salience 10
when
order: OrderHeader()
customer: Customer()
then
System.out.println("Customer Status: " + customer.getStatus());
System.out.println("Order Total: " + order.getTotalAmount());
end
rule "Customer Platinum Status"
salience 20
when
customer: Customer(status > 50)
order: OrderHeader(orderPriority == 3)
then
System.out.println("Platinum Customer - High Priority - Higher discount");
order.setOrderDiscount(8.5);
end
rule "Customer Gold Status"
salience 20
when
customer: Customer(status > 10, status <= 50)
order: OrderHeader(orderPriority == 2)
then
System.out.println("Gold Customer - Medium Priority - discount ");
order.setOrderDiscount(3.4);
end
- Строки 1-8 и правило «Ведение журнала» должны выглядеть знакомо, поэтому давайте перейдем к другим правилам, определенным в этом файле.
- Строка 13 — Помните, как мы говорили о том, как правила не выполняются в той последовательности, в которой их можно просматривать в файле правил .drl? Этому правилу присваивается значение свойства значимости 10. Поскольку это правило выводит только некоторые данные журнала, ему назначается более низкий уровень значимости, чем другим правилам, определенным в файле.
- Строка 22 — Это правило устанавливает уровень скидки для клиентов самого высокого класса.
- Строка 23 — И, так как мы хотим быть уверены, что это правило срабатывает, мы присваиваем ему значение свойства значимости 20.
- Строки 25-26. Это условие «когда» имеет значение «истина», когда правило способно сопоставить как факт Customer со статусом больше 50, так и факт OrderHeader с orderPriority, равным 3. Если оба эти условия выполняются, то правило переменные customer и order инициализируются из фактов Customer и и OrderHeader, и правило запускается.
- Строка 29 — обратите внимание, что при запуске правила метод setOrderDiscount выполняется для переменной правила «order». Тот же метод установки выполняется для факта OrderHeader в рабочей памяти. (Помните, как мы говорили о том, как правила могут как реагировать на изменения фактов в рабочей памяти, так и вызывать изменения этих фактов? Это пример.) Для клиентов класса «Платина» мы назначаем щедрую скидку.
- Строки 32-40 — это правило следует той же схеме, что и правило «Платиновый статус клиента». Обратите внимание, что мы даем «Золотому» классу покупателей несколько менее щедрую скидку. ?
Третий и последний файл правил, используемый быстрым стартом, управляет маршрутизацией на основе содержимого, используемой быстрым стартом для маршрутизации сообщений в службы. В платформе SOA Правила являются одним из поддерживаемых механизмов реализации маршрутизации на основе контента. В отличие от более статических подходов к маршрутизации, эта форма маршрутизации сообщений основана на содержании сообщений, определяющем маршрут, по которому будет проходить сообщение. (Информацию о маршрутизации на основе контента см. В этом блоге: http://jboss-soa-p.blogspot.com/2009/07/when-content-knows-way-content-based.html ).
Этот файл правил имеет правильное имя: MyRoutingRules.drl
package com.jboss.soa.esb.routing.cbr
#list any import classes here.
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.format.MessageType;
import org.jboss.soa.esb.samples.quickstart.businessrules.dvdstore.OrderHeader;
#declare any global variables here
global java.util.List destinations;
rule "Highest Priority Orders"
when
OrderHeader( orderPriority == 3 )
then
System.out.println("HIGHEST PRIORITY");
destinations.add("SuperSpecialCustomerService");
end
rule "Medium Priority Orders"
when
OrderHeader( orderPriority == 2 )
then
System.out.println("Medium Priority");
destinations.add("SpecialCustomerService");
end
rule "Low Priority Orders"
when
OrderHeader( orderPriority == 1 )
then
System.out.println("Low Priority");
destinations.add("RegularCustomerService");
end
- Строки 1-6. Еще раз, эти строки импорта должны выглядеть знакомо.
- Строка 9 — Запишите список адресатов. Мы увидим, что это используется, когда сообщения маршрутизируются.
- Правила в этом файле правил довольно просты. В каждое из трех правил мы добавляем соответствующий пункт назначения на основе orderPriority в OrderHeader, где этот пункт назначения является службой, которую быстрый запуск развертывает в JBossESB в платформе SOA.
ОК, это те правила, которые мы будем использовать в кратком обзоре. Давайте теперь рассмотрим быстрый старт по мере его запуска.
Чтобы развернуть быстрый запуск, выполните эту цель муравья:
ant deploy
И затем мы видим это записано в журнал сервера:
22:20:57,568 INFO [QueueService] Queue[/queue/quickstart_Business_Rules_Request_GW] started, fullSize=200000, pageSize=2000, downCacheSize=2000
22:20:57,580 INFO [QueueService] Queue[/queue/quickstart_Business_Rules_Request_ESB] started, fullSize=200000, pageSize=2000, downCacheSize=2000
22:20:57,621 INFO [QueueService] Queue[/queue/quickstart_Business_Rules_ConciergeManager] started, fullSize=200000, pageSize=2000, downCacheSize=2000
22:20:57,632 INFO [QueueService] Queue[/queue/quickstart_Business_Rules_DistributionManager] started, fullSize=200000, pageSize=2000, downCacheSize=2000
22:20:57,643 INFO [QueueService] Queue[/queue/quickstart_Business_Rules_BasicShipping] started, fullSize=200000, pageSize=2000, downCacheSize=2000
22:20:57,682 INFO [EsbDeployment] Starting ESB Deployment 'Quickstart_business_rules_service.esb'
И чтобы запустить его, исключите эту цель муравья:
ant runtest
При запуске быстрого запуска, вот что происходит, шаг за шагом. Обратите внимание, что хотя мы будем подробно изучать большую часть содержимого файла jboss-esb.xml, мы будем делать это по частям или фрагментам, чтобы было легче следить за ними. Поэтому номера строк в каждом из этих фрагментов будут отличаться от фактического (целого) файла.
Шаг 1. Создание сообщения и его передача через шлюз в развернутое приложение быстрого запуска
Как и многие из быстрых запусков платформы SOA, быстрый запуск business_rules_service инициирует свои действия, когда сообщение вставляется в очередь, за которой наблюдает прослушиватель шлюза. Что за ворота? На JBossESB в платформе SPA все является либо службой, которая генерирует или потребляет сообщения, либо сообщением. То есть сообщение в форме (org.jboss.soa.esb.message), которое понимает ESB. Сервисы, которые могут понимать сообщения в этой форме, называются «поддерживающими ESB».
Как вы можете подключить другие, и, возможно, старые, устаревшие приложения через ESB? Используя шлюзы. Шлюз (org.jboss.soa.esb.listeners.gateway) — это служба, которая действует как мост между ESB-ориентированным и ESB-неосведомленным клиентом и службой. Шлюзы транслируют информацию между форматами сообщений ESB и не-ESB и EPR. (EPR обозначает ссылку на конечную точку.) Шлюзы являются процессами прослушивателя в том смысле, что они «прослушивают» входящие сообщения. Они отличаются от слушателей, поддерживающих ESB, тем, что принимают данные в разных форматах, например, объекты в файлах или таблицы SQL. Слушатели, поддерживающие ESB, могут принимать сообщения только в формате org.jboss.soa.esb.message.
Платформа SOA поддерживает следующие шлюзы:
- файловые шлюзы: локальная файловая система, ftp, sftp и ftps
- JMS
- HTTP / HTTPS
- электронная почта (POP3)
- Таблица SQL
- Hibernate
В случае этого быстрого запуска мы будем использовать шлюз JMS для получения сообщения JMS. Очередь шлюза и соответствующая ему ESB-очередь определяются в разделе jms-provider файла jboss-esb.xml:
<jms-bus busid="quickstartGwChannel">
<jms-message-filter dest-type="QUEUE"
dest-name="queue/quickstart_Business_Rules_Request_GW" />
</jms-bus>
<jms-bus busid="quickstartEsbChannel">
<jms-message-filter dest-type="QUEUE"
dest-name="queue/quickstart_Business_Rules_Request_ESB" />
</jms-bus>
И слушатель определен в верхней части определения сервиса «Business_Rules_Service»:
<service category="Business_RulesServices"
name="Business_Rules_Service" description="The main entry point">
<listeners>
<!-- Gateway -->
<jms-listener name="TheGateway"
busidref="quickstartGwChannel" is-gateway="true" />
<jms-listener name="TheESBChannel"
busidref="quickstartEsbChannel" >
</jms-listener>
</listeners>
<actions mep="OneWay">
- Обратите внимание, что в строке 6 мы идентифицируем слушателя как шлюз.
- Также обратите внимание, что в строке 11 мы определяем mep, или «шаблон обмена сообщениями». В случае этого быстрого запуска шаблон является «односторонним», что указывает на то, что шаблон сообщения является асинхронным. Мы отправляем сообщения, но не ждем ответа (или блокируем).
Как мы генерируем это сообщение? Взгляните на цель «runtest», в частности на имя класса, в файле ant build.xml быстрого запуска:
<target name="runtest" depends="compile"
description="willl receive JMS message to tigger the actions in the ESB">
<echo>Runs Test JMS Sender</echo>
<java fork="yes" classname="org.jboss.soa.esb.samples.quickstart.businessrules.test.SendJMSMessage" failonerror="true">
<classpath refid="exec-classpath" />
</java>
Это верно — мы отправляем сообщение JMS с программой под названием «SendJMSMessage». Трудно быть проще, чем это. ?
Чтобы смоделировать реалистичный заказ клиента в сообщении, SendJMSMessage создает сообщение из файла SampleOrder.xml быстрого запуска:
<Order orderId="1" orderDate="Wed Nov 15 13:45:28 EST 2006" statusCode="0"
netAmount="59.97" totalAmount="64.92" tax="4.95">
<Customer userName="user1" firstName="Harry" lastName="Fletcher" state="SD"/>
<OrderLines>
<OrderLine position="1" quantity="1">
<Product productId="364" title="The 40-Year-Old Virgin " price="29.98"/>
</OrderLine>
<OrderLine position="2" quantity="1">
<Product productId="299" title="Pulp Fiction" price="29.99"/>
</OrderLine>
</OrderLines>
</Order>
Класс SendJMSMessage читает этот файл, создает объект сообщения типа javax.jms.ObjectMessage (помните, что это сообщение, не поддерживающее ESB) и записывает его в очередь (queue / quickstart_Business_Rules_Request_GW), которую прослушивает наш шлюз JMS. Слушатель получает сообщение, и ESB преобразует его в сообщение с поддержкой ESB, а затем передает его в ESB через очередь queue / quickstart_Business_Rules_Request_ESB.
Теперь все становится интереснее.
Помните, что наши правила основаны на том, что определенные типы фактов (которые являются JavaBeans) доступны в рабочей памяти. Откуда эти факты? Мы создадим их из этого сообщения.
Шаг 2 — Преобразование сообщения в бины
Проблема в том, что у нас должен быть способ создать эти факты из информации в сообщении. К счастью, одной из задач, которые выполняет JBossESB в платформе SOA, является «преобразование». Следующее действие в конвейере действий быстрого старта использует механизм обработки smooks ( http://www.smooks.org/ ) и готовое действие JBossESB «SmooksAction» для преобразования информации в сообщении в факты:
<action name="transform"
class="org.jboss.soa.esb.smooks.SmooksAction">
<property name="smooksConfig" value="/smooks-res.xml" />
<property name="resultType" value="JAVA" />
</action>
Исходный код фактов (помните, что это JavaBeans и имеют методы getter и setter) находится в следующих файлах быстрого запуска:
В: src / org / jboss / soa / esb / samples / quickstart / businessrules / dvdstore
- Customer.java
- OrderHeader.java
- OrderItem.java
Быстрый запуск использует файл smooks-res.xml для выполнения преобразования. Давайте посмотрим на этот файл.
<?xml version='1.0' encoding='UTF-8'?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.2.xsd">
<!-- Populate the OrderHeader -->
<jb:bean beanId="orderHeader" class="org.jboss.soa.esb.samples.quickstart.businessrules.dvdstore.OrderHeader" createOnElement="order">
<jb:value property="orderId" data="Order/@orderId" />
<jb:value property="orderDate" data="Order/@orderDate" decoder="Calendar">
<jb:decodeParam name="format">EEE MMM dd HH:mm:ss z yyyy</jb:decodeParam>
<jb:decodeParam name="locale-language">en</jb:decodeParam>
<jb:decodeParam name="locale-country">US</jb:decodeParam>
</jb:value>
<jb:value property="statusCode" data="Order/@statusCode" />
<jb:value property="netAmount" data="Order/@netAmount" />
<jb:value property="totalAmount" data="Order/@totalAmount" />
<jb:value property="tax" data="Order/@tax" />
</jb:bean>
<!-- Populate the Customer -->
<jb:bean beanId="customer" class="org.jboss.soa.esb.samples.quickstart.businessrules.dvdstore.Customer" createOnElement="customer">
<jb:value property="userName" data="customer/@userName" />
<jb:value property="firstName" data="customer/@firstName" />
<jb:value property="lastName" data="customer/@lastName" />
<jb:value property="state" data="customer/@state" />
</jb:bean>
<!-- Populate the OrderItem list -->
<jb:bean beanId="orderItemList" class="java.util.ArrayList" createOnElement="orderlines">
<jb:wiring beanIdRef="orderItem" />
</jb:bean>
<!-- Populate the OrderItem instance -->
<jb:bean beanId="orderItem" class="org.jboss.soa.esb.samples.quickstart.businessrules.dvdstore.OrderItem" createOnElement="orderlines/orderline">
<jb:value property="position" data="orderline/@position" />
<jb:value property="quantity" data="orderline/@quantity" />
<jb:value property="productId" data="orderline/product/@productId" />
<jb:value property="title" data="orderline/product/@title" />
<jb:value property="price" data="orderline/product/@price" />
</jb:bean>
</smooks-resource-list>
Это верно — он использует XPath (http://www.w3.org/TR/xpath/) для анализа информации в сообщении в Customer (начиная со строки NN), OrderHeader (начиная со строки NN) и OrderItem.java (начиная со строки NN) JavaBeans и объект java.util.ArrayList, который содержит список заказов.
Шаг 3 — И добавьте бобы обратно в сообщение
Что происходит дальше? Ну, у нас есть оригинальное сообщение и несколько JavaBeans. Но помните, что в JBossESB на платформе SOA все является либо сообщением, либо службой. Нам нужен какой-то способ вернуть эти JavaBeans обратно в сообщение. То, как мы это делаем, заключается в следующем действии в конвейере действий:
<action name="map_order_components" class="org.jboss.soa.esb.actions.scripting.GroovyActionProcessor">
<property name="script" value="/map_order_components.groovy" />
</action>
GroovyActionProcessor — это еще одно из готовых действий платформы SOA. Сценарий groovy, на который ссылается действие, возвращает только что созданные JavaBeans и добавляет их (обратите внимание на использование beanId, определенных нами в файле smooks-res.xml) обратно в сообщение с именами свойств, которые соответствуют идентификаторам bean. Сценарий очень короткий — строки 3 и 4 добавляют orderHeard и customer к телу сообщения:
// Need to map down the orderHeader and customer beans onto the message
// to make them available to the ObjectMapper...
message.getBody().add("orderHeader", message.getBody().get().get("orderHeader"));
message.getBody().add("customer", message.getBody().get().get("customer"));
Теперь у нас есть JavaBeans в сообщении. Что происходит дальше? Быстрый запуск обновляет статус клиента (ему присваивается значение «0» в сообщении JMS, которое запустило быстрый запуск) с помощью настраиваемого действия «UpdateCustomerStatus»:
<!-- Update Customer Status -->
<action name="updateCustomerStatus"
class="org.jboss.soa.esb.samples.quickstart.businessrules.UpdateCustomerStatus">
<property name="status" value="60"/>
</action>
Мы установим это значение равным 60, поскольку клиент относится к платиновому классу. (Подсказка: для дополнительного кредита попробуйте быстрый старт с различными значениями статуса.)
Вот вывод в журнале — эта строка печатается с помощью настраиваемого действия org.jboss.soa.esb.samples.quickstart.businessrules.UpdateCustomerStatus:
21:42:15,793 INFO [STDOUT] { Updated customer status to 60}
Шаг 4. Обработка сообщения с помощью BusinessRulesProcessor
ОК — теперь мы можем увидеть, как BusinessRulesProcessor выполняется в следующем действии:
<!-- Use the BRP to calculate the order priority -->
<action
class="org.jboss.soa.esb.actions.BusinessRulesProcessor"
name="BRP">
<property name="ruleSet"
value="MyBusinessRules.drl" />
<property name="ruleReload" value="true" />
<property name="object-paths">
<object-path esb="body.orderHeader" />
<object-path esb="body.customer" />
</property>
</action>
<action name="reviewMessage1"
class="org.jboss.soa.esb.samples.quickstart.businessrules.ReviewMessage">
<property name="stuff" value="After Order Priority"/>
</action>
- Строка 1 — Комментарии всегда хорошие вещи! ?
- Строка 2 — это начало действия, которое использует BusinessRulesProcessor.
- Строка 3 — и вот ссылка на класс BusinessRulesProcessor.
- Строки 5-6 — и вот ссылка на файл правил, который мы хотим выполнить.
- Строка 7 — это свойство приводит к изменению правила, если файл изменяется.
- Строки 8-11. И вот объекты, которые мы добавили в сообщение. Помните файл map_order_components.groovy?
Итак, что только что произошло? Мы сделали объекты orderHeader и customer доступными для Правил, определенных в MyBusinessRules.drl, и выполнили Правила. Чистый эффект этого состоит в том, что приоритет порядка, определенного в сообщении, должен был измениться. Следующее действие в конвейере действий записывает это в журнал:
21:42:15,931 INFO [STDOUT] Platinum Customer - High Priority
21:42:15,932 INFO [STDOUT] Customer Status: 60
21:42:15,932 INFO [STDOUT] Order Total: 64.92
Первые три строки напечатаны по правилам. Помните, как все правила включали операторы System.out.prinln? И как правило ведения журнала, которое печатает статус клиента и итоговую сумму заказа, имеет свойство значимости более низкого значения, чем правила, которые устанавливают и печатают приоритет клиента? Это объясняет порядок, в котором выписки выводятся в журнал.
Затем эти строки печатаются с помощью обычного действия org.jboss.soa.esb.samples.quickstart.businessrules.ReviewMessage:
21:42:15,932 INFO [STDOUT] { ================ After Order Priority
21:42:15,933 INFO [STDOUT] Customer: user1,Harry,Fletcher,SD,60
21:42:15,933 INFO [STDOUT] Order Priority: 3
21:42:15,933 INFO [STDOUT] Order Discount: 0.0
21:42:15,933 INFO [STDOUT] Order Total: 64.92
21:42:15,933 INFO [STDOUT] } ================ After Order Priority
Правило «Заказы с наивысшим приоритетом», определенное в MyBusinessRules.drl, установило приоритет порядка 3.
Затем быстрый запуск снова вызывает BusinessRulesProcessor, на этот раз для определения скидки на заказ:
<!-- Use the BRP to calculate the order discount -->
<action
class="org.jboss.soa.esb.actions.BusinessRulesProcessor"
name="BRP2">
<property name="ruleSet"
value="MyBusinessRulesDiscount.drl" />
<property name="ruleReload" value="true" />
<property name="object-paths">
<object-path esb="body.orderHeader" />
<object-path esb="body.customer" />
</property>
</action>
<action name="reviewMessage2"
class="org.jboss.soa.esb.samples.quickstart.businessrules.ReviewMessage">
<property name="stuff" value="After Order Discount"/>
</action>
- Строка 6 — правило «Платиновый статус клиента», определенное в файле MyBusinessRulesDiscount.drl, выполняется, поскольку наш клиент имеет как самый высокий приоритет, так и значение статуса 60. Это правило и правило ведения журнала распечатывают эти операторы для входа в систему. этот заказ:
21:42:16,062 INFO [STDOUT] Platinum Customer - High Priority - Higher discount
21:42:16,063 INFO [STDOUT] Customer Status: 60
21:42:16,063 INFO [STDOUT] Order Total: 64.9
Затем выполняется пользовательское действие org.jboss.soa.esb.samples.quickstart.businessrules.ReviewMessage для вывода этих операторов в журнал:
21:42:16,063 INFO [STDOUT] { ================ After Order Discount
21:42:16,063 INFO [STDOUT] Customer: user1,Harry,Fletcher,SD,60
21:42:16,064 INFO [STDOUT] Order Priority: 3
21:42:16,064 INFO [STDOUT] Order Discount: 8.5
21:42:16,064 INFO [STDOUT] Order Total: 64.92
21:42:16,064 INFO [STDOUT] } ================ After Order Discount
И там мы видим нашу щедрую скидку 8,5%.
Затем, быстрый старт распечатывает все сообщение в журнал с этим действием из коробки:
<action name="sout" class="org.jboss.soa.esb.actions.SystemPrintln" />
А вот как это выглядит в server.log:
21:42:16,064 INFO [STDOUT] Message structure: 21:42:16,064 INFO [STDOUT] [{orderHeader=1, java.util.GregorianCalendar[time=1163616328000,
areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.
ZoneInfo[id="US/Eastern",offset=-18000000,dstSavings=3600000,useDaylight=true,
transitions=235,lastRule=java.util.SimpleTimeZone[id=US/Eastern,offset=-18000000,
dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,
startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,
endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,
ERA=?,YEAR=2006,MONTH=10,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=15,DAY_OF_YEAR=?,
DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=?,AM_PM=?,HOUR=?,HOUR_OF_DAY=13,MINUTE=45,SECOND=28,
MILLISECOND=?,ZONE_OFFSET=-18000000,DST_OFFSET=0], 0, 59.97, 64.92, 4.95, ,
orderItemList=[1,1,364,The 40-Year-Old Virgin ,29.98, 2,1,299,Pulp Fiction,29.99],
orderItem=2,1,299,Pulp Fiction,29.99, customer=user1,Harry,Fletcher,SD,60}].
Это немного сложно читать. Давайте возьмем дату / время заказа, чтобы мы могли лучше видеть Bean-компоненты customer и orderHeader, которые мы добавили в сообщение:
{
orderHeader=1, 0, 59.97, 64.92, 4.95,
orderItemList=[1,1,364,The 40-Year-Old Virgin ,29.98, 2,1,299,Pulp Fiction,29.99],
orderItem=2,1,299,Pulp Fiction,29.99,
customer=user1,Harry,Fletcher,SD,60
}
Шаг 5 — Направьте сообщение к месту назначения на основе его содержимого.
На этом этапе быстрый запуск завершился с использованием BusinessRulesProcessor, но еще не с использованием правил. Помните, как я сказал, что на JBossESB в платформе SOA все является либо сообщением, либо службой? Ну, одна из основных функций, выполняемых ESB, заключается в маршрутизации сообщений на правильный сервис. Эти маршруты могут быть статическими или динамическими в зависимости от содержимого сообщения. Здесь начинается маршрутизация на основе контента с правилами. Правила маршрутизации определены в файле MyRoutingRules.drl. Помните, как правила в этом файле обозначали «места назначения» сообщений? Это следующее действие использует вызывает org.jboss.soa.esb.actions.ContentBasedRouter класс для маршрутизации сообщений в их предполагаемые места назначения.
<!-- Use the CBR to route the "scored" order to the appropriate service team -->
<action
class="org.jboss.soa.esb.actions.ContentBasedRouter"
name="ContentBasedRouter">
<property name="ruleSet" value="MyRoutingRules.drl" />
<property name="ruleReload" value="true" />
<property name="destinations">
<route-to
destination-name="SuperSpecialCustomerService"
service-category="ConciergeManager" service-name="ConciergeService" />
<route-to
destination-name="SpecialCustomerService"
service-category="DistributionManager" service-name="DistributionService" />
<route-to
destination-name="RegularCustomerService"
service-category="BasicShipping" service-name="ShipperService" />
</property>
<property name="object-paths">
<object-path esb="body.orderHeader" />
<object-path esb="body.customer" />
</property>
</action>
- Линии 107-109, 110-112 и 113-115 определяют маршруты. Поскольку наше сообщение теперь имеет наивысший приоритет, оно направляется в ConciergeService.
Вот что показывает нам журнал. Опять же, первая строка печатается по правилу:
21:42:16,210 INFO [STDOUT] HIGHEST PRIORITY
А остальные строки печатаются с помощью настраиваемого действия org.jboss.soa.esb.samples.quickstart.businessrules.ReviewMessage, вызываемого ConciergeService.
21:42:16,309 INFO [STDOUT] { ================ Concierge
21:42:16,309 INFO [STDOUT] Customer: user1,Harry,Fletcher,SD,60
21:42:16,309 INFO [STDOUT] Order Priority: 3
21:42:16,309 INFO [STDOUT] Order Discount: 8.5
21:42:16,310 INFO [STDOUT] Order Total: 64.92
21:42:16,310 INFO [STDOUT] } ================ Concierge
Итак, заказ клиента был доставлен в самый шикарный ConciergeService, и быстрое выполнение завершено.
Заключительные мысли
Хорошо, давайте рассмотрим, что случилось. Быстрый запуск определяет несколько бизнес-правил для проверки и изменения сообщения, поскольку оно обрабатывается действиями, выполняемыми службами ESB, а затем направляет это сообщение в правильную службу назначения. Правила хранятся в файлах .drl, отдельно от кода пользовательских действий служб, что упрощает их обслуживание. И обратите внимание на то, что быстрый запуск не должен был выполнять — правила были выполнены, а маршрутизация на основе контента была выполнена с помощью готовых действий, предоставляемых JBossESB платформы SOA. Это позволило для быстрого старта сосредоточиться на бизнес-логике правил.
Подтверждения
Как всегда, я хочу поблагодарить команду и сообщество JBoss SOA Platform (особенно Кевина Коннера и Марка Проктора за их своевременную рецензию на этот пост в блоге).
Рекомендации
- Платформа JBoss SOA ( http://www.jboss.com/products/platforms/soa/ )
- Платформа JBoss BRMS ( http://www.jboss.com/products/platforms/brms/ )
- Проект JBossESB ( http://www.jboss.org/jbossesb )
- Проект JBoss Drools ( http://www.jboss.org/drools )
- Проект JBoss Smooks ( http://www.smooks.org )
- Бизнес-правила JBoss Drools Пола Брауна (опубликованные Packt Publishing) ( https://www.packtpub.com/jboss-drools-business-rules/book )