[seam-commits] Seam SVN: r11112 - in branches/community/Seam_2_2: doc/Seam_Reference_Guide/en-US and 7 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Wed Jun 10 18:33:06 EDT 2009


Author: tsurdilovic
Date: 2009-06-10 18:33:06 -0400 (Wed, 10 Jun 2009)
New Revision: 11112

Added:
   branches/community/Seam_2_2/examples/drools/resources/numberguess.xls
   branches/community/Seam_2_2/examples/drools/src/org/jboss/seam/example/numberguess/GameConsequenceExceptionHandler.java
Modified:
   branches/community/Seam_2_2/build/core.pom.xml
   branches/community/Seam_2_2/build/root.pom.xml
   branches/community/Seam_2_2/doc/Seam_Reference_Guide/en-US/Drools.xml
   branches/community/Seam_2_2/examples/build.xml
   branches/community/Seam_2_2/examples/drools/resources/WEB-INF/components.xml
   branches/community/Seam_2_2/seam-gen/ivy/ivy.xml
   branches/community/Seam_2_2/src/main/org/jboss/seam/drools-2.2.xsd
   branches/community/Seam_2_2/src/main/org/jboss/seam/drools/ManagedWorkingMemory.java
   branches/community/Seam_2_2/src/main/org/jboss/seam/drools/RuleBase.java
Log:
JBSEAM-4049 - Drools Custom Consequence Exception handlers 	
JBSEAM-4188	- Add decision table support to org.jboss.seam.drools.RuleBase 	
JBSEAM-4225	- Allow to add eventListeners to WorkingMemory

Modified: branches/community/Seam_2_2/build/core.pom.xml
===================================================================
--- branches/community/Seam_2_2/build/core.pom.xml	2009-06-10 18:17:22 UTC (rev 11111)
+++ branches/community/Seam_2_2/build/core.pom.xml	2009-06-10 22:33:06 UTC (rev 11112)
@@ -251,6 +251,25 @@
       <artifactId>drools-compiler</artifactId>
       <optional>true</optional>
     </dependency>
+    
+    
+     <dependency>
+     	<groupId>org.drools</groupId>
+     	<artifactId>drools-decisiontables</artifactId>
+     	<optional>true</optional>
+     	<exclusions>
+         	<exclusion>
+            	<groupId>jexcelapi</groupId>
+      			<artifactId>jxl</artifactId>
+          	</exclusion>
+        </exclusions>
+     </dependency>
+ 	 	
+	 <dependency>
+		<groupId>net.sourceforge.jexcelapi</groupId>
+		<artifactId>jxl</artifactId>
+		<optional>true</optional>
+	 </dependency>
 
     <!-- Surefire can't cope with such a new version of testng, so we have to specify it
       here, otherwise ui build fails -->

Modified: branches/community/Seam_2_2/build/root.pom.xml
===================================================================
--- branches/community/Seam_2_2/build/root.pom.xml	2009-06-10 18:17:22 UTC (rev 11111)
+++ branches/community/Seam_2_2/build/root.pom.xml	2009-06-10 22:33:06 UTC (rev 11112)
@@ -786,6 +786,18 @@
         </exclusions>
       </dependency>
 
+	  <dependency>
+        <groupId>org.drools</groupId>
+        <artifactId>drools-decisiontables</artifactId>
+        <version>${version.drools}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>jexcelapi</groupId>
+      		<artifactId>jxl</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+
       <dependency>
         <groupId>org.drools</groupId>
         <artifactId>drools-compiler</artifactId>

Modified: branches/community/Seam_2_2/doc/Seam_Reference_Guide/en-US/Drools.xml
===================================================================
--- branches/community/Seam_2_2/doc/Seam_Reference_Guide/en-US/Drools.xml	2009-06-10 18:17:22 UTC (rev 11111)
+++ branches/community/Seam_2_2/doc/Seam_Reference_Guide/en-US/Drools.xml	2009-06-10 22:33:06 UTC (rev 11112)
@@ -26,7 +26,7 @@
 </drools:rule-base>]]></programlisting>
 
          <para>
-             This component compiles rules from a set of <literal>.drl</literal>
+             This component compiles rules from a set of DRL (<literal>.drl</literal>) or decision table (<literal>.xls</literal>)
              files and caches an instance of <literal>org.drools.RuleBase</literal>
              in the Seam <literal>APPLICATION</literal> context. Note that it is 
              quite likely that you will need to install multiple rule bases in a 
@@ -44,6 +44,40 @@
     </drools:rule-files>
 </drools:rule-base>]]></programlisting>
 
