В предыдущем посте о camel-drools я представил компонент camel-drools и реализовал некоторый простой процесс, ориентированный на выполнение задач, используя правила внутри маршрута Camel. Сегодня я покажу, как расширить этот пример, добавив обработку событий .
Итак, как описать событие? Каждое событие происходит в определенное время и длится в течение некоторого времени, события происходят в определенном порядке. Затем у нас есть «облако событий», из которого мы хотим идентифицировать те, которые образуют некоторые интересные корреляции. И здесь использование Drools становится разумным — нам не нужно реагировать на каждое событие, просто описать набор правил и последствий для этих интересных взаимосвязей. Двигатель слюней найдет их и сработает по правилам соответствия.
Предположим, что наша система должна контролировать выполнение задач, назначенных пользователям. После создания задачи у пользователя есть 10 дней на ее выполнение. Когда он этого не делает — следует отправить остаток по электронной почте.
Определение правила может выглядеть так:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
import org.apache.camel.component.drools.stateful.model.*global org.apache.camel.component.drools.CamelDroolsHelper helperdeclare TaskCreated @role( event ) @expires( 365d )enddeclare TaskCompleted @role( event ) @expires( 365d )endrule "Task not completed after 10 days" when $t : TaskCreated() not(TaskCompleted(name==$t.name, this after [-*, 10d] $t)) then helper.send("direct:escalation", $t.getName());end |
Как видите, есть два типа событий: TaskCreated — когда система назначает задачу пользователям, и TaskCompleted — когда пользователь завершает задачу. Мы коррелируем эти два по свойству name. Во-первых, нам нужно объявить наши классы моделей как события, добавив аннотации @role (event) и @expires. Затем мы опишем правило: «если после 10 дней события TaskCreated нет события TaskCompleted, отправьте имя задачи по адресу direct: escalation route». Опять же, это может быть примером декларативного программирования — нам не нужно указывать фактические имена задач, просто соотносим TaskCreated с событиями TaskCompleted по имени.
В этом примере я использовал временной оператор «после». Описание других — см. Документацию Drools Fusion .
И, наконец, вот фрагмент кода теста JUnit:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
public class TaskEventsTest extends GenericTest { DefaultCamelContext ctx; @Test public void testCompleted() throws Exception { insertAdvanceDays(new TaskCreated("Task1"), 4); assertContains(0); insertAdvanceDays(new TaskCompleted("Task1"), 4); advanceDays(5); assertContains(0); } @Test public void testNotCompleted() throws Exception { insertAdvanceDays(new TaskCreated("Task1"), 5); assertContains(0); advanceDays(5); assertContains("Task1"); } @Test public void testOneNotCompleted() throws Exception { ksession.insert(new TaskCreated("Task1")); insertAdvanceDays(new TaskCreated("Task2"), 5); assertContains(0); insertAdvanceDays(new TaskCompleted("Task1"), 4); assertContains(0); advanceDays(1); assertContains("Task2"); advanceDays(10); assertContains("Task2"); } @Override protected void setUpResources(KnowledgeBuilder kbuilder) throws Exception { kbuilder.add(new ReaderResource(new StringReader( IOUtils.toString(getClass() .getResourceAsStream("/stateful/task-event.drl")))), ResourceType.DRL); } @Override public void setUpInternal() throws Exception { this.ctx = new DefaultCamelContext(); CamelDroolsHelper helper = new CamelDroolsHelper(ctx, new DefaultExchange(ctx)) { public Object send(String uri, Object body) { sentStuff.add(body.toString()); return null; }; }; ksession.setGlobal("helper", helper); }} |
- Вы можете найти исходный код для этого примера здесь .