Java Annotation Semantic Module

Warning

Java Annotation Semantic Module is being replaced with Spring Integration for 2.1. All the capabilities of the Annotation module are available in the Spring Integration, albeit with slightly different syntax.



The Java Annotation Semantic Module allows rules to be defined as simple annotated Plain Old Java Objects (POJOs).


Module benefits:

  • The use of Java IDE's for rule editing. While most IDE's provide decent XML editing, support for embedded scripting is weak.
  • The ability to unit-test rules using mocks.
  • The ability to interactively step through rules in a Java debugger.
  • The ability to inject dependencies into rules via Spring.

Annotated Java Rules

Rules

Annotated rules are simple POJOs with Java5 annotations marking the behavioral aspects of the rule.

Example:
import org.drools.semantics.annotation.*;

@DroolsRule
public class Hello {
    
    @DroolsCondition
    public boolean conditionOne(...) {
        ...
    }
    
    @DroolsCondition
    public boolean conditionTwo(...) {
        ...
    }
    
    @DroolsConsequence
    public void consequence(...) {
    	...
    }
}

Condition Methods:

A rule may contain zero or more conditions methods annotated with @DroolsCondition. Condition methods must return boolean, otherwise a runtime exception will be thrown. Rule methods can utilize facts and application-data by declaring parameters annotated with @DroolsParameter and @DroolsApplicationData respectively. A condition method with a parameter annotated with @DroolsParameter implicitly declares a rule-level parameter.

Example:
@DroolsCondition
public boolean isTrader(@DroolsParameter("user") User user) {
    return user.getType () == UserType.TRADER;
}