+         <para>
+             If you want to register a custom consequence exception handler through the RuleBaseConfiguration, you need to 
+             write the handler, for example: 
+         </para>
+         
+        <programlisting role="JAVA"><![CDATA[@Scope(ScopeType.APPLICATION)
+ at Startup
+ at Name("myConsequenceExceptionHandler")
+public class MyConsequenceExceptionHandler implements ConsequenceExceptionHandler, Externalizable {
+
+   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+   }
+
+   public void writeExternal(ObjectOutput out) throws IOException {
+   }
+
+   public void handleException(Activation activation,
+                               WorkingMemory workingMemory,
+                               Exception exception) {
+       throw new ConsequenceException( exception,
+                                       activation.getRule() );
+   }
+
+}]]></programlisting>
+
+		<para>
+		and register it:
+		</para>
+		<programlisting role="XML"><![CDATA[<drools:rule-base name="policyPricingRules" dsl-file="policyPricing.dsl" consequence-exception-handler="#{myConsequenceExceptionHandler}">
+    <drools:rule-files>
+        <value>policyPricingRules.drl</value>
+    </drools:rule-files>
+</drools:rule-base>]]></programlisting>
+
         <para>
         In most rules-driven applications,
             rules need to be dynamically deployable, so a production application will want to use a
@@ -86,7 +120,18 @@
              reference back to our rule base via the <literal>ruleBase</literal>
              configuration property.
          </para>
+                  
+         <para>
+         	We can also add means to be notified of rule engine events, including rules firing, objects being asserted, etc. 
+         	by adding event listeners to WorkingMemory.
+         </para>
          
+         <programlisting role="XML"><![CDATA[<drools:managed-working-memory name="policyPricingWorkingMemory" auto-create="true" rule-base="#{policyPricingRules}">
+	<drools:event-listeners>
+    	<value>org.drools.event.DebugWorkingMemoryEventListener</value>
+        <value>org.drools.event.DebugAgendaEventListener</value>
+	</drools:event-listeners>
+</drools:managed-working-memory>]]></programlisting>
      </section>
      
      <section>

Modified: branches/community/Seam_2_2/examples/build.xml
===================================================================
--- branches/community/Seam_2_2/examples/build.xml	2009-06-10 18:17:22 UTC (rev 11111)
+++ branches/community/Seam_2_2/examples/build.xml	2009-06-10 22:33:06 UTC (rev 11112)
@@ -325,6 +325,8 @@
 		<include name="mvel14.jar" if="drools.lib" />
 		<include name="drools-core.jar" if="drools.lib" />
 		<include name="drools-compiler.jar" if="drools.lib" />
+		<include name="drools-decisiontables.jar" if="drools.lib"/>
+		<include name="jxl.jar" if="drools.lib"/>
 	</fileset>
 
 	<!-- Dependencies for using Spring with Cglib -->
@@ -470,6 +472,11 @@
 		<include name="*.jpdl.xml" />
 		<exclude name=".gpd*" />
 	</fileset>
+	
+	<!-- binary resources to go in the jar -->
+		<fileset id="jar.binary.resources" dir="${resources.dir}">
+			<include name="*.xls" />
+		</fileset>
 
 	<!-- resources to go in the jar for tomcat  -->
 	<fileset id="tomcat.jar.resources" dir="${resources.dir}">
@@ -652,6 +659,11 @@
 				<filter token="distributable" value="${distributable}" />
 			</filterset>
 		</copy>
+		<!-- copy decision tables (binary) without the filter definitions
+			 so that they won't get corrupted -->
+		<copy todir="${jar.dir}">
+			<fileset refid="jar.binary.resources" />
+		</copy>
 	</target>
 	
 	<target name="init.war">

Modified: branches/community/Seam_2_2/examples/drools/resources/WEB-INF/components.xml
===================================================================
--- branches/community/Seam_2_2/examples/drools/resources/WEB-INF/components.xml	2009-06-10 18:17:22 UTC (rev 11111)
+++ branches/community/Seam_2_2/examples/drools/resources/WEB-INF/components.xml	2009-06-10 22:33:06 UTC (rev 11112)
@@ -10,8 +10,18 @@
                  http://jboss.com/products/seam/bpm http://jboss.com/products/seam/bpm-2.2.xsd">
             
     <drools:rule-base name="ruleBase" rule-files="numberguess.drl"/>
