Статьи

Интегрированные JBoss Fuse и JBoss BPM Suite

На прошлой неделе был выпущен Apache Camel v2.16 с более чем 600 исправленными проблемами (исправления ошибок, обновления и новые функции). Клаус уже писал о 10 лучших моментах, и здесь я хочу кратко показать пример использования моего небольшого вклада в этот выпуск: компонент camel-jbpm .

Этот компонент предназначен для упрощения интеграции с jBPM (приложение для управления бизнес-процессами). Использует Remote Java APIи в основном выполняет вызовы REST в jBPM для управления бизнес-процессами (запуск, остановка, прерывание), выполнения бизнес-правил, управления человеческими задачами и т. д. Поэтому вместо ручного создания клиента REST или удаленного API вы можете использовать компонент Camel. Удаленный API также обеспечивает интеграцию на основе HornetMQ, но я исключил эту часть из компонента Camel, так как он плохо работает с OSGI.

В примере использования (который вдохновлен реальным) есть интеграционное приложение на базе Camel, которое работает на JBoss Fuse и должно выполнять интеграцию в реальном времени. И всякий раз, когда возникает ошибка в пути интеграции, подробности ошибки отправляются в jBPM для оценки и проверки человеком, если это необходимо. Чтобы продемонстрировать, что я создал два отдельных проекта:

  • Проект Camel, который работает на Fuse , обрабатывает любые исключения и отправляет подробности в jBPM
  • Проект бизнес-процесса, который выполняется в jBPM , классифицирует ошибки, используя Drools и обработку сложных событий, и создает неавтоматизированные задачи, если ошибка является критической.

Приведенный ниже маршрут Camel не требует пояснений, есть маршрут, который генерирует 10 исключений с задержкой в ​​полсекунды каждый, и обработчик ошибок, который перехватывает эти исключения и отправляет их в jBPM. Обратите внимание, что он также заполняет заголовок CamelJBPMParameters подробностями об ошибке.

public void configure() {

    from("timer://trigger?fixedRate=true&period=500&repeatCount=10").routeId("mainRoute")
            .to("log:com.ofbizian.jbpm.before?showAll=true&multiline=true")
            .process(new Processor() {
                @Override
                public void process(Exchange exchange) throws Exception {
                    throw new RuntimeException("Something went wrong");
                }
            });

    onException(Exception.class)
            .handled(true)
            .process(new Processor() {
                @Override
                public void process(Exchange exchange) throws Exception {
                    final Map map = new HashMap();
                    map.putAll(exchange.getIn().getHeaders());
                    map.put("contextId", exchange.getContext().getName());
                    map.put("routeId", exchange.getProperty(Exchange.FAILURE_ROUTE_ID));
                    map.put("endpointId", exchange.getProperty(Exchange.FAILURE_ENDPOINT));
                    map.put("exchangeId", exchange.getExchangeId());
                    map.put("breadcrumbId", exchange.getIn().getHeader(Exchange.BREADCRUMB_ID));
                    map.put("exceptionType", exchange.getProperty(Exchange.EXCEPTION_CAUGHT).getClass());
                    map.put("errorMessage", exchange.getProperty(Exchange.EXCEPTION_CAUGHT).toString());
                    exchange.getOut().setHeader("CamelJBPMParameters", map);
                }
            })
            .to("jbpm:http://localhost:8080/business-central?userName=bpmsAdmin&password=password&deploymentId=org.kie.example:camel-process:1.0.0-SNAPSHOT&processId=project1.camel.demo");
}   

Вы можете найти пример кода на github с инструкциями о том, как собрать и запустить его на Fuse.

Вторая часть демонстрации состоит из процесса jBPM, который получает ошибки и обрабатывает их. Диаграмма BPMN2 процесса ниже:

Процесс имеет входные параметры, соответствующие значениям из заголовка CamelJBPMParameters. На первом этапе он инициализирует объект RequestQualifier, помеченный как некритический. На втором этапе мы используем Drools и обработку сложных событий, чтобы квалифицировать ошибки, которые происходят в течение определенного периода времени. Идея с CEP состоит в том, что мы хотим пометить ошибку как критическую, только если за 10 секунд было более 5 ошибок. Кроме того, чтобы пометить как критические множественные ошибки и заполнить систему человеческими задачами, мы ограничиваем только одну критическую ошибку максимум через 10 минут. Все эти условия записаны в Drools следующим образом:

package org.kie.example.project1;

rule "Mark a request as critical when there are 5 or more in 10 seconds. There should be at most 1 critical per 10 minutes"
when
    $requestQualifier: RequestQualifier(processed == false)
    Number( intValue >=5 ) from accumulate($r: RequestQualifier( ) over window:time( 10s ),count( $r ) )
    Number( intValue ==0 ) from accumulate($r: RequestQualifier( critical == true) over window:time(10m ),count( $r ) )
then
    modify($requestQualifier) {
        setProcessed(true),
        setCritical(true);
    }
end

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

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

Это требует, чтобы пользователь назначил задачу и предпринял действия по ней. Мы видим, что Human Task получил подробности из бизнес-процесса:

После того, как задание «Человек» заявлено и выполнено, бизнес-процесс продолжается и завершается на следующем шаге.