@DroolsCondition
public boolean isMarketOpen(@DroolsParameter("order") Order order,
                            @DroolsApplicationData("calendar") MarketCalendar calendar{
    return calendar.isExchangeOpen(order.getExchange(), order.getTradeTime());
}

Consequence Method

A must contain exactly one consequence method annotated with @DroolsConsequence. Consequence methods must return void, otherwise a runtime exception will be thrown. Like condition methods, consequence methods can utilize facts and application-data by declaring parameters annotated with @DroolsParameter and @DroolsApplicationData respectively. In addition, consequence methods can declare a single parameter of type KnowledgeHelper to gain access to the drools run-time.

Example:
@DroolsConsequence
public void consequence(KnowledgeHelper knowledgeHelper,
                        @DroolsParameter("order") Order order,
                        @DroolsApplicationData("accountBilling") AccountBilling accountBilling) {
    BillingItem billingItem = new BillingItem(order, ...);                        
    accountBilling.addBillingItem(billingItem);
    knowledgeHelper.revokeObject(order);
}

Annotations and Parameter Types Summary

Annotation Target
@DroolsRule ElementType.TYPE
@DroolsCondition ElementType.MTEHOD
@DroolsConsequence ElementType.METHOD
@DroolsParameter ElementType.PARAMETER
@DroolsApplicationData ElementType.PARAMETER
Parameters Context
KnowledgeHelper consequence method parameter

Loading with DRL

Annotated POJO rules are declared in the DRL file similar to other rules. However no nested elements are required, as this information is extracted from the annotations. Note that you must use <annotation:rule> instead of <rule>. The standard rule attribute can be specified on the <annotation:rule> element. Annotated POJO rules loaded via a DRL file must have a default or no-argument constructor.

Example:
<rule-set ...>
    <annotation:rule name="Hello World" salience="10"
        class="org.drools.semantics.annotation.examples.helloworld.HelloWorldRules$Hello" />

    <annotation:rule name="Goodbye Cruel World" salience="10"
        class="org.drools.semantics.annotation.examples.helloworld.HelloWorldRules$Goodbye" />

    <annotation:rule name="Debug" salience="20" noloop="true"
        class="org.drools.semantics.annotation.examples.helloworld.HelloWorldRules$Debug" />
</rule-set>

Annotated POJO rules can be freely mixed with rules from other semantic modules.

Example:
<rule-set ...>
    <java:import>java.lang.Object</java:import>
    <java:import>java.lang.String</java:import>

    <java:functions>
        public void printHelloWorld(String hello) {
        System.err.println(hello + " World"); }
    </java:functions>

    <rule name="Hello World">
        <parameter identifier="hello">
            <class>String</class>
        </parameter>

        <java:condition>hello.equals("Hello")</java:condition>

        <java:consequence>printHelloWorld(hello);</java:consequence>
    </rule>

    <annotation:rule name="Goodbye Cruel World"
        class="org.drools.semantics.annotation.examples.helloworld.HelloWorldRules$Goodbye" />

    <rule name="Debug">
        <parameter identifier="object">
            <class>Object</class>
        </parameter>

        <groovy:consequence>println "Asserted object: " + object;</groovy:consequence>
    </rule>
</rule-set>

See HelloWordDrlExample for a complete program.

Note: The syntax for defining annotation rules in DRL files may change prior to 1.0 release. Rather than a <annotation:rule> element, <annotation:class> will be nested under <rule>.

Loading Native

Annotation rules can be added a RuleSet directly. The Rule instances is created with the use of AnnotatedPojoRuleBuilder.

Example:
RuleSet ruleSet = new RuleSet("native rule-set");
AnnonatedPojoRuleBuilder annoRuleBuilder = new AnnonatedPojoRuleBuilder();
ruleSet.addRule(annoRuleBuilder.buildRule(new Rule("Hello"), new HelloWorldRules.Hello()));
ruleSet.addRule(annoRuleBuilder.buildRule(new Rule("Goodbye"), new HelloWorldRules.Goodbye()));
ruleSet.addRule(annoRuleBuilder.buildRule(new Rule("Debug"), new HelloWorldRules.Debug()));

Rule properties or POJO properties can be set directly.

Example:
Rule rule = new Rule("Hello");
rule.setSalience(...);
rule.setDuration(...);

HellowWorldRules.Hello pojo = new HelloWorldRules.Hello();
pojo.setMessage("Hi There");
Rule rule = annoRuleBuilder.buildRule(rule, pojo);

ruleSet.addRule(rule);

See HelloWordNativeExample for a complete program.

Loading with Spring

Annotated rules and rule-sets can be declared and loaded from a Spring config file.

Example:
<beans>

    <bean id="ruleSet" abstract="true"
        class="org.drools.semantics.annotation.spring.RuleSetFactory" />
        
    <bean id="rule" abstract="true"
        class="org.drools.semantics.annotation.spring.RuleFactory" />
        
    <bean id="messagePrinter"
        class="org.drools.semantics.annotation.examples.helloworld.MessagePrinter" />

    <bean id="messagePrintingBean" abstract="true">
        <property name="messagePrinter">
            <ref local="messagePrinter" />
        </property>
    </bean>

    <bean id="ruleSet" parent="ruleSet">
        <property name="name">
            <value>rule-set</value>
        </property>
        <property name="rules">
            <set>
                <bean parent="rule">
                    <property name="name">
                        <value>Hello</value>
                    </property>
                    <property name="pojo">
                        <bean parent="messagePrintingBean"
                            class="examples.helloworld.HelloRule" />
                    </property>
                </bean>
                <bean parent="rule">
                    <property name="name">
                        <value>Goodbye</value>
                    </property>
                    <property name="pojo">
                        <bean parent="messagePrintingBean"
                            class="examples.helloworld.GoodbyeRule" />
                    </property>
                </bean>
                <bean parent="rule">
                    <property name="name">
                        <value>Debug</value>
                    </property>
                    <property name="pojo">
                        <bean
                            class="examples.helloworld.DebugRule" />
                    </property>
                </bean>
            </set>
        </property>
    </bean>
    
</beans>
Example:
ApplicationContext context = new ClassPathXmlApplicationContext("examples/helloworld/helloworld.appctx.xml");
RuleSet ruleSet = (RuleSet) context.getBean("ruleSet");
RuleBaseBuilder builder = new RuleBaseBuilder();
builder.addRuleSet(ruleSet);
RuleBase ruleBase = builder.build();

WorkingMemory workingMemory = ruleBase.newWorkingMemory();
// assert facts
workingMemory.fireRules();

See HelloWorldSpringInnerPojosExample and HelloWorldSpringOutterPojosExample for complete programs.

Labels

 
(None)