package com.example.switchyard.docs; public interface Example { public void process(MyData data); }
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.
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.
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.
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
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 action type.
Mapping variables from your SwitchYard Exchange, Context or Message into Drools Globals can be done via expressions, the default (and only currently supported) type is MVEL. This can be done by configuring the rules implementation:
Your expression can use the variables exchange (org.switchyard.Exchange), context (org.switchyard.Context) or message (org.switchyard.Message). You can see in the example above is that context can be accessed in the expression as a java.util.Map. When accessing it as such, the default properties Scope is IN. This can be overridden using the contextScope attribute by changing it to OUT or EXCHANGE.
Now you can use these global variables in your Drools DRL:
package example global java.lang.String service global java.lang.String messageId global com.example.Payload payload rule "Example" when ... then ... System.out.println("service: " + service + ", messageId: " + messageId + ", payload: " + payload); end
Of course, in a more realistic scenario, the payload would be accessed in rule firing because it was inserted into the session directly by the RulesExchangeHandler, and thus evaluated (rather than being accessed as a global). See Mapping Facts below.
The default Object which is inserted into the rules engine as a fact is the SwitchYard Message's content. However, this can be overridden by specifying your own fact mappings.
IMPORTANT: If you specify your own fact mappings, the SwitchYard Message content will not be inserted as a fact. You will have to add a fact mapping with an expression of "message.content" to have it still included.
There is no point in specifying the "variable" attribute of the mappings (as done for global mappings), as the result of each expression is inserted as a nameless fact. For stateless execution, the full list of facts is passed to the StatelessKnowledgeSessions' execute(Iterable) method. For stateful execution, each fact is individually inserted into the StatefulKnowledgeSession. And for Complex Event Processing, each fact is individually inserted into the WorkingMemoryEntryPoint.
If the result of the mapping expression implements Iterable (for example, a Collection), then the result is iterated over, and each iteration is inserted as a separate fact, rather than the parent Iterable itself being inserted. This is not recursive behavior (i.e: it is only done once).
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:
<implementation.rules ...> <actions> <action id="FooStream" operation="processFooMessage" type="FIRE_UNTIL_HALT"/> <action id="BarStream" operation="processBarMessage" type="FIRE_UNTIL_HALT"/> </actions> ... <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>
Please see the Listeners and Loggers sections found in the Knowledge Services documentation.
Please see the Channels section found in the Knowledge Services documentation.