Red Hat Training
A Red Hat training course is available for Red Hat Process Automation Manager
Designing a decision service using DRL rules
Red Hat Customer Content Services
brms-docs@redhat.com
Abstract
Preface
As a business rules developer, you can define business rules using the DRL (Drools Rule Language) designer in Business Central. DRL rules are defined directly in free-form .drl
text files instead of in a guided or tabular format like other types of rule assets in Business Central. These DRL files form the core of the decision service for your project.
Prerequisite
The team and project for the DRL rules have been created in Business Central. Each asset is associated with a project assigned to a team. For details, see Getting started with decision services.
Chapter 1. Rule-authoring assets in Red Hat Process Automation Manager
Red Hat Process Automation Manager provides several assets that you can use to create business rules for your decision service. Each rule-authoring asset has different advantages, and you might prefer to use one or a combination of multiple assets depending on your goals and needs.
The following table highlights each rule-authoring asset in Business Central to help you decide or confirm the best method for creating rules in your decision service.
Table 1.1. Rule-authoring assets in Business Central
Asset | Highlights | Documentation |
---|---|---|
Guided decision tables |
| |
Uploaded decision tables |
| |
Guided rules |
| |
Guided rule templates |
| |
DRL rules |
|
Chapter 2. DRL (Drools Rule Language) rules
DRL (Drools Rule Language) rules are business rules that you define directly in .drl
text files. These DRL files are the source in which all other rule assets in Business Central are ultimately rendered. You can create and manage DRL files within the Business Central interface, or create them externally using Red Hat Developer Studio, Java objects, or Maven archetypes. A DRL file can contain one or more rules that define at minimum the rule conditions (when
) and actions (then
). The DRL designer in Business Central provides syntax highlighting for Java, DRL, and XML.
All data objects related to a DRL rule must be in the same project package as the DRL rule in Business Central. Assets in the same package are imported by default. Existing assets in other packages can be imported with the DRL rule.
Chapter 3. Data objects
Data objects are the building blocks for the rule assets that you create. Data objects are custom data types implemented as Java objects in specified packages of your project. For example, you might create a Person
object with data fields Name
, Address
, and DateOfBirth
to specify personal details for loan application rules. These custom data types determine what data your assets and your decision service are based on.
3.1. Creating data objects
The following procedure is a generic overview of creating data objects. It is not specific to a particular business process.
Procedure
- In Business Central, go to Menu → Design → Projects and click the project name.
- Click Add Asset → Data Object.
Enter a unique Data Object name and select the Package where you want the data object to be available for other rule assets. Data objects with the same name cannot exist in the same package. The package that you specify must be the same package where the rule assets that require those data objects have been assigned or will be assigned.
Importing data objects from other packagesYou can also import an existing data object from another package into the package of the rule asset. Select the relevant rule asset within the project and in the asset designer, go to Data Objects → New item to select the object to be imported.
- To make your data object persistable, select the Persistable checkbox. Persistable data objects are able to be stored in a database according to the JPA specification. The default JPA is Hibernate.
- Click Ok.
In the data object designer, click add field to add a field to the object with the attributes Id, Label, and Type. Required attributes are marked with an asterisk (*).
- Id: Enter the unique ID of the field.
- Label: (Optional) Enter a label for the field.
- Type: Enter the data type of the field.
List: Select this check box to enable the field to hold multiple items for the specified type.
Figure 3.1. Add data fields to a data object
Click Create to add the new field, or click Create and continue to add the new field and continue adding other fields.
NoteTo edit a field, select the field row and use the general properties on the right side of the screen.
Chapter 4. Creating DRL rules in Business Central
You can create and manage DRL rules for your project in Business Central. In each DRL rule file, you define rule conditions, actions, and other components related to the rule, based on the data objects you create or import in the package.
Procedure
- Go to Menu → Design → Projects and click the project name.
- Click Add Asset → DRL file.
Enter an informative DRL file name and select the appropriate Package. The package that you specify must be the same package where the required data objects have been assigned or will be assigned.
You can also select Show declared DSL sentences if any domain specific language (DSL) assets have been defined in your project. These DSL assets will then become usable objects for conditions and actions that you define in the DRL designer.
Click Ok to create the rule asset.
The new DRL file is now listed in the DRL panel of the Project Explorer, or in the DSLR panel if you selected the Show declared DSL sentences option. The package to which you assigned this DRL file is listed at the top of the file.
-
In the Fact types list in the left panel of the DRL designer, confirm that all data objects and data object fields (expand each) required for your rules are listed. If not, you can either import relevant data objects from other packages by using
import
statements in the DRL file, or create data objects within your package. After all data objects are in place, return to the Model tab of the DRL designer and define the DRL file with any of the following components:
Components of a DRL file
package //automatic import function //optional query //optional declare //optional rule rule ...
-
package
: (automatic) This was defined for you when you created the DRL file and selected the package. import
: Use this to identify the data objects from either this package or another package that you want to use in the DRL file. Specify the package and data object in the formatpackage.name.object.name
, one import per line.Importing data objects
import mortgages.mortgages.LoanApplication;
function
: (optional) Use this to include a function to be used by rules in the DRL file. Functions put semantic code in your rule source file. Functions are especially useful if an action (then
) part of a rule is used repeatedly and only the parameters differ for each rule. Above the rules in the DRL file, you can declare the function or import a static method as a function, and then use the function by name in an action (then
) part of the rule.Declaring and using a function with a rule (option 1)
function String hello(String applicantName) { return "Hello " + applicantName + "!"; } rule "Using a function" when eval( true ) then System.out.println( hello( "James" ) ); end
Importing and using the function with a rule (option 2)
import function my.package.applicant.hello; rule "Using a function" when eval( true ) then System.out.println( hello( "James" ) ); end
query
: (optional) Use this to search the process engine for facts related to the rules in the DRL file. Queries search for a set of defined conditions and do not requirewhen
orthen
specifications. Query names are global to the KIE base and therefore must be unique among all other rule queries in the project. To return the results of a query, construct a traditionalQueryResults
definition usingksession.getQueryResults("name")
, where"name"
is the query name. This returns a list of query results, which enable you to retrieve the objects that matched the query. Define the query and query results parameters above the rules in the DRL file.Query and query results for people under the age of 21, with a rule
query "people under the age of 21" person : Person( age < 21 ) end QueryResults results = ksession.getQueryResults( "people under the age of 21" ); System.out.println( "we have " + results.size() + " people under the age of 21" ); rule "Underage" when application : LoanApplication( ) Applicant( age < 21 ) then application.setApproved( false ); application.setExplanation( "Underage" ); end
declare
: (optional) Use this to declare a new fact type to be used by rules in the DRL file. The default fact type in thejava.lang
package of Red Hat Process Automation Manager isObject
, but you can declare other types in DRL files as needed. Declaring fact types in DRL files enables you to define a new fact model directly in the process engine, without creating models in a lower-level language like Java.Declaring and using a new fact type
declare Person name : String dateOfBirth : java.util.Date address : Address end rule "Using a declared type" when $p : Person( name == "James" ) then // Insert Mark, who is a customer of James. Person mark = new Person(); mark.setName("Mark"); insert( mark ); end
rule
: Use this to define each rule in the DRL file. Rules consist of a rule name in the formatrule "name"
, followed by optional attributes that define rule behavior (such assalience
orno-loop
), followed bywhen
andthen
definitions. The same rule name cannot be used more than once in the same package. Thewhen
part of the rule contains the conditions that must be met to execute an action. For example, if a bank requires loan applicants to have over 21 years of age, then thewhen
condition for anUnderage
rule would beApplicant( age < 21 )
. Thethen
part of the rule contains the actions to be performed when the conditional part of the rule has been met. For example, when the loan applicant is under 21 years old, thethen
action would besetApproved( false )
, declining the loan because the applicant is under age. Conditions (when
) and actions (then
) consist of a series of stated fact patterns with optional constraints, bindings, and other supported DRL elements, based on the available data objects in the package. These patterns determine how defined objects are affected by the rule.Rule for loan application age limit
rule "Underage" salience 15 dialect "mvel" when application : LoanApplication( ) Applicant( age < 21 ) then application.setApproved( false ); application.setExplanation( "Underage" ); end
At minimum, each DRL file must specify the
package
,import
, andrule
components. All other components are optional.Figure 4.1. Sample DRL file with required components and optional rule attributes
-
- After you define all components of the rule, click Validate in the upper-right toolbar of the DRL designer to validate the DRL file. If the file validation fails, address any problems described in the error message, review all syntax and components in the DRL file, and try again to validate the file until the file passes.
- Click Save in the DRL designer to save your work.
For more details about adding conditions to DRL rules, see Section 4.1, “Adding WHEN conditions in DRL rules”.
For more details about adding actions to DRL rules, see Section 4.2, “Adding THEN actions in DRL rules”.
4.1. Adding WHEN conditions in DRL rules
The when
part of the rule contains the conditions that must be met to execute an action. For example, if a bank requires loan applicants to have over 21 years of age, then the when
condition of an Underage
rule would be Applicant( age < 21 )
. Conditions consist of a series of stated patterns and constraints, with optional bindings and other supported DRL elements, based on the available data objects in the package.
Prerequisites
-
The
package
is defined at the top of the DRL file. This should have been done for you when you created the file. -
The
import
list of data objects used in the rule is defined below thepackage
line of the DRL file. Data objects can be from this package or from another package in Business Central. -
The
rule
name is defined in the formatrule "name"
below thepackage
,import
, and other lines that apply to the entire DRL file. The same rule name cannot be used more than once in the same package. Optional rule attributes (such assalience
orno-loop
) that define rule behavior are below the rule name, before thewhen
section.
Procedure
In the DRL designer, enter
when
within the rule to begin adding condition statements. Thewhen
section consists of zero or more fact patterns that define conditions for the rule.If the
when
section is empty, then actions in thethen
section are executed every time afireAllRules()
call is made in the process engine. This is useful if you want to use rules to set up the process engine state.Rule without conditions
rule "bootstrap" when // empty then // actions to be executed once insert( new Applicant() ); end // The above rule is internally rewritten as: rule "bootstrap" when eval( true ) then insert( new Applicant() ); end
Enter a pattern for the first condition to be met, with optional constraints, bindings, and other supported DRL elements. A basic pattern format is
patternBinding : patternType ( constraints )
. Patterns are based on the available data objects in the package and define the conditions to be met in order to trigger actions in thethen
section.Simple pattern: A simple pattern with no constraints matches against a fact of the given type. For example, the following condition is only that the applicant exists.
when Applicant( )
Pattern with constraints: A pattern with constraints matches against a fact of the given type and the additional restrictions in parentheses that are true or false. For example, the following condition is that the applicant is under the age of 21.
when Applicant( age < 21 )
Pattern with binding: A binding on a pattern is a shorthand reference that other components of the rule can use to refer back to the defined pattern. For example, the following binding
a
onLoanApplication
is used in a related action for underage applicants.when a : LoanApplication( ) Applicant( age < 21 ) then a.setApproved( false ); a.setExplanation( "Underage" )
Continue defining all condition patterns that apply to this rule. The following are some of the keyword options for defining DRL conditions:
and
: Use this to group conditional components into a logical conjunction. Infix and prefixand
are supported. By default, all listed conditions or actions are combined withand
when no conjunction is specified.a : LoanApplication( ) and Applicant( age < 21 ) a : LoanApplication( ) and Applicant( age < 21 ) a : LoanApplication( ) Applicant( age < 21 ) // All of the above are the same.
or
: Use this to group conditional components into a logical disjunction. Infix and prefixor
are supported.Bankruptcy( amountOwed == 100000 ) or IncomeSource( amount == 20000 ) Bankruptcy( amountOwed == 100000 ) or IncomeSource( amount == 20000 )
exists
: Use this to specify facts and constraints that must exist. Note that this does not mean that a fact exists, but that a fact must exist. This option is triggered on only the first match, not subsequent matches.exists (Bankruptcy( yearOfOccurrence > 1990 || amountOwed > 10000 ))
not
: Use this to specify facts and constraints that must not exist.not (Applicant( age < 21 ))
forall
: Use this to set up a construct where all facts that match the first pattern match all the remaining patterns.forall( app : Applicant( age < 21 ) Applicant( this == app, status = 'underage' ) )
from
: Use this to specify a source for data to be matched by the conditional pattern.Applicant( ApplicantAddress : address ) Address( zipcode == "23920W" ) from ApplicantAddress
entry-point
: Use this to define anEntry Point
corresponding to a data source for the pattern. Typically used withfrom
.Applicant( ) from entry-point "LoanApplication"
collect
: Use this to define a collection of objects that the construct can use as part of the condition. In the example, all pending applications in the process engine for each given mortgage are grouped inArrayLists
. If three or more pending applications are found, the rule is executed.m : Mortgage() a : ArrayList( size >= 3 ) from collect( LoanApplication( Mortgage == m, status == 'pending' ) )
accumulate
: Use this to iterate over a collection of objects, execute custom actions for each of the elements, and return one or more result objects (if the constraints evaluate totrue
). This option is a more flexible and powerful form ofcollect
. Use the formataccumulate( <source pattern>; <functions> [;<constraints>] )
. In the example,min
,max
, andaverage
are accumulate functions that calculate the minimum, maximum and average temperature values over all the readings for each sensor. Other supported functions includecount
,sum
,variance
,standardDeviation
,collectList
, andcollectSet
.s : Sensor() accumulate( Reading( sensor == s, temp : temperature ); min : min( temp ), max : max( temp ), avg : average( temp ); min < 20, avg > 70 )
Advanced DRL optionsThese are examples of basic keyword options and pattern constructs for defining conditions. For more advanced DRL options and syntax supported in the DRL designer, see the Drools Documentation online.
- After you define all condition components of the rule, click Validate in the upper-right toolbar of the DRL designer to validate the DRL file. If the file validation fails, address any problems described in the error message, review all syntax and components in the DRL file, and try again to validate the file until the file passes.
- Click Save in the DRL designer to save your work.
4.2. Adding THEN actions in DRL rules
The then
part of the rule contains the actions to be performed when the conditional part of the rule has been met. For example, when a loan applicant is under 21 years old, the then
action of an Underage
rule would be setApproved( false )
, declining the loan because the applicant is under age. Actions execute consequences based on the rule conditions and on available data objects in the package.
Prerequisites
-
The
package
is defined at the top of the DRL file. This should have been done for you when you created the file. -
The
import
list of data objects used in the rule is defined below thepackage
line of the DRL file. Data objects can be from this package or from another package in Business Central. -
The
rule
name is defined in the formatrule "name"
below thepackage
,import
, and other lines that apply to the entire DRL file. The same rule name cannot be used more than once in the same package. Optional rule attributes (such assalience
orno-loop
) that define rule behavior are below the rule name, before thewhen
section.
Procedure
-
In the DRL designer, enter
then
after thewhen
section of the rule to begin adding action statements. Enter one or more actions to be executed on fact patterns based on the conditions for the rule.
The following are some of the keyword options for defining DRL actions:
and
: Use this to group action components into a logical conjunction. Infix and prefixand
are supported. By default, all listed conditions or actions are combined withand
when no conjunction is specified.application.setApproved ( false ) and application.setExplanation( "has been bankrupt" ); application.setApproved ( false ); and application.setExplanation( "has been bankrupt" ); application.setApproved ( false ); application.setExplanation( "has been bankrupt" ); // All of the above are the same.
set
: Use this to set the value of a field.application.setApproved ( false ); application.setExplanation( "has been bankrupt" );
modify
: Use this to specify fields to be modified for a fact and to notify the process engine of the change.modify( LoanApplication ) { setAmount( 100 ) }
update
: Use this to specify fields and the entire related fact to be modified and to notify the process engine of the change. After a fact has changed, you must callupdate
before changing another fact that might be affected by the updated values. Themodify
keyword avoids this added step.update( LoanApplication ) { setAmount( 100 ) }
delete
: Use this to remove an object from the process engine. The keywordretract
is also supported in the DRL designer and executes the same action, butdelete
is preferred for consistency with the keywordinsert
.delete( LoanApplication );
insert
: Use this to insert anew
fact and define resulting fields and values as needed for the fact.insert( new Applicant() );
insertLogical
: Use this to insert anew
fact logically into the process engine and define resulting fields and values as needed for the fact. The Red Hat Process Automation Manager process engine is responsible for logical decisions on insertions and retractions of facts. After regular or stated insertions, facts have to be retracted explicitly. After logical insertions, facts are automatically retracted when the conditions that originally asserted the facts are no longer true.insertLogical( new Applicant() );
Advanced DRL optionsThese are examples of basic keyword options and pattern constructs for defining actions. For more advanced DRL options and syntax supported in the DRL designer, see the Drools Documentation online.
- After you define all action components of the rule, click Validate in the upper-right toolbar of the DRL designer to validate the DRL file. If the file validation fails, address any problems described in the error message, review all syntax and components in the DRL file, and try again to validate the file until the file passes.
- Click Save in the DRL designer to save your work.
4.2.1. Rule attributes
Rule attributes are additional specifications that you can add to business rules to modify rule behavior. The following table lists the names and supported values of the attributes that you can assign to rules:
Table 4.1. Rule attributes
Attribute | Value |
---|---|
| An integer defining the priority of the rule. Rules with a higher salience value are given higher priority when ordered in the activation queue.
Example: |
| A Boolean value. When the option is selected, the rule is enabled. When the option is not selected, the rule is disabled.
Example: |
|
A string containing a date and time definition. The rule can be activated only if the current date and time is after a
Example: |
|
A string containing a date and time definition. The rule cannot be activated if the current date and time is after the
Example: |
| A Boolean value. When the option is selected, the rule cannot be reactivated (looped) if a consequence of the rule re-triggers a previously met condition. When the condition is not selected, the rule can be looped in these circumstances.
Example: |
| A string identifying an agenda group to which you want to assign the rule. Agenda groups allow you to partition the agenda to provide more execution control over groups of rules. Only rules in an agenda group that has acquired a focus are able to be activated.
Example: |
| A string identifying an activation (or XOR) group to which you want to assign the rule. In activation groups, only one rule can be activated. The first rule to fire will cancel all pending activations of all rules in the activation group.
Example: |
| A long integer value defining the duration of time in milliseconds after which the rule can be activated, if the rule conditions are still met.
Example: |
|
A string identifying either
Example: |
| A Quartz calendar definition for scheduling the rule.
Example: |
| A Boolean value, applicable only to rules within agenda groups. When the option is selected, the next time the rule is activated, a focus is automatically given to the agenda group to which the rule is assigned.
Example: |
|
A Boolean value, applicable only to rules within rule flow groups or agenda groups. When the option is selected, the next time the ruleflow group for the rule becomes active or the agenda group for the rule receives a focus, the rule cannot be activated again until the ruleflow group is no longer active or the agenda group loses the focus. This is a stronger version of the
Example: |
| A string identifying a rule flow group. In rule flow groups, rules can fire only when the group is activated by the associated rule flow.
Example: |
|
A string identifying either
Example: |
Chapter 5. Executing rules
After you create rules in Business Central, you can build and deploy your project and execute rules locally or on Process Server to test your rules.
Procedure
- In Business Central, go to Menu → Design → Projects and click the project name.
- In the upper-right corner, click Build and then Deploy to build the project and deploy it to Process Server. If the build fails, address any problems described in the Alerts panel at the bottom of the screen. For more information about deploying projects, see Packaging and deploying a Red Hat Process Automation Manager project.
Open the
pom.xml
file of your client application and add the following dependencies, if not added already:-
kie-ci
: Enables your client application to load Business Central project data locally usingReleaseId
-
kie-server-client
: Enables your client application to interact remotely with assets on Process Server -
slf4j
: (Optional) Enables your client application to use Simple Logging Facade for Java (SLF4J) to return debug logging information after you interact with Process Server
Example dependencies for Red Hat Process Automation Manager 7.0 in a client application
pom.xml
file:// For local execution: <dependency> <groupId>org.kie</groupId> <artifactId>kie-ci</artifactId> <version>7.7.0.Final-redhat-7</version> </dependency> // For remote execution on Process Server: <dependency> <groupId>org.kie.server</groupId> <artifactId>kie-server-client</artifactId> <version>7.7.0.Final-redhat-7</version> </dependency> // For debug logging (optional): <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency>
NoteFor available versions of these artifacts, search the group ID and artifact ID in the MVNRepository online and select the Redhat GA tab where applicable. For more information about Maven dependencies and using the Bill of Materials (BOM) in Red Hat Process Automation Manager, see What is the mapping between Red Hat Process Automation Manager and Maven library version?.
-
Ensure that the dependencies for artifacts containing model classes are defined in the client application
pom.xml
file exactly as they appear in thepom.xml
file of the deployed project. If dependencies for model classes differ between the client application and your projects, execution errors can occur.To view the project
pom.xml
in Business Central, select any existing asset in the project and then in the Project Explorer menu on the left side of the screen, click the Customize View gear icon and select Repository View → pom.xml.For example, the following is a
Person
class dependency as it appears in both the client and deployed projectpom.xml
files:<dependency> <groupId>com.sample</groupId> <artifactId>Person</artifactId> <version>1.0.0</version> </dependency>
If you added the
slf4j
dependency to the client applicationpom.xml
file for debug logging, create asimplelogger.properties
file on the relevant classpath (for example, insrc/main/resources/META-INF
in Maven) with the following content:org.slf4j.simpleLogger.defaultLogLevel=debug
In your client application, create a
.java
main class containing the necessary imports and amain()
method to load the knowledge base, insert facts, and execute the rules.For example, a
Person
object in a project contains getter and setter methods to set and retrieve the first name, last name, hourly rate, and the wage of a person. The followingWage
rule in a project calculates the wage and hourly rate values and displays a message based on the result:package com.sample; import com.sample.Person; dialect "java" rule "Wage" when Person(hourlyRate * wage > 100) Person(name : firstName, surname : lastName) then System.out.println("Hello" + " " + name + " " + surname + "!"); System.out.println("You are rich!"); end
To test this rule locally outside of Process Server (if desired), configure the
.java
class to import KIE services, a KIE container, and a KIE session, and then use themain()
method to fire all rules against a defined fact model:Executing rules locally
import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; public class RulesTest { public static final void main(String[] args) { try { // Identify the project in the local repository: ReleaseId rid = new ReleaseId(); rid.setGroupId("com.myspace"); rid.setArtifactId("MyProject"); rid.setVersion("1.0.0"); // Load the knowledge base: KieServices ks = KieServices.Factory.get(); KieContainer kContainer = ks.newKieContainer(rid); KieSession kSession = kContainer.newKieSession(); // Set up the fact model: Person p = new Person(); p.setWage(12); p.setFirstName("Tom"); p.setLastName("Summers"); p.setHourlyRate(10); // Insert the person into the session: kSession.insert(p); // Fire all rules: kSession.fireAllRules(); kSession.dispose(); } catch (Throwable t) { t.printStackTrace(); } } }
To test this rule on Process Server, configure the
.java
class with the imports and rule execution information similarly to the local example, and additionally specify KIE services configuration and KIE services client details:Executing rules on Process Server
package com.sample; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.kie.api.command.BatchExecutionCommand; import org.kie.api.command.Command; import org.kie.api.KieServices; import org.kie.api.runtime.ExecutionResults; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; import org.kie.server.api.marshalling.MarshallingFormat; import org.kie.server.api.model.ServiceResponse; import org.kie.server.client.KieServicesClient; import org.kie.server.client.KieServicesConfiguration; import org.kie.server.client.KieServicesFactory; import org.kie.server.client.RuleServicesClient; import com.sample.Person; public class RulesTest { private static final String containerName = "testProject"; private static final String sessionName = "myStatelessSession"; public static final void main(String[] args) { try { // Define KIE services configuration and client: Set<Class<?>> allClasses = new HashSet<Class<?>>(); allClasses.add(Person.class); String serverUrl = "http://$HOST:$PORT/kie-server/services/rest/server"; String username = "$USERNAME"; String password = "$PASSWORD"; KieServicesConfiguration config = KieServicesFactory.newRestConfiguration(serverUrl, username, password); config.setMarshallingFormat(MarshallingFormat.JAXB); config.addExtraClasses(allClasses); KieServicesClient kieServicesClient = KieServicesFactory.newKieServicesClient(config); // Set up the fact model: Person p = new Person(); p.setWage(12); p.setFirstName("Tom"); p.setLastName("Summers"); p.setHourlyRate(10); // Insert Person into the session: KieCommands kieCommands = KieServices.Factory.get().getCommands(); List<Command> commandList = new ArrayList<Command>(); commandList.add(kieCommands.newInsert(p, "personReturnId")); // Fire all rules: commandList.add(kieCommands.newFireAllRules("numberOfFiredRules")); BatchExecutionCommand batch = kieCommands.newBatchExecution(commandList, sessionName); // Use rule services client to send request: RuleServicesClient ruleClient = kieServicesClient.getServicesClient(RuleServicesClient.class); ServiceResponse<ExecutionResults> executeResponse = ruleClient.executeCommandsWithResults(containerName, batch); System.out.println("number of fired rules:" + executeResponse.getResult().getValue("numberOfFiredRules")); } catch (Throwable t) { t.printStackTrace(); } } }
Run the configured
.java
class from your project directory. You can run the file in your development platform (such as Red Hat JBoss Developer Studio) or in the command line.Example Maven execution (within project directory):
mvn clean install exec:java -Dexec.mainClass="com.sample.app.RulesTest"
Example Java execution (within project directory)
javac -classpath "./$DEPENDENCIES/*:." RulesTest.java java -classpath "./$DEPENDENCIES/*:." RulesTest
- Review the rule execution status in the command line and in the server log. If any rules do not execute as expected, review the configured rules in the project and the main class configuration to validate the data provided.
Chapter 6. Other methods for creating DRL rules
As an alternative to creating and managing DRL rules within the Business Central interface, you can create DRL rule files in external standalone projects using Red Hat Developer Studio, Java objects, or Maven archetypes. These standalone projects can then be integrated as knowledge JAR (KJAR) dependencies in existing Red Hat Process Automation Manager projects in Business Central. The DRL files in your standalone project must contain at minimum the required package
specification, import
lists, and rule
definitions. Any other DRL components, such as global variables and functions, are optional. All data objects related to a DRL rule must be included with your standalone DRL project or deployment.
6.1. Creating and executing DRL rules in Red Hat JBoss Developer Studio
You can use Red Hat JBoss Developer Studio to create DRL files with rules and integrate the files with your Red Hat Process Automation Manager decision service. This method of creating DRL rules is helpful if you already use Red Hat Developer Studio for your decision service and want to continue with the same work flow. If you do not already use this method, then the Business Central interface of Red Hat Process Automation Manager is recommended for creating DRL files and other rule assets.
Prerequisite
Red Hat JBoss Developer Studio has been installed from the Red Hat Customer Portal.
Procedure
- In the Red Hat JBoss Developer Studio, click File → New → Project.
- In the New Project window that opens, select Drools → Drools Project and click Next.
- Click the second icon to Create a project and populate it with some example files to help you get started quickly. Click Next.
Enter a Project name and select the Maven radio button as the project building option. The GAV values are generated automatically. You can update these values as needed for your project:
-
Group ID:
com.sample
-
Artifact ID:
my-project
-
Version:
1.0.0-SNAPSHOT
-
Group ID:
Click Finish to create the project.
This configuration sets up a basic project structure, class path, and sample rules. The following is an overview of the project structure:
my-project `-- src/main/java | `-- com.sample | `-- DecisionTableTest.java | `-- DroolsTest.java | `-- ProcessTest.java | `-- src/main/resources | `-- dtables | `-- Sample.xls | `-- process | `-- sample.bpmn | `-- rules | `-- Sample.drl | `-- META-INF | `-- JRE System Library | `-- Maven Dependencies | `-- Drools Library | `-- src | `-- target | `-- pom.xml
Notice the following elements:
-
A
Sample.drl
rule file in thesrc/main/resources
directory, containing an exampleHello World
andGoodBye
rules. -
A
DroolsTest.java
file under thesrc/main/java
directory in thecom.sample
package. TheDroolsTest
class can be used to execute theSample.drl
rule. -
The
Drools Library
directory, which acts as a custom class path containing JAR files necessary for execution.
You can edit the existing
Sample.drl
file andDroolsTest.java
files with new configurations as needed, or create new rule and object files. In this procedure, you are creating a new rule and new Java objects.-
A
Create a Java object on which the rule or rules will operate.
In this example, a
Person.java
file is created inmy-project/src/main/java/com.sample
. ThePerson
class contains getter and setter methods to set and retrieve the first name, last name, hourly rate, and the wage of a person:public class Person { private String firstName; private String lastName; private Integer hourlyRate; private Integer wage; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Integer getHourlyRate() { return hourlyRate; } public void setHourlyRate(Integer hourlyRate) { this.hourlyRate = hourlyRate; } public Integer getWage(){ return wage; } public void setWage(Integer wage){ this.wage = wage; } }
- Click File → Save to save the file.
Create a rule file in
.drl
format inmy-project/src/main/resources/rules
. The DRL file must contain at minimum a package specification, an import list of data objects to be used by the rule or rules, and one or more rules withwhen
conditions andthen
actions.The following
Wage.drl
file contains aWage
rule that imports thePerson
class, calculates the wage and hourly rate values, and displays a message based on the result:package com.sample; import com.sample.Person; dialect "java" rule "Wage" when Person(hourlyRate * wage > 100) Person(name : firstName, surname : lastName) then System.out.println("Hello" + " " + name + " " + surname + "!"); System.out.println("You are rich!"); end
- Click File → Save to save the file.
Create a main class and save it to the same directory as the Java object that you created. The main class will load the knowledge base and execute rules.
NoteYou can also add the
main()
method andPerson
class within a single Java object file, similar to theDroolsTest.java
sample file.In the main class, add the required
import
statements to import KIE services, a KIE container, and a KIE session. Then load the knowledge base, insert facts, and execute the rule from themain()
method that passes the fact model to the rule.In this example, a
RulesTest.java
file is created inmy-project/src/main/java/com.sample
with the required imports andmain()
method:package com.sample; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; public class RulesTest { public static final void main(String[] args) { try { // Load the knowledge base: KieServices ks = KieServices.Factory.get(); KieContainer kContainer = ks.getKieClasspathContainer(); KieSession kSession = kContainer.newKieSession(); // Set up the fact model: Person p = new Person(); p.setWage(12); p.setFirstName("Tom"); p.setLastName("Summers"); p.setHourlyRate(10); // Insert the person into the session: kSession.insert(p); // Fire all rules: kSession.fireAllRules(); kSession.dispose(); } catch (Throwable t) { t.printStackTrace(); } } }
- Click File → Save to save the file.
- After you create and save all DRL assets in your project, right-click your project folder and select Run As → Java Application to build the project. If the project build fails, address any problems described in the Problems tab of the lower window in Developer Studio, and try again to validate the project until the project builds.
If Java Application is not an option when you right-click your project and select Run As, then go to Run As → Run Configurations, right-click Java Application, and click New. Then in the Main tab, browse for and select your Project and the associated Main class. Click Apply and then click Run to test the project. The next time you right-click your project folder, the Java Application option will appear.
To integrate the new rule assets with an existing project in Red Hat Process Automation Manager, you can compile the new project as a knowledge JAR (KJAR) and add it as a dependency in the pom.xml
file of the project in Business Central.
6.2. Creating and executing DRL rules using Java
You can use Java objects to create DRL files with rules and integrate the objects with your Red Hat Process Automation Manager decision service. This method of creating DRL rules is helpful if you already use external Java objects for your decision service and want to continue with the same work flow. If you do not already use this method, then the Business Central interface of Red Hat Process Automation Manager is recommended for creating DRL files and other rule assets.
Procedure
Create a Java object on which the rule or rules will operate.
In this example, a
Person.java
file is created in a directorymy-project
. ThePerson
class contains getter and setter methods to set and retrieve the first name, last name, hourly rate, and the wage of a person:public class Person { private String firstName; private String lastName; private Integer hourlyRate; private Integer wage; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Integer getHourlyRate() { return hourlyRate; } public void setHourlyRate(Integer hourlyRate) { this.hourlyRate = hourlyRate; } public Integer getWage(){ return wage; } public void setWage(Integer wage){ this.wage = wage; } }
Create a rule file in
.drl
format under themy-project
directory. The DRL file must contain at minimum a package specification (if applicable), an import list of data objects to be used by the rule or rules, and one or more rules withwhen
conditions andthen
actions.The following
Wage.drl
file contains aWage
rule that calculates the wage and hourly rate values and displays a message based on the result:package com.sample; import com.sample.Person; dialect "java" rule "Wage" when Person(hourlyRate * wage > 100) Person(name : firstName, surname : lastName) then System.out.println("Hello" + " " + name + " " + surname + "!"); System.out.println("You are rich!"); end
- Create a main class and save it to the same directory as the Java object that you created. The main class will load the knowledge base and execute rules.
In the main class, add the required
import
statements to import KIE services, a KIE container, and a KIE session. Then load the knowledge base, insert facts, and execute the rule from themain()
method that passes the fact model to the rule.In this example, a
RulesTest.java
file is created inmy-project
with the required imports andmain()
method:import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; public class RulesTest { public static final void main(String[] args) { try { // Load the knowledge base: KieServices ks = KieServices.Factory.get(); KieContainer kContainer = ks.getKieClasspathContainer(); KieSession kSession = kContainer.newKieSession(); // Set up the fact model: Person p = new Person(); p.setWage(12); p.setFirstName("Tom"); p.setLastName("Summers"); p.setHourlyRate(10); // Insert the person into the session: kSession.insert(p); // Fire all rules: kSession.fireAllRules(); kSession.dispose(); } catch (Throwable t) { t.printStackTrace(); } } }
-
Download the Red Hat Process Automation Manager 7.0.0 Source Distribution ZIP file from the Red Hat Customer Portal and extract it under
my-project/pam-engine-jars/
. In the
my-project/META-INF
directory, create akmodule.xml
metadata file with the following content:<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://www.drools.org/xsd/kmodule"> </kmodule>
This
kmodule.xml
file is a KIE module descriptor that selects resources to knowledge bases and configures sessions. This file enables you to define and configure one or more KIE bases, and to include DRL files from specificpackages
in a specific KIE base. You can also create one or more KIE sessions from each KIE base.The following example shows a more advanced
kmodule.xml
file:<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.drools.org/xsd/kmodule"> <kbase name="KBase1" default="true" eventProcessingMode="cloud" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg1"> <ksession name="KSession1_1" type="stateful" default="true" /> <ksession name="KSession1_2" type="stateful" default="true" beliefSystem="jtms" /> </kbase> <kbase name="KBase2" default="false" eventProcessingMode="stream" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1"> <ksession name="KSession2_1" type="stateless" default="true" clockType="realtime"> <fileLogger file="debugInfo" threaded="true" interval="10" /> <workItemHandlers> <workItemHandler name="name" type="new org.domain.WorkItemHandler()" /> </workItemHandlers> <listeners> <ruleRuntimeEventListener type="org.domain.RuleRuntimeListener" /> <agendaEventListener type="org.domain.FirstAgendaListener" /> <agendaEventListener type="org.domain.SecondAgendaListener" /> <processEventListener type="org.domain.ProcessListener" /> </listeners> </ksession> </kbase> </kmodule>
This example defines two KIE bases. Two KIE sessions are instantiated from the
KBase1
KIE base, and one KIE session fromKBase2
. The KIE session fromKBase2
is astateless
KIE session, which means that data from a previous invocation of the KIE session (the previous session state) is discarded between session invocations. Specificpackages
of rule assets are included with both KIE bases. When you specify packages in this way, you must organize your DRL files in a folder structure that reflects the specified packages.After you create and save all DRL assets in your Java object, navigate to the
my-project
directory in the command line and run the following command to build your Java files. ReplaceRulesTest.java
with the name of your Java main class.javac -classpath "./pam-engine-jars/*:." RulesTest.java
If the build fails, address any problems described in the command line error messages and try again to validate the Java object until the object passes.
After your Java files build successfully, run the following command to execute the rules locally. Replace
RulesTest
with the prefix of your Java main class.java -classpath "./pam-engine-jars/*:." RulesTest
- Review the rules to ensure that they executed properly, and address any needed changes in the Java files.
To integrate the new rule assets with an existing project in Red Hat Process Automation Manager, you can compile the new Java project as a knowledge JAR (KJAR) and add it as a dependency in the pom.xml
file of the project in Business Central.
6.3. Creating and executing DRL rules using Maven
You can use Maven archetypes to create DRL files with rules and integrate the archetypes with your Red Hat Process Automation Manager decision service. This method of creating DRL rules is helpful if you already use external Maven archetypes for your decision service and want to continue with the same work flow. If you do not already use this method, then the Business Central interface of Red Hat Process Automation Manager is recommended for creating DRL files and other rule assets.
Procedure
Navigate to a directory where you want to create a Maven archetype and run the following command:
mvn archetype:generate -DgroupId=com.sample.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
This creates a directory
my-app
with the following structure:my-app |-- pom.xml `-- src |-- main | `-- java | `-- com | `-- sample | `-- app | `-- App.java `-- test `-- java `-- com `-- sample `-- app `-- AppTest.java
The
my-app
directory contains the following key components:-
A
src/main
directory for storing the application sources -
A
src/test
directory for storing the test sources -
A
pom.xml
file with the project configuration
-
A
Create a Java object on which the rule or rules will operate within the Maven archetype.
In this example, a
Person.java
file is created in the directorymy-app/src/main/java/com/sample/app
. ThePerson
class contains getter and setter methods to set and retrieve the first name, last name, hourly rate, and the wage of a person:package com.sample.app; public class Person { private String firstName; private String lastName; private Integer hourlyRate; private Integer wage; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Integer getHourlyRate() { return hourlyRate; } public void setHourlyRate(Integer hourlyRate) { this.hourlyRate = hourlyRate; } public Integer getWage(){ return wage; } public void setWage(Integer wage){ this.wage = wage; } }
Create a rule file in
.drl
format inmy-app/src/main/resources/rules
. The DRL file must contain at minimum a package specification, an import list of data objects to be used by the rule or rules, and one or more rules withwhen
conditions andthen
actions.The following
Wage.drl
file contains aWage
rule that imports thePerson
class, calculates the wage and hourly rate values, and displays a message based on the result:package com.sample.app; import com.sample.app.Person; dialect "java" rule "Wage" when Person(hourlyRate * wage > 100) Person(name : firstName, surname : lastName) then System.out.println("Hello " + name + " " + surname + "!"); System.out.println("You are rich!"); end
In the
my-app/src/main/resources/META-INF
directory, create akmodule.xml
metadata file with the following content:<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://www.drools.org/xsd/kmodule"> </kmodule>
This
kmodule.xml
file is a KIE module descriptor that selects resources to knowledge bases and configures sessions. This file enables you to define and configure one or more KIE bases, and to include DRL files from specificpackages
in a specific KIE base. You can also create one or more KIE sessions from each KIE base.The following example shows a more advanced
kmodule.xml
file:<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.drools.org/xsd/kmodule"> <kbase name="KBase1" default="true" eventProcessingMode="cloud" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg1"> <ksession name="KSession1_1" type="stateful" default="true" /> <ksession name="KSession1_2" type="stateful" default="true" beliefSystem="jtms" /> </kbase> <kbase name="KBase2" default="false" eventProcessingMode="stream" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1"> <ksession name="KSession2_1" type="stateless" default="true" clockType="realtime"> <fileLogger file="debugInfo" threaded="true" interval="10" /> <workItemHandlers> <workItemHandler name="name" type="new org.domain.WorkItemHandler()" /> </workItemHandlers> <listeners> <ruleRuntimeEventListener type="org.domain.RuleRuntimeListener" /> <agendaEventListener type="org.domain.FirstAgendaListener" /> <agendaEventListener type="org.domain.SecondAgendaListener" /> <processEventListener type="org.domain.ProcessListener" /> </listeners> </ksession> </kbase> </kmodule>
This example defines two KIE bases. Two KIE sessions are instantiated from the
KBase1
KIE base, and one KIE session fromKBase2
. The KIE session fromKBase2
is astateless
KIE session, which means that data from a previous invocation of the KIE session (the previous session state) is discarded between session invocations. Specificpackages
of rule assets are included with both KIE bases. When you specify packages in this way, you must organize your DRL files in a folder structure that reflects the specified packages.In the
my-app/pom.xml
configuration file, specify the libraries that your application requires. Provide the Red Hat Process Automation Manager dependencies as well as thegroup ID
,artifact ID
, andversion
(GAV) of your application.<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sample.app</groupId> <artifactId>my-app</artifactId> <version>1.0.0</version> <repositories> <repository> <id>jboss-ga-repository</id> <url>http://maven.repository.redhat.com/ga/</url> </repository> </repositories> <dependencies> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>VERSION</version> </dependency> <dependency> <groupId>org.kie</groupId> <artifactId>kie-api</artifactId> <version>VERSION</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> </project>
For information about Maven dependencies and the BOM (Bill of Materials) in Red Hat Process Automation Manager, see What is the mapping between Red Hat Process Automation Manager and Maven library version?.
-
Use the
testApp
method inmy-app/src/test/java/com/sample/app/AppTest.java
to test the rule. TheAppTest.java
file is created by Maven by default. In the
AppTest.java
file, add the requiredimport
statements to import KIE services, a KIE container, and a KIE session. Then load the knowledge base, insert facts, and execute the rule from thetestApp()
method that passes the fact model to the rule.import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; public void testApp() { // Load the knowledge base: KieServices ks = KieServices.Factory.get(); KieContainer kContainer = ks.getKieClasspathContainer(); KieSession kSession = kContainer.newKieSession(); // Set up the fact model: Person p = new Person(); p.setWage(12); p.setFirstName("Tom"); p.setLastName("Summers"); p.setHourlyRate(10); // Insert the person into the session: kSession.insert(p); // Fire all rules: kSession.fireAllRules(); kSession.dispose(); }
After you create and save all DRL assets in your Maven archetype, navigate to the
my-app
directory in the command line and run the following command to build your files:mvn clean install
If the build fails, address any problems described in the command line error messages and try again to validate the files until the build is successful.
After your files build successfully, run the following command to execute the rules locally. Replace
com.sample.app
with your package name.mvn exec:java -Dexec.mainClass="com.sample.app"
- Review the rules to ensure that they executed properly, and address any needed changes in the files.
To integrate the new rule assets with an existing project in Red Hat Process Automation Manager, you can compile the new Maven project as a knowledge JAR (KJAR) and add it as a dependency in the pom.xml
file of the project in Business Central.
Chapter 7. Next steps
Appendix A. Versioning information
Documentation last updated on: Monday, October 1, 2018.