JBoss.orgCommunity Documentation
Both assets and whole packages of assets are "versioned" in the Guvnor, but the mechanism is slightly different. Individual assets are saved a bit like a version of a file in a source control system. However, packages of assets are versioned "on demand" by taking a snapshot (typically which is used for deployment). The next section talks about deployment management and snapshots.
Each time you make a change to an asset, it creates a new item in the version history. This is a bit like having an unlimited undo. You can look back through the history of an individual asset like the list above, and view it (and restore it) from that point in time.
The Asset Editor is the principle component of Guvnor's User-Interface. It consists of two tabs:-
Attributes
A : Meta data (from the "Dublin Core" standard):-
"Last modified:" The last modified date.
"By:" Who made the last change.
"Note:" A comment made when the Asset was last updated (i.e. why a change was made)
"Created on:" The date and time the Asset was created.
"Created by:" Who initially authored the Asset.
"Format:" The short format name of the type of Asset.
"Package:" The package to which the Asset belongs.
"Is Disabled:" Whether the Asset has been disabled from inclusion in a binary package.
"UUID:" A unique identifier for the Asset version.
B : Other miscellaneous meta data for the Asset.
C : Version history of the Asset.
D : Free-format documentation\description for the Asset. It is encouraged, but not mandatory, to record a description of the Asset before editing.
E : Discussions regarding development of the Asset can be recored here.
Edit
A : The Asset editor is where the "editor widget" lives - exactly what form the editor takes depends on the Asset type.
B : These are menus contains various actions for the Asset; such as Saving, Archiving, changing Status etc.
C : The current status of the Asset.
Configuring packages is generally something that is done once, and by someone with some experience with rules/models. Generally speaking, very few people will need to configure packages, and once they are setup, they can be copied over and over if needed. Package configuration is most definitely a technical task that requires the appropriate expertise.
All assets live in "packages" in the Guvnor - a package is like a folder (it also serves as a "namespace"). A home folder for rule assets to live in. Rules in particular need to know what the fact model is, what the namespace is etc.
The above picture shows the package explorer. Clicking on an
asset type will show a list of matches (for packages with thousands of
rules, showing the list may take several seconds - hence the importance of
using categories to help you find your way around).
So while rules (and assets in general) can appear in any number of categories, they only live in one package. If you think of the Guvnor as a file system, then each package is a folder, and the assets live in that folder - as one big happy list of files. When you create a deployment snapshot of a package, you are effectively copying all the assets in that "folder" into another special "folder".
The package management feature allows you to see a list of packages, and then "expand" them, to show lists of each "type" of asset (there are many assets, so some of them are grouped together):
The asset types:
Business assets: this shows a list of all "business rule" types, which include decision tables, business rules etc. etc.
Technical assets: this is a list of items that would be considered technical (e.g. DRL rules, data enumerations and rule flows).
Functions: In the Guvnor you can also have functions defined (optionally of course).
DSL: Domain Specific Languages can also be stored as an asset. If they exist (generally there is only one), then they will be used in the appropriate editor GUIs.
Model: A package requires at least one model - for the rules.
WorkingSets: Working Sets let you create subsets of package's Fact Types and apply constraints to their fields.
From the package explorer you can create new rules, or new assets. Some assets you can only create from the package explorer. The above picture shows the icons which launch wizards for this purpose. If you hover the mouse over them, a tooltip will tell you what they do.
One of the most critical things you need to do is configure packages.
This is mostly importing the classes used by the rules, and globals
variables. Once you make a change, you need to save it, and that package is
then configured and ready to be built. For example, you may add a model
which has a class called com.something.Hello
, you would then
add import com.something.Hello
in your package configuration
and save the change.
Finally you would "build" a package. Any errors caught are then shown at this point. If the build was successful, then you will have the option to create a snapshot for deployment. You can also view the DRL that this package results in.
In cases of large numbers of rules, all these operations can take some time.
It is optional at this stage to enter the name of a "selector" - see the admin section for details on how to configure custom selectors for your system (if you need them - selectors allow you to filter down what you build into a package - if you don't know what they are for, you probably don't need to use them).
It is also possible to create a package by importing an existing DRL
file. When you choose to create a new package, you can choose an option to
upload a .drl
file. The Guvnor will then attempt to
understand that DRL, break create a package for you. The rules in it will
be stored as individual assets (but still as DRL text content). Note that
to actually build the package, you will need to upload an appropriate
model (as a JAR) to validate against, as a separate step.
As drools supports various configuration options for a package (such
as adding functions for "accumulate" etc), this can be done by adding a
X.package
or X.conf
file to the
package - files which contain name/value pairs in the "properties" style.
These will then be automatically added to the package configuration. See
the main drools documentation for all the things you can do.
Working Sets are a mean for grouping Facts and then defining constraints on them. You can create groups of Facts and only those Facts will be visible when authoring rules using the Guided Editor.
Right now, Working Sets must be activated manually from the Guided Editor window (using the "Select Working Set" button placed in the toolbar). In the future, different Working Sets could be assigned to different users to reduce the scope and complexity when authoring rules.
The figure above shows the window used to create or modify Working Sets. In this window you will find 2 lists. The list on the left side contains the possible Fact Types that can be added to the Working Set. These facts are those defined/imported in the package's model. The list on the right side contains the allowed Fact Types of this Working Set. When this Working Sets is active, only those Fact Types could be used while authoring rules using the Guided BRL Editor
Once you have selected the valid Fact Types for a Working Set, you can add Constraints to the fields of those Facts Types. The image above shows how the Field Constraint tab looks like. In this configuration screen you will find:
A.- Fact Types dropdown: Here you will find a list containing the Working Set's Fact Types
B.- Field dropdown: Once you have selected a Fact Type, this dropdown will contain its fields.
C.- Constraints List: This lists shows all the Constraints applied to the selected Field
D.- Action Buttons: Using these buttons you will be able to add or remove Constraints to the selected Field. Right now, Guvnor provides a built-in collection of Constraints. The idea for next releases is to let users to plug their custom Constraints too.
E.- Constraint's Attributes: In this section you will find all the attributes of the current Constraint that could be parametrized by the user.
In the example above, a Matches Constraint is created for Car.brand field. This means that when rule authors use this field in a Rule condition, they should use a value valid according to this constraint, otherwise they will receive an error or warning.
Working Sets are no active by default in Guvnor. Because this is an experimental feature, you must enable them manually in the Guided Editor panel if you want to use them. In the future, Working Sets will be associated to each user's profile.
A new button was added in Guided Editor's Toolbar: "Select Working Sets". This button will open a popup with the list of the package's Working Sets. Using this popup you can activate one or more Working Sets.
When Working Sets are activated, only the Fact Types allowed by them could be used when inserting new Patterns or Actions. The Patterns and Actions already present in the rule that contain prohibited Fact Types are marked as read only. Take a look at the next screen shots comparing the Guided Editor panel with and without Working Sets
In the image you can see how Working Sets could help rule's authors by reducing the amount of available Fact Types
Here you can see how Patterns containing prohibited Fact Types are switched to read only mode after Working Sets are activated.
Up to now we have only cover how Facts are filtered using Working Sets. Another important feature of Working Sets is Field Constraints. We have already saw how to configure them, now we are going to explain how to use them.
Because Field Constraints are defined inside a Working Set, we need to activate one or more Working Set to start working with them. Once a Working Set defining Field's Constraints is active we have two ways to use them: on demand validation and real-time validation.
On demand validation is performed when you press the "Verify" button present in Guided Editor's toolbar. This button will fire a rule verification and will end up showing a report with the results. Any violated constraint will be shown as an error or warning according to its relevance
The image above shows the report that appears when a Working Set defines a Range Constraint on Driver.age. The age should be between 18 and 80.
Real-Time validation is an experimental feature (yes, inside another experimental feature like Working Sets) that checks for Field's Constraints violations in real time and mark the lines where the violations are using error or warning icons. This feature is disabled by default because sometimes it could be expensive. If you want to try it out, you should enable it in Administration -> Rules Verification. This configuration is not yet persisted, so you need to enable it every time you start Guvnor.
This Image shows the result of real-time validation. There you can see the same result as on demand validation, but you don't need to click any button, and the errors/warnings are shown in a more fashionable way!
The problem with real-time validation is that right now only support "top level" Patterns.
Guided editor style "Business rules": (also known as "BRL format"). These rules use the guided GUI which controls and prompts user input based on knowledge of the object model. This can also be augmented with DSL sentences.
To use the BRL guided editor, someone will need to have you package configured before hand.
The above diagram shows the editor in action. The following descriptions apply to the lettered boxes in the diagram:-
A : The different parts of a rule:-
The "WHEN" part, or conditions, of the rule.
The "THEN" action part of the rule.
Optional attributes that may effect the operation of the rule.
B : This shows a pattern which is declaring that the rule is looking for a "LoanApplication" fact (the fields are listed below, in this case none). Another pattern, "Applicant", is listed below "LoanApplication". Fields "creditRating" and "applicationDate" are listed. Clicking on the fact name ("LoanApplication") will pop-up a list of options to add to the fact declaration:-
Add more fields (e.g. their "location").
Assign a variable name to the fact (which you can use later on if needs be)
Add "multiple field" constraints - i.e. constraints that span across fields (e.g. age > 42 or risk > 2).
C : The "minus" icon ("[-]") indicates you can remove something. In this case it would remove the whole "LoanApplication" fact declaration. Depending upon the placement of the icon different components of the rule declaration can be removed, for example a Fact Pattern, Field Constraint, other Conditional Element ("exists", "not exists", "from" etc) or an Action.
D : The "plus" icon ("+") allows you to add more patterns to the condition or the action part of the rule, or more attributes. In all cases, a popup option box is provided. For the "WHEN" part of the rule, you can choose from a list of Conditional Elements to add:
A Constraint on a Fact: it will give you a list of facts.
"The following does not exist": the fact plus constraints must not exist.
"The following exists": at least one match should exist (but there only needs to be one - it will not trigger for each match).
"Any of the following are true": any of the patterns can match (you then add patterns to these higher level patterns).
"From": this will insert a new From Conditional Element to the rule.
"From Accumulate": this will insert a new Accumulate Conditional Element to the rule.
"From Collect": this will insert a new Collect Conditional Element to the rule.
"From Entry-point": this allows you to define an Entry Point for the pattern.
"Free Form DRL": this will let you insert a free chunk of DRL.
If you just put a fact (like is shown above) then all the patterns are combined together so they are all true ("and").
E : This shows the constraint for the "creditRating" field. Looking from left to right you find:-
The field name: "creditRating". Clicking on it you can assign a variable name to it, or access nested properties of it.
A list of constraint operations ("equal to" being selected): The content of this list changes depending on the field's data type.
The value field: It could be one of the following:-
A literal value: depending on the field's data type different components will be displayed:
String or Number -> TextBox
Date -> Calendar
Enumeration -> Combobox
Boolean -> Checkbox
A "formula": this is an expression which is calculated (this is for advanced users only)
An Expression - this will let you use an Expression Builder to build up a full mvel expression. (At the moment only basic expressions are supported)
F : This shows the constraint for the "applicationDate" field. Looking from left to right you find:
The field name: "applicationDate".
A list of constraint operations: "after" being selected.
A "clock" icon. Since the "applicationDate" is a Date data-type the list of available operators includes those relating to Complex Event Processing (CEP). When a CEP operator is used this additional icon is displayed to allow you to enter additional CEP operator parameters. Clicking the "clock" will cycle the available combinations of CEP operator parameters.
Complex Event Processing operators are also available when the Fact has been declared as an event. Refer to the "Fact Model" chapter of this user-guide for details on how to add annotations to your Fact model. Events have access to the full range of CEP operators; Date field-types are restricted to "after", "before" and "coincides".
Facts annotated as Events can also have CEP sliding windows defined.
G : Pattern/Action toolbar. Next to each Pattern or Action you will find a toolbar containing 3 buttons. The first button lets you insert a new Pattern/Action below the one you selected, the other two buttons will move the current Pattern/Action up or down.
H : This shows an "action" of the rule, the Right Hand Side of a rule consists in a list of actions. In this case, we are updating the "explanation" field of the "LoanApplication" fact. There are quite a few other types of actions you can use:-
Insert a completely new Fact
Logically insert a completely new Fact (see "Truth Maintenance" in the Expert documentation).
Modify an existing fact (which tells the engine the fact has changed).
Set a field on a fact (in which case the engine doesn't know about the change - normally because you are setting a result).
Retract a fact.
Add Facts to existing global lists.
Call a method on a variable.
Write a chunk of free form code.
In most cases you can click on the Fact name to get a list of its attributes or to bind it to a variable name.
Note that is it possible to limit field values to items in a pre configured list. This list is configured as part of the package (using a data enumeration to provide values for the drop down list). These values can be a fixed list, or (for example) loaded from a database. This is useful for codes, and other fields where there are set values. It is also possible to have what is displayed on screen, in a drop down, be different to the value (or code) used in a rule. See the section on data enumerations for how these are configured.
If the package the rule is part of has a DSL configuration, when when you add conditions or actions, then it will provide a list of "DSL Sentences" which you can choose from - when you choose one, it will add a row to the rule - where the DSL specifies values come from a user, then a edit box (text) will be shown (so it ends up looking a bit like a form). This is optional, and there is another DSL editor. Please note that the DSL capabilities in this editor are slightly less then the full set of DSL features (basically you can do [when] and [then] sections of the DSL only - which is no different to drools 3 in effect).
The following diagram shows the DSL sentences in action in the guided editor:
In the above example, you can see how to use a mixture of Conditional Elements, literal values, and formulas. The rule has 4 "top level" Patterns and 1 Action. The "top level" Patterns are:
A Fact Pattern on Person. This Pattern contains two field constraints: one for birthdate field and the other one is a formula. Note that the value of the birthdate restriction is selected from a calendar. Another thing to note is that you can make calculations and use nested fields in the formula restriction (i.e. car.brand). Finally, we are setting a variable name ($p) to the Person Fact Type. You can then use this variable in other Patterns.
The generated DRL from this Pattern will be:
$p : Person( birthDate < "19-Dec-1982" , eval( car.brand == "Ford" && salary > (2500 * 4.1) ))
A From Pattern. This condition will create a match for every Address whose street name is "Elm St." from the Person's list of addresses. The left side of the from is a regular Fact Pattern and the right side is an Expression Builder that let us inspect variable's fields.
The generated DRL from this Pattern will be: Address(
street == "Elm St." ) from $p.addresses
A "Not Exist" Conditional Element. This condition will match when its content doesn't create a match. In this case, its content is a regular Fact Pattern (on Person). In this Fact Pattern you can see how variables ($p) could be used inside a formula value.
The generated DRL from this Pattern will be: not Person(
salary == ( $p.salary * 2 ) )
A "From Accumulate" Conditional Element. This is maybe one of the most complex Patterns you can use. It consist in a Left Pattern (It must be a Fact Pattern. In this case is a Number Pattern. The Number is named $totalAddresses), a Source Pattern (Which could be a Fact Pattern, From, Collect or Accumulate conditional elements. In this case is an Address Pattern Restriction with a field restriction in its zip field) and a Formula Section where you can use any built-in or custom Accumulate Function (in this example a count() function is used). Basically, this Conditional Element will count the addresses having a zip code of 43240 from the Person's list of addresses.
The generated DRL from this Pattern will be:
$totalAddresses : Number() from accumulate ($a : Address(
zipCode == " 43240") from $p.addresses, count($a))
When clicking on the + button of the WHEN section, a new popup will appear letting you to add a new Pattern to the Rule. The popup will looks similar to the image above. In this popup you could select the type of Pattern to add by selecting one of the list items. In the list you will have an entry for each defined Fact Type, in addition to the already mentioned Conditional Elements like "exists", "doesn't exist", "from", "collect", "accumulate", "from entry-point" and "free form DRL". Once you have selected one of this elements, you can add a new Pattern by clicking on the "Ok" button. The new pattern will be added at the bottom of the rule's left hand side. If you wan't to choose a different position, you can use the combobox placed at the top of the popup.
You can also open this popup by clicking in the [+] button from a Pattern's action toolbar. If that is the case, the pop-up that appears wouldn't containt the position combobox, because the new Pattern will be added just after the Pattern where you clicked.
The above dialog is what you will get when you want to add constraints to a fact. In the top half are the simple options: you can either add a field constraint straight away (a list of fields of the applicable fact will be shown), or you can add a "Multiple field constraint" using AND or OR operands. In the bottom half of the window you have the Advanced options: you can add a formula (which resolves to True or False - this is like in the example above: "... salary > (2500 * 4.1)". You can also assign a Variable name to the fact (which means you can then access that variable on the action part of the rule, to set a value etc).
DSL rules are textual rules, that use a language configuration asset to control how they appear.
A dsl rule is a single rule. Referring to the picture above, you can a text editor. You can use the icons to the right to provide lists of conditions and actions to choose from (or else press Control + Space at the same time to pop up a list).
Technical (DRL) rules are stored as text - they can be managed in the Guvnor. A DRL can either be a whole chunk of rules, or an individual rule. if its an individual rule, no package statement or imports are required (in fact, you can skip the "rule" statement altogether, just use "when" and "then" to mark the condition and action sections respectively). Normally you would use the IDE to edit raw DRL files, since it has all the advanced tooling and content assistance and debugging. However, there are times when a rule may have to deal with something fairly technical in a package in Guvnor. In any typical package of rules, you generally have a need for some "technical rules" - you can mix and match all the rule types together of course.
Multiple rules can be stored in a spreadsheet (each row is a rule). The details of the spreadsheet are not covered in this chapter (as there is a separate chapter for them).
To use a spreadsheet, you upload an XLS file (and can download the current version, as per the picture above). To create a new decision table, when you launch the rule wizard, you will get an option to create one (after that point, you can upload the XLS file).
The guided decision table feature allows decision tables to be edited in place on the web. This works similar to the guided editor by introspecting what facts and fields are available to guide the creation of a decision table. Rule attributes, meta-data, conditions and actions can be defined in a tabular format thus facilitating rapid entry of large sets of related rules. Web-based decision table rules are compiled into DRL like all other rule assets.
Cells can be selected in a variety of ways:-
Firstly individual cells can be double-clicked and a pop-up editor corresponding to the underlying data-type will appear. Groups of cells in the same column can be selected by either clicking in the first and dragging the mouse pointer or clicking in the first and clicking the extent of the required range with the shift key pressed.
Secondly the keyboard cursor keys can be used to navigate around the table. Pressing the enter key will pop-up the correspondig editor. Ranges can be selected by pressing the shift key whilst extending the range with the cursor keys.
Columns can be resized by hovering over the corresponding divider in the table header. The mouse cursor will change and then the column width dragged either narrower or wider.
The guided decision table is split into two main sections:-
The upper section allows table columns to be defined representing rule attributes, meta-data, conditions and actions.
The lower section contains the actual table itself; where individual rows define seperate rules.
When you edit or create a new column, you will be given a choice of the type of constraint:-
Literal : The value in the cell will be compared with the field using the operator.
Formula: The expression in the cell will be evaluated and then compared with the field.
Predicate : No field is needed, the expression will be evaluated to true or false.
You can set a default value, but normally if there is no value in the cell, that constraint will not apply.
Two columns containing rule number and description are provided by default.
Zero or more attribue columns representing any of the DRL rule attributes can be added. An additional pseudo attribute is provide in the guided decision table editor to "negate" a rule. Use of this attribute allows complete rules to be negated. For example the following simple rule can be negated as also shown.
when $c : Cheese( name == "Cheddar" ) then ... end
when not Cheese( name == "Cheddar" ) then ... end
Zero or more meta-data columns can be defined, each represents the normal meta-data annotation on DRL rules.
Conditions represent fact patterns defined in the right-hand side, or "when" portion, of a rule. To define a condition column you must define a binding to a model class or select one that has previously been defined. You can choose to negate the pattern. Once this has been completed you can define field constraints. If two or more columns are defined using the same fact pattern binding the field constraints become composite field constraints on the same pattern. If you define multiple bindings for a single model class each binding becomes a seperate model class in the right-hand side of the rule.
Action columns can be defined to perform simple operations on bound facts within the rule engine's working memory or create new facts entirely. New facts can be inserted logically into the rule engine's working memory thus being subject to truth maintenance as usual. Please refer to the "Drools Expert" documentation for discussion on truth maintenance and logical insertions.
This section alows individual rules to be defined using the columns defined earlier.
The icon in the top left of the decision table toggles cell merging on and off. When cells are merged those in the same column with identical values are merged into a single cell. This simplifies changing the value of multiple cells that shared the same original value. When cells are merged they also gain an icon in the top-left of the cell that allows rows spanning the merged cell to be grouped.
Cells that have been merged can be further collapsed into a single row. Clicking the [+\-] icon in the top left of a merged cell collapses the corresponding rows into a single entry. Cells in other columns spanning the collapsed rows that have identical values are shown unchanged. Cells in other columns spanning the collapsed rows that have different values are highlighted and the first value displayed.
When the value of a grouped cell is altered all cells that have been collapsed also have their values updated.
Condition columns defined with literal values that use either the equality (==) or inequality (!=) operators can take advantage of a special decision table cell value of "otherwise". This special value allows a rule to be defined that matches on all values not explicitly defined in all other rules defined in the table. This is best illustrated with an example:-
when Cheese( name not in ("Cheddar", "Edam", "Brie") ) ... then ... end
when Cheese( name in ("Cheddar", "Edam", "Brie") ) ... then ... end
The guided rule editor is great when you need to define a single rule, however if you need to define multiple rules following the same structure but with different values in field constraints or action sections a "Rule Template" is a valuable asset. Rule templates allow the user to define a rule structure with place-holders for values that are to be interpolated from a table of data. Literal values, formulae and expressions can also continue to be used.
Rule Templates can often be used as an alternative for Decision Tables in Drools Guvnor.
To create a template for a rule simply select the "New Rule Template" from the Knowlegde Bases "Create New" popup menu. The create "New Rule Template" asset popup window will appear from which the normal asset attributes can be defined; such as name, category and description.
Once a rule template has been created the editor is displayed. The editor takes the form of the standard guided editor explained in more detail under the "Rule Authoring" section. As the rule is constructed you are given the ability to insert "Template Keys" as place-holders within your field constraints and action sections. Literal values, formulae and expressions can continue to be used as in the standard guided editor.
The following screenshot illustrates a simple rule that has been defined with a "Template Key" for the applicants' maximum age, minimum age and credit rating. The template keys have been defined as "$max_age", "$min_age" and "$cr" respectively.
When you have completed the definition of your rule template you need to enter the data that will be used to interpolate the "Template Key" place-holders. Drools Guvnor provides the facility to enter data in a flexible grid within the guided editor screen. The grid editor can be launched by pressing the "Load Template Data" button on the guided editor screen.
The rule template data grid is very flexible; with different pop-up editors for the underlying fields' data-types. Columns can be resized and sorted; and cells can be merged and grouped to facilitate rapid data entry.
One row of data interpolates the "Template Key" place-holders for a single rule; thus one row becomes one rule.
If any cells for a row are left blank a rule for the applicable row is not generated.
The icon in the top left of the grid toggles cell merging on and off. When cells are merged those in the same column with identical values are merged into a single cell. This simplifies changing the value of multiple cells that shared the same original value. When cells are merged they also gain an icon in the top-left of the cell that allows rows spanning the merged cell to be grouped.
Cells that have been merged can be further collapsed into a single row. Clicking the [+\-] icon in the top left of a merged cell collapses the corresponding rows into a single entry. Cells in other columns spanning the collapsed rows that have identical values are shown unchanged. Cells in other columns spanning the collapsed rows that have different values are highlighted and the first value displayed.
When the value of a grouped cell is altered all cells that have been collapsed also have their values updated.
Whilst not necessary, rule authors can view the DRL that will be generated for a "Rule Template" and associated data. This feature and its operation is no different to that for other assets. Select the "Source" -> "View Source" menu item from the Asset Editor screen. The DRL for all rules will be displayed.
For any rule base application, a fact model is needed to drive the rules. The fact model typically overlaps with the applications domain model, but in general it will be decoupled from it (as it makes the rules easier to manage over time). There are no technical limitations on using your domain model as your fact model, however this introduces tighter coupling between your business domain (domain model) and your knowledge domain (fact model). Consequentially if your domain model were to change you would need to, at the very least, revisit your rule definitions.
There are two ways to do define your fact model; each of which will be discussed in more detail in the following sections.
Upload a JAR file containing Java Classes used by both your application and rules.
Declare a model within Guvnor; that can be exported as a KnowledgeBase and used within your Java code.
Creating and uploading a JAR model file is a two step process.
Select "Upload POJO Model JAR" from the "Create New" popup menu from the "Knowledge Bases" section of the Explorer widget. This will launch the "New Asset" configuration screen from which the new upload can be given basic details such as name, category and a description.
Once the POJO Model JAR asset has been created you are presented with a screen to upload the actual JAR containing the model defined as Java classes and packaged in a regular Java JAR file. Many Java IDE's are able to export classes as a JAR file.
Why would you chose declared types over JAR files: generally this reinforces the fact that the model "belongs" to the KnowledgeBase, rather then the application, and allows the model to have a lifecycle separate from the application. It also allows Java types to be enriched with Rule specific annotations. Additionally it also removes the burden of keeping JAR files syncronised between rules and the applications that use the rules.
Declarative models can be either:-
A standalone definition of the entire Fact model used within your rules.
Supplementary Fact defintions to support a Java POJO Model.
Used to enrich a Java JAR model as uploaded in the previous section. Enriching JAR models allows annotations used by Drools (such as a "role" of type "event" for Facts used as events in Complex Event Processing) to be appended to classes. When enriching an existing Java JAR model the package name in Guvnor needs to be identical to the Java package name containing the class(es) you wish to enrich.
Creating a Declarative Model is a two step process.
Select "New Declarative Model" from the "Create New" popup menu from the "Knowledge Bases" section of the Explorer widget. This will launch the "New Asset" configuration screen from which the new upload can be given basic details such as name, category and a description.
Once the Declarative Model asset has been created you are presented with the initial modelling screen; that is empty to begin.
Facts, being semantically equivalent to Java classes, can be created by selecting the "Add new fact type" button. An existing Fact definition can be edited by clicking the "pencil" icon on the same row as the Fact name. Furthermore existing Facts can be deleted by clicking the "[-]" icon.
Fact Fields can be created by selecting the "Add field" button. The type of a field is suggested by a list (but this list is not exhaustive). An existing Fact Field definition can be edited by clicking the "pencil" icon on the same row as the Fact Field name. Furthermore existing Fact Fields can be deleted by clicking the "[-]" icon.
Fact annotations can be created by selecting the "Add annotation" button. Annotations are listed under the Fact title, before the fields, by convention. Annotations are prefixed with the "@" symbol. This not only makes them instantly recognisable but is also consistent with their definition in DRL.
The annotation "Name" and "Value" are mandatory whereas the "Key" is optional. If a "Key" is not given a default value of "value" will be assigned. This is consistent with how annotations are held within Drools Expert.
An existing Fact Annotation can be edited by clicking the "pencil" icon on the same row as the Fact Annotation name. Furthermore existing Fact Annotations can be deleted by clicking the "[-]" icon.
Declarative types can extend existing:-
Java classes uploaded as part of a JAR (POJO) model
Other declared types in the same package.
To extend a Java class the following steps need to be completed:-
Import the applicable Java JAR into Guvnor
If the Java package name in which the class belongs is different to the Guvnor package name in to which the JAR has been imported ensure the Guvnor package imports the class from which you want to extend. This is normally completed for you automatically when you upload a JAR model however if you have multiple classes with the same name in the JAR you should check the appropriate one has been imported.
Within the Declarative Modelling screen define an empty type (i.e. with no fields) of the same name as that you want to extend.
Create a new declarative type as appropriate, extending the empty declaration created in the preceeding step.
Only properties on Java classes that have both a "getter" and "setter" following standard Java Bean conventions are available on the declared sub-type. This is because the declarative symantics imply all properties on declared types have both accessors and mutators.
Declared types are generated at knowledge base compilation time, i.e. the application will only have access to them at application run time. Therefore, these classes are not available for direct reference from the application.
Declarative types can be used like normal fact objects, but the way you create them is different (as they are not on your applications classpath). To create these objects, they are available from the KnowledgeBase instance.
Example 4.1. Handling declared fact types through the API
// get a reference to a knowledge base with a declared type: KnowledgeBase kbase = ... // get the declared FactType FactType personType = kbase.getFactType( "org.drools.examples", "Person" ); // handle the type as necessary: // create instances: Object bob = personType.newInstance(); // set attributes values personType.set( bob, "name", "Bob" ); personType.set( bob, "age", 42 ); // insert fact into a session StatefulKnowledgeSession ksession = ... ksession.insert( bob ); ksession.fireAllRules(); // read attributes String name = personType.get( bob, "name" ); int age = personType.get( bob, "age" );
The namespace of the declared type is the package namespace
where it was declared (i.e. org.drools.examples
in the
above example).
Functions are another asset type. They are NOT rules, and should only be used when necessary. The function editor is a textual editor. Functions
The DSL editor allows DSL Sentences to be authored. The reader should take time to explore DSL features in the Drools Expert documentation; as the syntax in Guvnor's DSL Editor is identical. The normal syntax is extended to provide "hints" to control how the DSL variable is rendered and validated within the user-interface.
The following "hints" are supported:-
{<varName>:<regular expression>}
This will render a text field in place of the DSL variable when the DSL Sentence is used in the guided editor. The content of the text field will be validated against the regular expression.
{<varName>:ENUM:<factType.fieldName>}
This will render an enumeration in place of the DSL variable when the DSL Sentence is used in the guided editor. <factType.fieldName> binds the enumeration to the model Fact and Field enumeration definition. This could be either a "Guvnor enumeration" (i.e. defined as a Knowledge Base "Enumeration") or a Java enumeration (i.e. defined in a model POJO JAR file).
{<varName>:DATE:<dateFormat>}
This will render a Date selector in place of the DSL variable when the DSL Sentence is used in the guided editor.
{<varName>:BOOLEAN:<[checked | unchecked]>}
This will render a dropdown selector in place of the DSL variable, providing boolean choices, when the DSL Sentence is used in the guided editor.
Rule flows: Rule flows allow you to visually describe the steps
taken - so not all rules are evaluated at once, but there is a flow of
logic. Rule flows are not covered in this chapter on the Guvnor, but you
can use the IDE to graphically draw ruleflows, and upload the
.rfm
file to the Guvnor.
Similar to spreadsheets, you upload/download ruleflow files (the eclipse IDE has a graphical editor for them). The details of Rule Flows are not discussed here.
Data enumerations are an optional asset type that technical folk can configure to provide drop down lists for the guided editor. These are stored and edited just like any other asset, and apply to the package that they belong to.
The contents of an enum config are a mapping of Fact.field to a list of values to be used in a drop down. That list can either be literal, or use a utility class (which you put on the classpath) to load a list of strings. The strings are either a value to be shown on a drop down, or a mapping from the code value (what ends up used in the rule) and a display value (see the example below, using the '=').
In the above diagram - the "MM" indicates a value that will be used in the rule, yet "Mini Mal" will be displayed in the GUI.
Getting data lists from external data sources: It is possible to have
the Guvnor call a piece of code which will load a list of Strings. To do
this, you will need a bit of code that returns a java.util.List
(of String's) to be on the classpath of the Guvnor. Instead of specifying a
list of values in the Guvnor itself - the code can return the list of
Strings (you can use the "=" inside the strings if you want to use a
different display value to the rule value, as normal). For example, in the
'Person.age' line above, you could change it to:
'Person.age' : (new com.yourco.DataHelper()).getListOfAges()
This assumes you have a class called "DataHelper" which has a method "getListOfAges()" which returns a List of strings (and is on the classpath). You can of course mix these "dynamic" enumerations with fixed lists. You could for example load from a database using JDBC. The data enumerations are loaded the first time you use the guided editor in a session. If you have any guided editor sessions open - you will need to close and then open the rule to see the change. To check the enumeration is loaded - if you go to the Package configuration screen, you can "save and validate" the package - this will check it and provide any error feedback.
There are a few other advanced things you can do with data enumerations.
Drop down lists that depend on field values: Lets imagine a simple fact model, we have a class called Vehicle, which has 2 fields: "engineType" and "fuelType". We want to have a choice for the "engineType" of "Petrol" or "Diesel". Now, obviously the choice type for fuel must be dependent on the engine type (so for Petrol we have ULP and PULP, and for Diesel we have BIO and NORMAL). We can express this dependency in an enumeration as:
'Vehicle.engineType' : ['Petrol', 'Diesel'] 'Vehicle.fuelType[engineType=Petrol]' : ['ULP', 'PULP' ] 'Vehicle.fuelType[engineType=Diesel]' : ['BIO', 'NORMAL' ]
This shows how it is possible to make the choices dependent on other field values. Note that once you pick the engineType, the choice list for the fuelType will be determined.
Loading enums programmatically: In some cases, people may want to
load their enumeration data entirely from external data source (such as a
relational database). To do this, you can implement a class that returns a
Map. The key of the map is a string (which is the Fact.field name as shown
above), and the value is a java.util.List
of Strings.
public class SampleDataSource2 {
public Map<String>, List<String> loadData() {
Map data = new HashMap();
List d = new ArrayList();
d.add("value1");
d.add("value2");
data.put("Fact.field", d);
return data;
}
}
And in the enumeration in the BRMS, you put:
=(new SampleDataSource2()).loadData()
The "=" tells it to load the data by executing your code.
Mode advanced enumerations: In the above cases, the values in the lists are calculated up front. This is fine for relatively static data, or small amounts of data. Imagine a scenario where you have lists of countries, each country has a list of states, each state has a list of localities, each locality has a list of streets and so on... You can see how this is a lot of data, and it can not be loaded up. The lists should be loaded dependent on what country was selected etc...
Well the above can be addressed in the following fashion:
'Fact.field[dependentField1, dependentField2]' : '(new com.yourco.DataHelper()).getListOfAges("@{dependentField1}", "@{dependentField2}")'
Similar to above, but note that we have just specified what fields are needed, and also on the right of the ":" there are quotes around the expression. This expression will then be evaluated, only when needed, substituting the values from the fields specified. This means you can use the field values from the GUI to drive a database query, and drill down into data etc. When the drop down is loaded, or the rule loaded, it will refresh the list based on the fields. 'depenentField1' and 'dependentField2' are names of fields on the 'Fact' type - these are used to calculate the list of values which will be shown in a drop down if values for the "field".