JBoss Community Archive (Read Only)

SwitchYard 1.0

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/69536172/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/69536172/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>

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/69536172/Rules-Resources.png

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:54:35 UTC, last content change 2013-07-24 14:13:34 UTC.