| 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.