-    <drools:managed-working-memory name="workingMemory" rule-base="#{ruleBase}"/>
-
+    <!-- use this in order to load from decision table instead -->        
+    <!-- <drools:rule-base name="ruleBase" rule-files="numberguess.xls"/>  -->
+    <!--  use this if you want to register a custom consequence exception handler -->
+    <!--  <drools:rule-base name="ruleBase" rule-files="numberguess.xls" consequence-exception-handler="#{gameConsequenceExceptionHandler}"/>  -->
+    <drools:managed-working-memory name="workingMemory" rule-base="#{ruleBase}">
+    	<!--  add WM event listeners -->
+    	<!-- <drools:event-listeners>
+           <value>org.drools.event.DebugWorkingMemoryEventListener</value>
+           <value>org.drools.event.DebugAgendaEventListener</value>
+        </drools:event-listeners>  -->
+    </drools:managed-working-memory>
+    
     <bpm:jbpm>
         <bpm:pageflow-definitions>
             <value>pageflow.jpdl.xml</value>

Added: branches/community/Seam_2_2/examples/drools/resources/numberguess.xls
===================================================================
(Binary files differ)


Property changes on: branches/community/Seam_2_2/examples/drools/resources/numberguess.xls
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/community/Seam_2_2/examples/drools/src/org/jboss/seam/example/numberguess/GameConsequenceExceptionHandler.java
===================================================================
--- branches/community/Seam_2_2/examples/drools/src/org/jboss/seam/example/numberguess/GameConsequenceExceptionHandler.java	                        (rev 0)
+++ branches/community/Seam_2_2/examples/drools/src/org/jboss/seam/example/numberguess/GameConsequenceExceptionHandler.java	2009-06-10 22:33:06 UTC (rev 11112)
@@ -0,0 +1,37 @@
+package org.jboss.seam.example.numberguess;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.Activation;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.ConsequenceExceptionHandler;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.Startup;
+
+ at Scope(ScopeType.APPLICATION)
+ at Startup
+ at Name("gameConsequenceExceptionHandler")
+public class GameConsequenceExceptionHandler implements ConsequenceExceptionHandler, Externalizable {
+
+   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+   }
+
+   public void writeExternal(ObjectOutput out) throws IOException {
+   }
+
+   public void handleException(Activation activation,
+                               WorkingMemory workingMemory,
+                               Exception exception) {
+       throw new ConsequenceException( exception,
+                                       activation.getRule() );
+   }
+
+}
+
+

Modified: branches/community/Seam_2_2/seam-gen/ivy/ivy.xml
===================================================================
--- branches/community/Seam_2_2/seam-gen/ivy/ivy.xml	2009-06-10 18:17:22 UTC (rev 11111)
+++ branches/community/Seam_2_2/seam-gen/ivy/ivy.xml	2009-06-10 22:33:06 UTC (rev 11112)
@@ -56,6 +56,9 @@
 		<dependency org="org.drools" name="drools-core" rev="4.0.4">
 			<artifact name="drools-core" type="jar"/>
 		</dependency>
+		<dependency org="org.drools" name="drools-decisiontables" rev="4.0.4">
+        	<artifact name="drools-decisiontables" type="jar"/>
+        </dependency>
 		<dependency org="org.eclipse.jdt" name="core" rev="3.2.3.v_686_R32x">
 			<artifact name="core" type="jar"/>
 		</dependency>

Modified: branches/community/Seam_2_2/src/main/org/jboss/seam/drools/ManagedWorkingMemory.java
===================================================================
--- branches/community/Seam_2_2/src/main/org/jboss/seam/drools/ManagedWorkingMemory.java	2009-06-10 18:17:22 UTC (rev 11111)
+++ branches/community/Seam_2_2/src/main/org/jboss/seam/drools/ManagedWorkingMemory.java	2009-06-10 22:33:06 UTC (rev 11112)
@@ -5,6 +5,9 @@
 import org.drools.RuleBase;
 import org.drools.StatefulSession;
 import org.drools.spi.GlobalResolver;
+import org.drools.event.AgendaEventListener;
+import org.drools.event.RuleFlowEventListener;
+import org.drools.event.WorkingMemoryEventListener;
 import org.jboss.seam.Component;
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.annotations.Destroy;
@@ -13,11 +16,14 @@
 import org.jboss.seam.annotations.intercept.BypassInterceptors;
 import org.jboss.seam.core.Mutable;
 import org.jboss.seam.core.Expressions.ValueExpression;
+import org.jboss.seam.log.LogProvider;
+import org.jboss.seam.log.Logging;
 
 /**
  * A conversation-scoped Drools WorkingMemory for a named RuleBase
  * 
  * @author Gavin King
+ * @author Tihomir Surdilovic
  *
  */
 @Scope(ScopeType.CONVERSATION)
