JBoss Community Archive (Read Only)

SwitchYard

Rules

Overview

The Rules Component is a pluggable container in SwitchYard which allows business rules to be exposed as a service.  One fronts their rules with a custom interface and, if desired, can easily annotate it's methods to define which should execute the rules. The Rules Component currently supports Drools as the rule engine.  Even though it is quite simple to write rules in Drools, that project's developer tooling and business analyst tooling are very mature.

Important

A Rules Service is a type of Knowledge Service (the other type being a BPM Service).  Thus, it is strongly suggested you familiarize yourself with the shared configuration capabilities of Knowledge Services.

Creating a Rules Service

To create a new Rules service in SwitchYard, you'll need the following information

  • File Name : the file name that will be used to create a new template rules definition.

  • Interface Type : the contract for the service being provided.  Rules services support Java, WSDL, and ESB contract types.

  • Service Name : the name of the service your process will provide.

  • Package Name : package name used for the new Rules file.

images/author/download/attachments/7307380/new-rules.jpg

The MyService interface can be as simple as this, with no SwitchYard-specific imports:

package com.example.switchyard.docs;
public interface Example {
    public void process(MyData data);
}

The generated rule template will look like this:

package com.example.switchyard.docs
import org.switchyard.Message
global Message message

rule "RulesExample"
    when
        // insert conditional here
    then
        // insert consequence here
        System.out.println("service: ExampleService, payload: " + message.getContent());
end

Operation Mappings

SwitchYard provides a flexible way to map data in and out service operation invocations via MVEL expressions.  First, please familiarize yourself with the general Knowledge Services documentation, specifically the sections related to what Globals, Faults, Inputs and Outputs are.  Next, consider the following tooling screenshot:

  images/author/download/attachments/7307380/Rules-Operations.png

The above will create XML configuration like this:

<operation name="process" type="EXECUTE">
  <globals>
    <global from="context['org.switchyard.messageId']" to="messageId"/>
  </globals>
  <inputs>
    <input from="message.content.policy"/>
    <input from="message.content.driver"/>
    <input from="context['org.example.foobar']"/>
  </inputs>
  <outputs>
    <output from="globals.Result" to="message.content"/>
  </outputs>
  <faults>
    <fault from="globals.Fault" to="message.content"/>
  </faults>
</operation>

The associated DRL could look like this:

package org.switchyard.example.docs

global java.lang.String messageId
global java.util.Map globals

rule "Approval"
    when
        policy : Policy(threshold >= 600)
    then
        policy.setFlag(true);
        globals.put("Result", policy);
end

rule "Denial"
    when
        policy : Policy(threshold < 600)
    then
        policy.setFlag(false);
        globals.put("Result", policy);
end

Globals

Globals represent variable in your rules that do not trigger rule execution, but can be used in either the LHS or RHS of your rules for customization.  They also provide a nice way to define in/out "buckets" so you can get data out of rule execution.  In the example above, the messageId is a global variable, and a Map (called "globals") is as well.  This way, we can set the outgoing SwitchYard Message content to the modified Policy.

Important

The global variable called globals (java.util.Map) is always available for in/out purposes.  You don't have to configure it in your <globals> section for it to be available to your DRL.  (See above.)

If you want to use your own application object as in in/out variable, you are free to do so.

You can even dynamically create your own Map using MVEL and name it what you want.  For example, "holder" as shown below:

<operation name="process" type="EXECUTE">
  <globals>
    <!-- the from is an MVEL construct which creates a new Map -->
    <global from="['':'']" to="holder"/>
  </globals>
  <outputs>
    <!-- this assumes your DRL did a holder.put("out", someObject) at some point -->
    <output from="holder.out" to="message.content"/>
  </outputs>
</operation>

Inputs

For the Rules component, Inputs are the "facts" that are inserted into the Drools rules engine.  In the example above, a Policy object, a Driver object, and a Context property.  The rules engine will react to these inserted objects, building an agenda so that the appropriate RHS clauses will execute.

If you do not specify your own Inputs, the default will be the incoming Message content.  If you do specify your own Inputs, the incoming Message content will not be inserted as a fact, and you will have to include "message.content" yourself, if desired.

