Добро пожаловать в очередной эпизод этой серии блогов, посвященный инициативе Kogito и нашим усилиям по выводу Drools в облако. Цель этих сообщений — собрать отзывы пользователей о функциях, которые мы предоставляем Kogito.
В этом посте мы представляем два новых способа реализации полного интеллектуального сервиса:
- автономные службы правил
- интегрированные интеллектуальные рабочие процессы с задачами правил
Единицы Казни в Когито
Как вы, возможно, уже знаете, в Kogito мы делаем переднюю и центральную новую концепцию Unit .
«Единица исполнения» — это термин, который мы используем для обозначения исполняемой части знаний. Единица может быть процессом, набором правил, решением и т. Д.… В случае набора правил мы называем это блоком правил . Если вы решите использовать юниты, в Kogito мы позаботимся обо всем шаблоне, который необходим для автоматической генерации конечной точки REST .
Единица правила состоит в основном из
1) определение данных;
2) набор правил и запросов, которые реализуют поведение модуля (правила механизма правил);
3) опционально, слушатели событий могут быть подключены для ряда целей.
В этом посте мы сосредоточимся на определениях данных, правилах и запросах.
Определения данных задаются объявлением класса Java, который может содержать источники данных. Каждый источник данных представляет собой раздел рабочей памяти, с которым ваши правила будут соответствовать шаблону или вставлять.
Например, предположим, что вы хотите объявить службу оповещений, которая получает события и выдает оповещения в зависимости от некоторых условий. Мы заявляем
Объекты Event
и Alert
:
01
02
03
04
05
06
07
08
09
10
11
12
|
package com.acme; public class Event { String type; int value; // getters and setters } public class Alert { String severity; String message; // getters and setters } |
Объявление типа модуля AlertingService
— это класс, который реализует интерфейс RuleUnitData
.
1
2
3
4
5
6
|
package com.acme; public class AlertingService implements RuleUnitData { private final DataStream<Event> eventData = DataSource.createStream(); private final DataStream<Alert> alertData = DataSource.createStream(); // getters and setters } |
Правила определяются в файлах DRL как обычно, за исключением того, что теперь вы должны указать их единицы в верхней части файла. Например, вы можете объявить определение данных для AlertingService
следующим образом:
1
2
3
4
5
6
7
8
9
|
package com.acme; unit AlertingService; rule IncomingEvent when // matches when a temperature higher than 30 °C is registered (OOPath syntax) $e : /eventData [ type == "temperature" , value >= 30 ] then System.out.println( "incoming event: " + $e.getMessage()); alertData.append( new Alert( "warning" , "Temperature is too high" ) ); end |
Как видите, правила могут совпадать или вставляться в данные источники данных.
Запросы определяются в файлах DRL, как правила, и также принадлежат модулю. Если вы объявите хотя бы один запрос, вы получите конечную точку REST, автоматически сгенерированную бесплатно . Например:
1
2
3
|
query Warnings alerts: /alertData [ severity == "warning" ] end |
сгенерирует конечную точку REST /warnings
которые вы сможете вызвать, отправив ей сообщение POST, следующим образом:
1
2
3
4
5
|
$ curl -X POST \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "eventData": [ { "type": "temperature", "value" : 40 } ] }' \ http: //localhost:8080/warnings |
Это сгенерирует ответ:
1
|
[ { "severity" : "warning" , "message" : "Temperature is too high" } ] |
Определение данных на основе Java очень знакомо программистам, но, исходя из ранних отзывов пользователей, мы решили предоставить два альтернативных метода для объявления модуля правила . Мы публикуем эту запись в блоге, чтобы собрать больше отзывов пользователей!
Тип декларации
Объявление типа — это функция DRL для объявления совместимых с Java типов, не зависящих от Java. В серии 7 пользователи могут объявлять типы с синтаксисом:
01
02
03
04
05
06
07
08
09
10
11
|
package com.acme; declare Event type: String value: int end declare Alert severity: String message: String end |
Это делает DRL полностью автономным: все сущности и правила могут быть определены с использованием DRL. Однако у них мало ограничений; например, они не поддерживают реализацию интерфейсов и не поддерживают поля универсального типа. Другими словами, следующее объявление в серии 7 является синтаксически недействительным:
1
2
3
4
5
|
package com.acme; declare AlertingService extends RuleUnitData eventData: DataStream<Event> alertData: DataStream<Alert> end |
В версии 0.8.0 мы снимаем эти ограничения: мы разрешаем ограниченное наследование для интерфейсов (пока разрешено только одно) и объявление универсального типа для полей. Благодаря этим новым функциям следующий фрагмент кода становится действительным DRL.
Короче говоря: теперь вы можете объявить полный микросервис
с одного ДХО .
Загрузите ваш сервис Kogito с помощью архетипа:
1
2
3
4
5
6
|
mvn archetype:generate \ -DarchetypeGroupId=org.kie.kogito \ -DarchetypeArtifactId=kogito-quarkus-archetype \ -DarchetypeVersion= 0.8 . 0 \ -DgroupId=com.acme \ -DartifactId=sample-kogito |
На данный момент ни одна версия Quarkus не входит в комплект Kogito 0.8.0; в противном случае вы могли бы использовать mvn io.quarkus:quarkus-maven-plugin:create
.
Теперь очистите содержимое src/main
и затем поместите этот DRL в папку src/main/resources/com/acme
:
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
|
package com.acme; unit AlertingService; import org.kie.kogito.rules.DataStream; import org.kie.kogito.rules.RuleUnitData; declare Event type: String value: int end declare Alert severity: String message: String end declare AlertingService extends RuleUnitData eventData: DataStream<Event> alertData: DataStream<Alert> end rule IncomingEvent when // matches when a temperature higher than 30 °C is registered (OOPath syntax) $e : /eventData [ type == "temperature" , value >= 30 ] then System.out.println( "incoming event: " + $e.getMessage()); alertData.append( new Alert( "warning" , "Temperature is too high: " + $e ) ); end query Warnings alerts: /alertData [ severity == "warning" ] end |
Теперь запустите сервис Quarkus в режиме разработчика с помощью:
1
|
$ mvn compile quarkus:dev |
Вот и все, теперь вы готовы curl
свой сервис:
1
2
3
4
5
|
$ curl -X POST \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "eventData": [ { "type": "temperature", "value" : 40 } ] }' \ http: //localhost:8080/warnings |
Интеграция рабочего процесса
Еще один способ предоставления службы на основе правил — через рабочий процесс .
Рабочий процесс (иногда называемый «бизнес-процессом») описывает последовательность шагов на диаграмме и обычно объявляет переменные : держатели данных для значений, которыми манипулируют при выполнении. Тип данных одной такой переменной может быть любым : вы можете использовать классы Java, но в этом примере мы снова будем использовать наши объявленные типы данных.
01
02
03
04
05
06
07
08
09
10
11
|
package com.acme; declare Event type: String value: int end declare Alert severity: String message: String end |
Давайте вызовем этот рабочий процесс com.acme.AlertingWorkflow
и объявим переменные eventData
и alertData
:
Рабочий процесс, который включает в себя задачу правила, может вообще пропустить объявление данных модуля правила: в этом случае модуль правила выводится непосредственно из структуры процесса: каждая переменная будет вставлена в источник данных с тем же именем .
Имя модуля объявляется процессом с использованием синтаксического unit:com.acme.AlertingService
. Вы по-прежнему можете явно объявить модуль com.acme.AlertingService
; в этом случае процесс подберет декларацию, которую вы написали вручную.
Примечание. Возможно, вы заметили, что мы используем поле «Группа правил потока». Мы будем реализовывать более явную поддержку в пользовательском интерфейсе в будущем.
Загрузите ваш сервис Kogito с помощью архетипа:
1
2
3
4
5
6
|
mvn archetype:generate \ -DarchetypeGroupId=org.kie.kogito \ -DarchetypeArtifactId=kogito-quarkus-archetype \ -DarchetypeVersion= 0.8 . 0 \ -DgroupId=com.acme \ -DartifactId=sample-kogito |
Будьте осторожны Поддержка этой функции является экспериментальной, поэтому она может не работать без проблем с горячей перезагрузкой кода Quarkus; нам также понадобится следующий дополнительный шаг, чтобы включить его, но это изменится в будущем.
Обновите ваш pom.xml
следующим объявлением плагина:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
<build> <plugins> <plugin> <groupId>org.kie.kogito</groupId> <artifactId>kogito-maven-plugin</artifactId> <version> 0.8 . 0 </version> <executions> <execution> <goals> <goal>generateDeclaredTypes</goal> </goals> </execution> </executions> </plugin> ... </plugins> </build> |
Теперь вы можете очистить содержимое src/main
, а затем отбросить процесс и следующий DRL в папку src/main/resources/com/acme
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.acme; unit AlertingService; import org.kie.kogito.rules.DataStream; import org.kie.kogito.rules.RuleUnitData; declare Event type: String value: int end declare Alert severity: String message: String end rule IncomingEvent when // matches when a temperature higher than 30 °C is registered (OOPath syntax) $e : /eventData [ type == "temperature" , value >= 30 ] then System.out.println( "incoming event: " + $e.getMessage()); alertData.set( new Alert( "warning" , "Temperature is too high: " + $e ) ); end |
Как вы могли заметить, вы не обязаны объявлять запрос явно: процесс будет отображать содержимое переменных в качестве ответа; он сгенерирует конечную точку /AlertingWorkflow
и примет запрос POST
следующей формы:
1
2
3
4
5
|
$ curl -X POST \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "eventData": { "type": "temperature", "value" : 40 } }' \ http: //localhost:8080/AlertingWorkflow |
Ответ будет:
01
02
03
04
05
06
07
08
09
10
11
|
{ "id" : ..., "eventData" : { "type" : "temperature" , "value" : 100 }, "alertData" : { "severity" : "warning" , "message" : "Temperature is too high: Event( type=temperature, value=100 )" } } |
Однако, если вы объявите запрос, будет также доступна отдельная конечная точка. Например, если вы объявите запрос Warnings
вы все равно сможете отправить POST по http://localhost:8080/warnings
и отдельно запустить службу правил следующим образом:
1
2
3
4
5
|
$ curl -X POST \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "eventData": { "type": "temperature", "value" : 40 } }' \ http: //localhost:8080/warnings |
Обратите внимание, что запрос больше не содержит список событий. Это потому, что переменные процесса отображаются в отдельные значения вместо DataStreams.
Вывод
Мы немного ознакомились с работой, которую мы делаем, чтобы улучшить начальный опыт работы с правилами и процессами в Kogito. С этими изменениями мы надеемся предоставить более упорядоченный способ определения услуг, основанных на знаниях. Разработчики всегда смогут быть более откровенными в отношении данных, которые они хотят обработать, включив написание Java; но если они хотят, они могут использовать полностью рабочий процесс разработки, ориентированный на DSL.
Для ленивых, примеры доступны на https://github.com/evacchi/kogito-rules-example/tree/master/code Удачи!
Смотреть оригинальную статью здесь: Kogito, ergo Rules: от знаний к сервису, без усилий Мнения, высказанные участниками Java Code Geeks, являются их собственными. |