Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a Spring Service in Drools rules?

I'm working with drools engine in the construction of an alert system. we need to execute a method of a @Service instantiated by Spring Framework on the actions of the rule (RHS), when the conditions are met.

What would be the way to get the @service instance created by Spring Framework to be used by the action (RHS) of the Drools rule?

I have followed the following indications:

  1. Using the form import function (Rule1.drl). This solution does not work because the class is instantiated in drools and requires static methods to be executed.
  2. Using a global Session variable (Rule2.drl). This solution throws me an exception at "runtime" indicating that it is not the same class type.

Any ideas on how to use it?

As

File: Rule1.drl

package com.mycompany.alerts.Alert;

import function com.mycompany.alerts.service.SecurityService.notifyAlert;

rule "Activate Alert Type"
salience 9000
when
  $alert: Alert(type == "TYPE1") 
then
  System.out.println("Running action:" + drools.getRule().getName());
  $alert.setActive(Boolean.TRUE);
  notifyAlert($alert.getStatus(),$alert.getSmsNumber());    
  System.out.println("End action:" + drools.getRule().getName());
end

File: Rule2.drl

package com.mycompany.alerts.Alert;

global com.mycompany.alerts.service.SecurityService securityService;

rule "Activate Alert Type 2"
salience 9000
when
  $alert: Alert(type == "TYPE2") 
then
  System.out.println("Running action:" + drools.getRule().getName());
  $alert.setActive(Boolean.TRUE);
  securityService.notifyAlert($alert.getStatus(),$alert.getSmsNumber());    
  System.out.println("End action:" + drools.getRule().getName());
end

File: SecurityService.java

package com.mycompany.alerts.service;

import com.mycompany.alerts.service.UserRepository;

@Service
@Transactional
public class SecurityService {

    private final Logger log = LoggerFactory.getLogger(SecurityService.class);

    private final UserRepository userRepository;

    public SecurityService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void notifyAlert(String status, String sms) {
         System.out.println("Alert notify with:" + status + " sms:" + sms);
    }

}
like image 811
Hector Gomez Avatar asked Apr 11 '17 12:04

Hector Gomez


People also ask

How rules are executed in Drools?

Let's quickly summarize how Drools works. Rules are written on . drl files, facts or POJOs are inserted in the Knowledge Base, then rules are applied on each fact. If a "When" part of a rule satisfies a fact, the "Then" part will execute.

How do you fire a specific rule in Drools?

In any case, the Customer has to be identified by a fact. To associcate a Customer with rules you need: class Customer { private String name; private List<String> rules; //... } So you are saying to create agenda for each customer and fire the rules based on agenda...

How can you improve Drools performance of rule execution?

Literal Restrictions using the operator '==' provide for faster execution as we can index using hashing to improve performance. One can bind variables to facts and their fields and then use them in subsequent field constraints. A bound variable is called a declaration.


1 Answers

You can use the setGlobal function of kieRuntime as:

kieRuntime.setGlobal("securityService", securityService);

then you can declare/use this variable in your drl file as :

global SecurityService securityService.

PS:- KieRuntime object can be obtained as: KieRuntime kieRuntime = (KieRuntime) kieSssion;

like image 178
Abhishek Patyal Avatar answered Sep 28 '22 02:09

Abhishek Patyal