@@ -26,7 +32,10 @@
 {
    private static final long serialVersionUID = -1746942080571374743L;
    
+   private static final LogProvider log = Logging.getLogProvider(ManagedWorkingMemory.class);
+   
    private String ruleBaseName;
+   private String[] eventListeners;
    private StatefulSession statefulSession;
    private ValueExpression<RuleBase> ruleBase;
    
@@ -66,9 +75,47 @@
       {
          statefulSession = getRuleBaseFromValueBinding().newStatefulSession();
          statefulSession.setGlobalResolver( createGlobalResolver( statefulSession.getGlobalResolver() ) );
+         if(eventListeners != null) {
+            setEventListeners(statefulSession);
+         }
       }
       return statefulSession;
    }
+   
+   private void setEventListeners(StatefulSession statefulSession) 
+   {
+      if(eventListeners != null) {
+         for(String eventListener : eventListeners) 
+         {
+            log.debug("adding eventListener: " + eventListener);
+            try
+            {
+               Class eventListenerClass = Class.forName(eventListener);
+               Object eventListenerObject = eventListenerClass.newInstance();
+               if(eventListenerObject instanceof WorkingMemoryEventListener) 
+               {
+                  statefulSession.addEventListener((WorkingMemoryEventListener) eventListenerObject);
+               } 
+               else if(eventListenerObject instanceof AgendaEventListener) 
+               {
+                  statefulSession.addEventListener((AgendaEventListener) eventListenerObject);
+               } 
+               else if(eventListenerObject instanceof RuleFlowEventListener) 
+               {
+                  statefulSession.addEventListener((RuleFlowEventListener) eventListenerObject);
+               } 
+               else 
+               {
+                  log.debug("event Listener is not of valid type - bypassing.");
+               }
+            }
+            catch (Exception e)
+            {
+               log.error("error adding event listener " + eventListener + " - bypassing.");
+            }
+         }
+      }
+   }
 
    protected RuleBase getRuleBaseFromValueBinding()
    {
@@ -115,4 +162,13 @@
       this.ruleBase = ruleBase;
    }
    
+   public String[] getEventListeners()
+   {
+      return eventListeners;
+   }
+
+   public void setEventListeners(String[] eventListeners)
+   {
+      this.eventListeners = eventListeners;
+   }
 }

Modified: branches/community/Seam_2_2/src/main/org/jboss/seam/drools/RuleBase.java
===================================================================
--- branches/community/Seam_2_2/src/main/org/jboss/seam/drools/RuleBase.java	2009-06-10 18:17:22 UTC (rev 11111)
+++ branches/community/Seam_2_2/src/main/org/jboss/seam/drools/RuleBase.java	2009-06-10 22:33:06 UTC (rev 11112)
@@ -1,20 +1,26 @@
 package org.jboss.seam.drools;
 
+import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 
+import org.drools.RuleBaseConfiguration;
 import org.drools.RuleBaseFactory;
 import org.drools.compiler.DroolsError;
 import org.drools.compiler.PackageBuilder;
 import org.drools.compiler.PackageBuilderConfiguration;
 import org.drools.compiler.RuleError;
+import org.drools.decisiontable.InputType;
+import org.drools.decisiontable.SpreadsheetCompiler;
+import org.drools.spi.ConsequenceExceptionHandler;
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.annotations.Create;
 import org.jboss.seam.annotations.Scope;
 import org.jboss.seam.annotations.Unwrap;
 import org.jboss.seam.annotations.intercept.BypassInterceptors;
 import org.jboss.seam.core.ResourceLoader;
+import org.jboss.seam.core.Expressions.ValueExpression;
 import org.jboss.seam.log.LogProvider;
 import org.jboss.seam.log.Logging;
 
@@ -22,6 +28,7 @@
  * Manager component for a Drools RuleBase
  * 
  * @author Gavin King
+ * @author Tihomir Surdilovic
  *
  */
 @Scope(ScopeType.APPLICATION)
@@ -32,6 +39,7 @@
    
    private String[] ruleFiles;
    private String dslFile;
+   private ValueExpression<ConsequenceExceptionHandler> consequenceExceptionHandler;
    private org.drools.RuleBase ruleBase;
    
    @Create
@@ -50,18 +58,32 @@
             {
                throw new IllegalStateException("could not locate rule file: " + ruleFile);
             }
