Drools Spring Integration

Drools Spring Integration

1. Вступление

В этом кратком руководстве мы собираемся интегрировать Drools с Spring. Если вы только начинаете работать с Drools,check out this intro article.

2. Maven Зависимости

Начнем с добавления следующих зависимостей в наш файлpom.xml:


    org.drools
    drools-core
    7.0.0.Final


    org.kie
    kie-spring
    7.0.0.Final

Последние версии можно найти здесь дляdrools-core и здесь дляkie-spring.

3. Начальные данные

Давайте теперь определим данные, которые будут использоваться в нашем примере. Мы рассчитаем стоимость поездки на основе пройденного расстояния и отметки о ночной надбавке.

Вот простой объект, который будет использоваться какFact:

public class TaxiRide {
    private Boolean isNightSurcharge;
    private Long distanceInMile;

    // standard constructors, getters/setters
}

Давайте также определим еще один бизнес-объект, который будет использоваться для представления тарифов:

public class Fare {
    private Long nightSurcharge;
    private Long rideFare;

    // standard constructors, getters/setters
}

Теперь давайте определим бизнес-правило для расчета стоимости такси:

global com.example.spring.drools.model.Fare rideFare;
dialect  "mvel"

rule "Calculate Taxi Fare - Scenario 1"
    when
        taxiRideInstance:TaxiRide(isNightSurcharge == false && distanceInMile < 10);
    then
        rideFare.setNightSurcharge(0);
        rideFare.setRideFare(70);
end

Как мы видим, определено правило для расчета общей стоимости проезда для данногоTaxiRide.

Это правило принимает объектTaxiRide и проверяет, равен ли атрибутisNightSurchargefalse, а значение атрибутаdistanceInMile меньше 10, затем вычисляет тариф как 70 и устанавливаетnightSurcharge на 0.

Расчетный результат устанавливается в объектFare для дальнейшего использования.

4. Весенняя интеграция

4.1. Конфигурация Spring Bean

Теперь перейдем к интеграции Spring.

Мы собираемся определить класс конфигурации компонента Spring, который будет отвечать за создание экземпляра компонентаTaxiFareCalculatorService и его зависимостей:

@Configuration
@ComponentScan("com.example.spring.drools.service")
public class TaxiFareConfiguration {
    private static final String drlFile = "TAXI_FARE_RULE.drl";

    @Bean
    public KieContainer kieContainer() {
        KieServices kieServices = KieServices.Factory.get();

        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        kieFileSystem.write(ResourceFactory.newClassPathResource(drlFile));
        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
        kieBuilder.buildAll();
        KieModule kieModule = kieBuilder.getKieModule();

        return kieServices.newKieContainer(kieModule.getReleaseId());
    }
}

KieServices - это синглтон, который действует как единая точка входа для получения всех услуг, предоставляемых Kie. KieServices извлекается с помощьюKieServices.Factory.get().

Затем нам нужно получитьKieContainer, который является заполнителем для всего объекта, который нам нужен для запуска механизма правил.

KieContainer создается с помощью других bean-компонентов, включаяKieFileSystem, KieBuilder, иKieModule.

Давайте приступим к созданиюKieModule, который является контейнером всех ресурсов, необходимых для определения знаний правил, известных какKieBase..

KieModule kieModule = kieBuilder.getKieModule();

KieBase - это репозиторий, который содержит все знания, связанные с приложением, такие как правила, процессы, функции, модели типов, и он скрыт внутриKieModule. KieBase можно получить изKieContainer.

После созданияKieModule мы можем приступить к созданиюKieContainer, который содержитKieModule, в котором был определенKieBase. KieContainer создается с помощью модуля:

KieContainer kContainer = kieServices.newKieContainer(kieModule.getReleaseId());

4.2. Весенняя служба

Давайте определим класс обслуживания, который выполняет реальную бизнес-логику, передавая объектFact механизму для обработки результата:

@Service
public class TaxiFareCalculatorService {

    @Autowired
    private KieContainer kieContainer;

    public Long calculateFare(TaxiRide taxiRide, Fare rideFare) {
        KieSession kieSession = kieContainer.newKieSession();
        kieSession.setGlobal("rideFare", rideFare);
        kieSession.insert(taxiRide);
        kieSession.fireAllRules();
        kieSession.dispose();
        return rideFare.getTotalFare();
    }
}

Наконец,KieSession создается с использованием экземпляраKieContainer. ЭкземплярKieSession - это место, куда могут быть вставлены входные данные. KieSession взаимодействует с механизмом для обработки фактической бизнес-логики, определенной в правиле, на основе вставленных фактов.

Global (как и глобальная переменная) используется для передачи информации в движок. Мы можем установить Global, используяsetGlobal(“key”, value);, в этом примере мы установили объектFare как Global для хранения рассчитанной стоимости такси.

Как мы обсуждали в разделе 4,a Rule requires data to operate on. Мы вставляемFact в сеанс с помощьюkieSession.insert(taxiRide);

После того, как мы закончили настройку входаFact,, мы можем запросить движок для выполнения бизнес-логики, вызвавfireAllRules().

Наконец, нам нужно очистить сеанс, чтобы избежать утечки памяти, вызвав методdispose().

5. Пример в действии

Теперь мы можем подключить контекст Spring и увидеть в действии, что Drools работает должным образом:

@Test
public void whenNightSurchargeFalseAndDistLessThan10_thenFixWithoutNightSurcharge() {
    TaxiRide taxiRide = new TaxiRide();
    taxiRide.setIsNightSurcharge(false);
    taxiRide.setDistanceInMile(9L);
    Fare rideFare = new Fare();
    Long totalCharge = taxiFareCalculatorService.calculateFare(taxiRide, rideFare);

    assertNotNull(totalCharge);
    assertEquals(Long.valueOf(70), totalCharge);
}

6. Заключение

В этой статье мы узнали об интеграции Drools Spring с помощью простого варианта использования.

Как всегда, доступны реализация примера и фрагменты кодаover on GitHub.