Outputs

Using in/out variables (for example, the global Map called "globals"), we can extract data out of the rules execution and into the outgoing Message content.

If you do not specify your own Outputs, the default will be the result of the expression "globals.Result".

Warning

If you do not specify your own Outputs, or in your DRL, you do not populate the "Result" of the globals Map, then your Rules component execution will return null.  For IN_OUT Exchange patterns, this could obviously be a problem, so in those cases make sure you configure (or populate the default) Output correctly!

Faults

Fault mapping is similar to Output mapping, however the data represents an Exception or data that will be wrapped in an Exception.

Stateless vs. Stateful Rules Execution

By default, service method invocation will create a new Drools knowledge session, execute it given the passed-in domain data, and then be cleanly disposed.

However, it is possible to configure SwitchYard so that a stateful knowledge session will be used.  Specifically, it will "stick around" spanning multiple invocations.  (Please visit the Drools documentation to learn more about stateless vs. stateful knowledge sessions.)  To do this, you use the FIRE_ALL_RULES action type instead of EXECUTE.

There is also a new capability which allows you to insert facts into a stateful knowledge session without firing the rules (you might want to do that later).  In this case, use the INSERT operation type.

Complex Event Processing

Complex Event Processing, or "CEP", is an advanced topic, and can best be explained in the Drools Fusion documentation. What will be shown here in the SwitchYard documentation is how it can be configured via XML. Obviously this can be set using the Eclipse tooling as well.

<implementation.rules ...>
    <operations>
        <operation eventId="FooStream" name="processFooMessage" type="FIRE_UNTIL_HALT"/>
        <operation eventId="BarStream" name="processBarMessage" type="FIRE_UNTIL_HALT"/>
    </operations>
    ...
    <properties>
        <property name="drools.clockType" value="realtime"/>
        <property name="drools.eventProcessingMode" value="stream"/>
        <property name="drools.maxThreads" value="1"/>
        <property name="drools.multithreadEvaluation" value="false"/>
    </properties>
</implementation.rules>

Note the type of "FIRE_UNTIL_HALT". This is required for CEP scenarios.

How do facts (data) get inputted for CEP?

Operations of type FIRE_UNTIL_HALT can specify <inputs> just like any other operation. If all of your inputs have "from" attributes but not "to" attributes, then:

  • If the "eventId" attribute on the operation element is set, then the eventId is your entry point that the data gets inserted into.

  • If the "eventId" attribute on the operation element is not set, then everything gets inserted into the stateful session, not into an entry point (as we can't guess that for you).

In other words, if you have input elements with "to" attributes, then the value of the "to" attribute will override - for just those input elements - what is set as "eventId" on the operation element. The point of this is that with just one operation invocation, you can have a list of different inputs, and whatever facts come from each input can be targeted to different entry points. Again, all with one operation invocation. Any inputs without to attributes in that operation will default to the operation's eventId, and if there is no eventId, again it defaults up again to be inserted into the stateful session itself.

Resources

A Resource represents an artifact that is required by your Rules component. It could be anything you could think of, including a properties file, a Drools Rule Language file, or whatever.  But it needs to be available to the Rules component's runtime for that process.  The list of resources available to your process is a configurable aspect of the Rules service component.

images/author/download/attachments/7307380/Rules-Resources.png

Decision Tables

If your resource type is decision table (DTABLE), then you have the option of also specifying additional information for that resource using the resourceDetail sub-element:

  • If the decision table is an eXcel spreadsheet (XLS), or a Comma Separated Value (CSV) file, you can use the "inputType" attribute.

  • If it is a spreadsheet, to use a specifically named tab (or "sheet") in it, you can use the "worksheetName" attribute.For example:

<resource location="META-INF/Example.xls" type="DTABLE">
    <resourceDetail inputType="XLS" worksheetName="Sheet 2"/>
</resource>

Auditing a Service

Please see the Listeners and Loggers sections found in the Knowledge Services documentation.

Consuming a Service

Please see the Channels section found in the Knowledge Services documentation.

JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-13 09:45:31 UTC, last content change 2013-11-22 20:19:05 UTC.