-            // read in the source
-            Reader drlReader = new InputStreamReader(stream);
-                                  
-            if (dslFile==null)
+            
+            if(isDecisionTable(ruleFile)) 
             {
-               builder.addPackageFromDrl(drlReader);               
+               log.debug("compiling decision table");
+               SpreadsheetCompiler compiler = new SpreadsheetCompiler();
+               String drl = compiler.compile(stream, InputType.XLS);
+               
+               log.debug("creating source");               
+               byte currentXMLBytes[] = drl.getBytes();
+               InputStreamReader source = new InputStreamReader(new ByteArrayInputStream(currentXMLBytes)); 
+               
+               builder.addPackageFromDrl(source);
+            } else {             
+               // read in the source
+               Reader drlReader = new InputStreamReader(stream);
+               
+               if (dslFile==null)
+               {
+                  builder.addPackageFromDrl(drlReader);               
+               }
+               else
+               {
+                  Reader dslReader = new InputStreamReader( ResourceLoader.instance().getResourceAsStream(dslFile) );
+                  builder.addPackageFromDrl(drlReader, dslReader);
+               }
             }
-            else
-            {
-               Reader dslReader = new InputStreamReader( ResourceLoader.instance().getResourceAsStream(dslFile) );
-               builder.addPackageFromDrl(drlReader, dslReader);
-            }
             
             if ( builder.hasErrors() )
             {
@@ -82,8 +104,18 @@
          }
       }
       
-      // add the package to a rulebase
-      ruleBase = RuleBaseFactory.newRuleBase();
+      if(consequenceExceptionHandler != null) 
+      {
+         log.debug("adding consequence exception handler: " + consequenceExceptionHandler.getExpressionString());
+         RuleBaseConfiguration rbconf = new RuleBaseConfiguration();
+         rbconf.setConsequenceExceptionHandler(consequenceExceptionHandler.getValue());
+         ruleBase = RuleBaseFactory.newRuleBase( rbconf );
+      }
+      else 
+      {
+         ruleBase = RuleBaseFactory.newRuleBase();
+      }
+      
       ruleBase.addPackage( builder.getPackage() );
    }
    
@@ -113,4 +145,19 @@
       this.dslFile = dslFile;
    }
    
+   public ValueExpression<ConsequenceExceptionHandler> getConsequenceExceptionHandler()
+   {
+      return consequenceExceptionHandler;
+   }
+
+   public void setConsequenceExceptionHandler(ValueExpression<ConsequenceExceptionHandler> consequenceExceptionHandler)
+   {
+      this.consequenceExceptionHandler = consequenceExceptionHandler;
+   }
+
+   private boolean isDecisionTable(String fileName) 
+   {
+      return fileName != null && fileName.length() > 0 && fileName.endsWith(".xls");
+   }
+   
 }

Modified: branches/community/Seam_2_2/src/main/org/jboss/seam/drools-2.2.xsd
===================================================================
--- branches/community/Seam_2_2/src/main/org/jboss/seam/drools-2.2.xsd	2009-06-10 18:17:22 UTC (rev 11111)
+++ branches/community/Seam_2_2/src/main/org/jboss/seam/drools-2.2.xsd	2009-06-10 22:33:06 UTC (rev 11112)
@@ -20,7 +20,8 @@
     <xs:element name="rule-files" type="components:multiValuedProperty"/>
     <xs:attributeGroup name="attlist.RuleBase">
         <xs:attribute name="dsl-file" type="components:string"/>
-        <xs:attribute name="rule-files" type="components:string"/>        
+        <xs:attribute name="rule-files" type="components:string"/> 
+        <xs:attribute name="consequence-exception-handler" type="components:expressionType"/>       
     </xs:attributeGroup>
 
     <xs:element name="rule-agent">
@@ -47,6 +48,9 @@
             <xs:documentation>A working memory for rules calculations</xs:documentation>
         </xs:annotation>
         <xs:complexType mixed="true">
+        	<xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element minOccurs="0" maxOccurs="1" ref="drools:event-listeners"/>
+            </xs:choice>
             <xs:attributeGroup ref="components:attlist.component"/>
             <xs:attributeGroup ref="drools:attlist.ManagedWorkingMemory"/>
         </xs:complexType>
@@ -54,5 +58,6 @@
     <xs:attributeGroup name="attlist.ManagedWorkingMemory">
         <xs:attribute name="rule-base" type="components:expressionType"/>
     </xs:attributeGroup>
+    <xs:element name="event-listeners" type="components:multiValuedProperty"/>
 
 </xs:schema>




More information about the seam-commits mailing list