В предыдущем посте о 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 helper declare TaskCreated @role ( event ) @expires ( 365d ) end declare TaskCompleted @role ( event ) @expires ( 365d ) end rule "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); } } |
- Вы можете найти исходный код для этого примера здесь .