[jboss-svn-commits] JBL Code SVN: r35072 - in labs/jbossrules/branches/diega_esteban_jpm_integration_r34940: drools-core/src/main/java/org/drools/audit and 7 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Sep 8 15:20:38 EDT 2010


Author: diegoll
Date: 2010-09-08 15:20:37 -0400 (Wed, 08 Sep 2010)
New Revision: 35072

Added:
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/ProcessNodeExceptionOccurredEvent.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/ProcessNodeExceptionOccurredEventImpl.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/java/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/resources/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest_2.rf
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/main/java/org/drools/workflow/instance/impl/ProcessNodeExecutionException.java
Modified:
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/DefaultProcessEventListener.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/ProcessEventListener.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/audit/WorkingMemoryLogger.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/DebugProcessEventListener.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/DefaultProcessEventListener.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/ProcessEventSupport.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/management/KnowledgeSessionMonitoring.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/java/org/drools/integrationtests/ProcessEventListenerTest.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/test/java/org/drools/event/process/ProcessEventSupportTest.java
   labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-persistence-jpa/src/test/java/org/drools/persistence/session/PersistentStatefulSessionTest.java
Log:
[JBRULES-2595] merging with rev35043

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/DefaultProcessEventListener.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/DefaultProcessEventListener.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/DefaultProcessEventListener.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -52,4 +52,9 @@
         // intentionally left blank
     }
 
+    public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
 }
\ No newline at end of file

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/ProcessEventListener.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/ProcessEventListener.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/ProcessEventListener.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -39,4 +39,5 @@
 
     void afterNodeLeft(ProcessNodeLeftEvent event);
 
+    void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event);
 }
\ No newline at end of file

Added: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/ProcessNodeExceptionOccurredEvent.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/ProcessNodeExceptionOccurredEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/ProcessNodeExceptionOccurredEvent.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -0,0 +1,8 @@
+package org.drools.event.process;
+
+public interface ProcessNodeExceptionOccurredEvent
+    extends
+    ProcessNodeEvent {
+
+    Throwable getError();
+}


Property changes on: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-api/src/main/java/org/drools/event/process/ProcessNodeExceptionOccurredEvent.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/audit/WorkingMemoryLogger.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/audit/WorkingMemoryLogger.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/audit/WorkingMemoryLogger.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -72,6 +72,7 @@
 import org.drools.event.WorkingMemoryEventListener;
 import org.drools.event.process.ProcessCompletedEvent;
 import org.drools.event.process.ProcessEventListener;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
 import org.drools.event.process.ProcessNodeLeftEvent;
 import org.drools.event.process.ProcessNodeTriggeredEvent;
 import org.drools.event.process.ProcessStartedEvent;
@@ -461,6 +462,16 @@
                 event.getProcessInstance().getId()) );
     }
     
+    public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+//      filterLogEvent(new RuleFlowVariableLogEvent(LogEvent.AFTER_VARIABLE_INSTANCE_CHANGED,
+//          event.getVariableId(),
+//          event.getVariableInstanceId(),
+//          event.getProcessInstance().getProcessId(),
+//          event.getProcessInstance().getProcessName(),
+//          event.getProcessInstance().getId(),
+//          event.getValue() == null ? "null" : event.getValue().toString() ));
+    }
+    
     private String createNodeId(NodeInstance nodeInstance) {
     	Node node = nodeInstance.getNode();
     	if (node == null) {

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/DebugProcessEventListener.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/DebugProcessEventListener.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/DebugProcessEventListener.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -18,6 +18,7 @@
 
 import org.drools.event.process.ProcessCompletedEvent;
 import org.drools.event.process.ProcessEventListener;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
 import org.drools.event.process.ProcessNodeLeftEvent;
 import org.drools.event.process.ProcessNodeTriggeredEvent;
 import org.drools.event.process.ProcessStartedEvent;
@@ -56,4 +57,8 @@
 		System.err.println(event);
 	}
 
+    public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+        System.err.println(event);
+    }
+
 }

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/DefaultProcessEventListener.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/DefaultProcessEventListener.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/DefaultProcessEventListener.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -18,6 +18,7 @@
 
 import org.drools.event.process.ProcessCompletedEvent;
 import org.drools.event.process.ProcessEventListener;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
 import org.drools.event.process.ProcessNodeLeftEvent;
 import org.drools.event.process.ProcessNodeTriggeredEvent;
 import org.drools.event.process.ProcessStartedEvent;
@@ -48,4 +49,7 @@
 	public void beforeProcessStarted(ProcessStartedEvent event) {
 	}
 
+    public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+    }
+
 }

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/ProcessEventSupport.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/ProcessEventSupport.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/ProcessEventSupport.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -20,6 +20,7 @@
 
 import org.drools.event.process.ProcessCompletedEvent;
 import org.drools.event.process.ProcessEventListener;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
 import org.drools.event.process.ProcessNodeLeftEvent;
 import org.drools.event.process.ProcessNodeTriggeredEvent;
 import org.drools.event.process.ProcessStartedEvent;
@@ -129,6 +130,18 @@
         }
     }
 
+    public void fireRuleFlowNodeExceptionOccurred(final ProcessInstance processInstance,
+                                                  NodeInstance nodeInstance, 
+                                                  KnowledgeRuntime kruntime, 
+                                                  Throwable error) {
+        for(ProcessEventListener listener : getEventListeners()){
+            ProcessNodeExceptionOccurredEvent event = new ProcessNodeExceptionOccurredEventImpl( nodeInstance,
+                                                                                             kruntime,
+                                                                                             error );
+            listener.processNodeExceptionOccurred( event );
+        }
+    }
+    
     public void reset() {
         this.clear();
     }

Added: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/ProcessNodeExceptionOccurredEventImpl.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/ProcessNodeExceptionOccurredEventImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/ProcessNodeExceptionOccurredEventImpl.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -0,0 +1,44 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *  under the License.
+ */
+
+package org.drools.event;
+
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
+import org.drools.runtime.KnowledgeRuntime;
+import org.drools.runtime.process.NodeInstance;
+
+/**
+ * @author esteban
+ */
+public class ProcessNodeExceptionOccurredEventImpl extends ProcessNodeTriggeredEventImpl implements ProcessNodeExceptionOccurredEvent {
+
+    private static final long serialVersionUID = 501L;
+    private final Throwable error;
+    
+    public ProcessNodeExceptionOccurredEventImpl(NodeInstance nodeInstance, KnowledgeRuntime kruntime, Throwable error) {
+        super(nodeInstance, kruntime);
+        this.error = error;
+    }
+
+    public Throwable getError() {
+        return error;
+    }
+
+    @Override
+    public String toString() {
+        return "==>[RuleFlowExceptionOccurredEvent(error=" + error +  "; processName=" + getProcessInstance().getProcessName() + "; processId=" + getProcessInstance().getProcessId() + ")]";
+    }
+
+}


Property changes on: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/event/ProcessNodeExceptionOccurredEventImpl.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/management/KnowledgeSessionMonitoring.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/management/KnowledgeSessionMonitoring.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-core/src/main/java/org/drools/management/KnowledgeSessionMonitoring.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -39,6 +39,7 @@
 import org.drools.event.RuleFlowGroupDeactivatedEvent;
 import org.drools.event.process.ProcessCompletedEvent;
 import org.drools.event.process.ProcessEventListener;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
 import org.drools.event.process.ProcessNodeLeftEvent;
 import org.drools.event.process.ProcessNodeTriggeredEvent;
 import org.drools.event.process.ProcessStartedEvent;
@@ -521,6 +522,11 @@
             }
         }
 
+        public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+            // TODO Auto-generated method stub
+            
+        }
+
     }
     
 }

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/java/org/drools/integrationtests/ProcessEventListenerTest.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/java/org/drools/integrationtests/ProcessEventListenerTest.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/java/org/drools/integrationtests/ProcessEventListenerTest.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -31,6 +31,7 @@
 import org.drools.event.process.ProcessCompletedEvent;
 import org.drools.event.process.ProcessEvent;
 import org.drools.event.process.ProcessEventListener;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
 import org.drools.event.process.ProcessNodeLeftEvent;
 import org.drools.event.process.ProcessNodeTriggeredEvent;
 import org.drools.event.process.ProcessStartedEvent;
@@ -126,6 +127,10 @@
                 processEventList.add(event);
 			}
 
+            public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+                processEventList.add(event);
+            }
+
         };
 
         ((InternalWorkingMemory)session).getProcessRuntime().addEventListener(listener);

Added: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/java/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/java/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.java	                        (rev 0)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/java/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -0,0 +1,430 @@
+package org.drools.integrationtests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.KnowledgeBase;
+import org.drools.KnowledgeBaseFactory;
+import org.drools.Person;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.builder.KnowledgeBuilder;
+import org.drools.builder.KnowledgeBuilderFactory;
+import org.drools.builder.ResourceType;
+import org.drools.common.AbstractRuleBase;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.event.process.DefaultProcessEventListener;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
+import org.drools.io.ResourceFactory;
+import org.drools.process.instance.impl.Action;
+import org.drools.process.instance.impl.demo.DoNothingWorkItemHandler;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.ruleflow.core.RuleFlowProcess;
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.process.WorkItem;
+import org.drools.runtime.process.WorkItemHandler;
+import org.drools.runtime.process.WorkItemManager;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.ProcessContext;
+import org.drools.workflow.core.DroolsAction;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.ConnectionImpl;
+import org.drools.workflow.core.impl.DroolsConsequenceAction;
+import org.drools.workflow.core.node.ActionNode;
+import org.drools.workflow.core.node.EndNode;
+import org.drools.workflow.core.node.StartNode;
+import org.drools.workflow.core.node.SubProcessNode;
+import org.drools.workflow.instance.impl.ProcessNodeExecutionException;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ProcessNodeExceptionOccurredEventTest {
+
+    /**
+     * Internal class to express an expected result of a process exception.
+     */
+    private static class ExpectedResult {
+
+        /**
+         * The expected process name where the exception occurred.
+         */
+        private String processName;
+        /**
+         * The expected node name where the exception occurred.
+         */
+        private String nodeName;
+        /**
+         * The expected exception name.
+         */
+        private String expectedException;
+
+        /**
+         * Creates a new ExpectedResult instance
+         * @param processName The expected process name where the exception occurred.
+         * @param nodeName The expected node name where the exception occurred.
+         * @param expectedException The expected exception name.
+         */
+        public ExpectedResult(String processName ,String nodeName, String expectedException) {
+            this.processName = processName;
+            this.nodeName = nodeName;
+            this.expectedException = expectedException;
+        }
+
+        /**
+         * Validates this ExpectedResult instance against a ProcessNodeExceptionOccurredEvent
+         * @param event the ProcessNodeExceptionOccurredEvent triggered by the process
+         */
+        public void validate(ProcessNodeExceptionOccurredEvent event) {
+
+            //Process name validation
+            if (this.processName != null) {
+                assertEquals(this.processName, event.getProcessInstance().getProcessName());
+            }
+
+            //Node name validation
+            if (this.nodeName != null) {
+                assertEquals(this.nodeName, event.getNodeInstance().getNodeName());
+            }
+
+            //Exception name validation. The real exception could not be the
+            //top-level exception of ProcessNodeExceptionOccurredEvent. That is
+            //why we need to navigate through the original exception.
+            if (this.expectedException != null) {
+                boolean found = false;
+                Throwable t = event.getError();
+                while (t != null) {
+                    if (t.toString().contains(this.expectedException)) {
+                        found = true;
+                        break;
+                    }
+                    t = t.getCause();
+                }
+
+                if (!found) {
+                    fail(this.expectedException + " wasn't found!");
+                }
+            }
+        }
+    }
+
+    /**
+     * A custom WorkItemHandler that will throw an exception when invoked.
+     */
+    private static class FailWorkItemHandler implements WorkItemHandler {
+
+        public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
+        }
+    }
+
+    /**
+     * An internal counter to keep track on the total number of exception thrown
+     * during a process execution.
+     */
+    private int exceptionCount = 0;
+
+    /**
+     * A expected result used to validate any  exception thrown
+     * during a process execution.
+     */
+    private ExpectedResult expectedResult;
+
+
+    /**
+     * Custom listener that will process incoming ProcessNodeExceptionOccurredEvent
+     * events. These events are thrown when a RuntimeException occurred inside
+     * a node.
+     */
+    private class CustomListener extends DefaultProcessEventListener {
+
+        /**
+         * Increments the exception counter and validates the generated event
+         * against some expected result.
+         * @param event
+         */
+        @Override
+        public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+            exceptionCount++;
+            expectedResult.validate(event);
+        }
+    }
+
+    private class MyBusinessException extends ProcessNodeExecutionException{
+        private ProcessNodeExceptionOccurredEvent source;
+
+        public MyBusinessException(ProcessNodeExceptionOccurredEvent source){
+            super(source.getError());
+            this.source = source;
+        }
+
+        public String getProcessName(){
+            return this.source.getProcessInstance().getProcessName();
+        }
+
+        public String getNodeName(){
+            return this.source.getNodeInstance().getNodeName();
+        }
+
+        public Throwable getOriginalException(){
+            return this.source.getError();
+        }
+
+        @Override
+        public String toString() {
+            return "MyBusinessException{" + "Original Exception= '" + this.getOriginalException().toString() + "', Process= '"+this.getProcessName()+"', Process= '"+this.getProcessName()+"}";
+        }
+
+    }
+
+    /**
+     * Test of ProcessNodeExceptionOccurredEvent inside an action node and inside
+     * a WorkItemHandler too.
+     * @throws InterruptedException
+     */
+    //@Test
+    public void actionAndWorkItemExceptionTest() throws InterruptedException {
+
+        //Create a new kbase with the given flow.
+        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+        kbuilder.add(ResourceFactory.newClassPathResource("org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.rf"), ResourceType.DRF);
+        if (kbuilder.hasErrors()) {
+            Assert.fail(kbuilder.getErrors().toString());
+        }
+        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
+
+        //Create a ksession and add a custom ProcessEventListener
+        final StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+        ksession.addEventListener(new CustomListener());
+
+        //We are expecting a NPE inside "Some Script" (an action node).
+        this.expectedResult = new ExpectedResult("flow","Some Script", "java.lang.NullPointerException");
+        try {
+            ksession.startProcess("org.drools.test.process1");
+            fail("An exception should occurr!");
+        } catch (RuntimeException ex) {
+            //ok
+        }
+        assertEquals(1, this.exceptionCount);
+        this.exceptionCount = 0;
+
+        //Insert all the needed globals. Inserting a person will make that the
+        //Action node works fine.
+        List<String> list = new ArrayList<String>();
+        Person person = new Person();
+        person.setName("John");
+        ksession.setGlobal("person", person);
+        ksession.setGlobal("list", list);
+
+        //Register a WorkItemHandler. This handler will throw an exception when
+        //invoked.
+        ksession.getWorkItemManager().registerWorkItemHandler("Human Task", new FailWorkItemHandler());
+
+        //We are expecting an UnsupportedOperationException thrown by the
+        //WorkItemHandler ("HumanTask" is its name).
+        this.expectedResult = new ExpectedResult("flow","HumanTask", "java.lang.UnsupportedOperationException");
+        try {
+            ksession.startProcess("org.drools.test.process1");
+            fail("An exception should occurr!");
+        } catch (RuntimeException ex) {
+        }
+        assertEquals(1, this.exceptionCount);
+        this.exceptionCount = 0;
+
+        ksession.dispose();
+    }
+
+    @Test
+    public void testListenerException(){
+        //Create a new kbase with the given flow.
+        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+        kbuilder.add(ResourceFactory.newClassPathResource("org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest_2.rf"), ResourceType.DRF);
+        if (kbuilder.hasErrors()) {
+            Assert.fail(kbuilder.getErrors().toString());
+        }
+        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
+
+        //Create a ksession and add a custom ProcessEventListener
+        final StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+        ksession.addEventListener(new DefaultProcessEventListener(){
+
+            @Override
+            public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+                if (event.getError() instanceof MyBusinessException){
+                    return;
+                }
+                System.out.println("\t"+event.getNodeInstance().getNodeName());
+                exceptionCount++;
+                throw new MyBusinessException(event);
+            }
+
+        });
+
+        //Insert all the needed globals. Inserting a person will make that the
+        //Action node works fine.
+        List<String> list = new ArrayList<String>();
+        Person person = new Person();
+        person.setName("John");
+        ksession.setGlobal("person", person);
+        ksession.setGlobal("list", list);
+
+        //Register a WorkItemHandler. This handler will throw an exception when
+        //invoked.
+        ksession.getWorkItemManager().registerWorkItemHandler("Human Task", new FailWorkItemHandler());
+
+        
+        this.expectedResult = new ExpectedResult("flow","HumanTask", "MyBusinessException");
+        try {
+            ksession.startProcess("org.drools.test.process1");
+            fail("An exception should occurr!");
+        } catch (MyBusinessException ex) {
+            System.out.println("\tMyBusinessException");
+            assertEquals("flow", ex.getProcessName());
+            assertEquals("HumanTask", ex.getNodeName());
+        } catch (Exception ex){
+            ex.printStackTrace();
+            fail("Unexpected Exception: "+ex);
+        }
+        assertEquals(1, this.exceptionCount);
+        this.exceptionCount = 0;
+
+        ///Register a real handler that never completes the WI
+        final List<Long> workItemIds = new ArrayList<Long>();
+        ksession.getWorkItemManager().registerWorkItemHandler("Human Task", new DoNothingWorkItemHandler(){
+
+            @Override
+            public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
+                workItemIds.add(workItem.getId());
+            }
+            
+        });
+
+        //no exceptions now
+        ksession.startProcess("org.drools.test.process1");
+
+        assertEquals(1, workItemIds.size());
+        try {
+            //After the WI is completed, an action node is executed. This
+            //Action Node is suposed to fail (throws an error).
+            ksession.getWorkItemManager().completeWorkItem(workItemIds.get(0), null);
+            fail("An error should occurr!");
+        } catch (MyBusinessException ex) {
+            System.out.println("\tMyBusinessException");
+            assertEquals("flow", ex.getProcessName());
+            assertEquals("Illegal Action Node", ex.getNodeName());
+        } catch (Exception ex){
+            ex.printStackTrace();
+            fail("Unexpected Exception: "+ex);
+        }
+        assertEquals(1, this.exceptionCount);
+        this.exceptionCount = 0;
+
+        ksession.dispose();
+    }
+
+    /**
+     * Test for ProcessNodeExceptionOccurredEvent events thrown inside a subprocess.
+     * This test will define the main process and subprocess using apis instead
+     * of makes use of external .rf files. The result using external flow files
+     * would be the same.
+     */
+    //@Test
+    public void testSubProcess() {
+
+        //Create a new Process (with name= "Process") with the following structure:
+        //Start -> SubProcess -> End
+        RuleFlowProcess process = new RuleFlowProcess();
+        process.setId("org.drools.process.process");
+        process.setName("Process");
+
+        StartNode startNode = new StartNode();
+        startNode.setName("Start");
+        startNode.setId(1);
+        process.addNode(startNode);
+        EndNode endNode = new EndNode();
+        endNode.setName("EndNode");
+        endNode.setId(2);
+        process.addNode(endNode);
+        SubProcessNode subProcessNode = new SubProcessNode();
+        subProcessNode.setName("SubProcessNode");
+        subProcessNode.setId(3);
+        subProcessNode.setProcessId("org.drools.process.subprocess");
+        process.addNode(subProcessNode);
+        new ConnectionImpl(
+            startNode, Node.CONNECTION_DEFAULT_TYPE,
+            subProcessNode, Node.CONNECTION_DEFAULT_TYPE
+        );
+        new ConnectionImpl(
+            subProcessNode, Node.CONNECTION_DEFAULT_TYPE,
+            endNode, Node.CONNECTION_DEFAULT_TYPE
+        );
+
+        //Add the process to a ruleBase.
+        AbstractRuleBase ruleBase = (AbstractRuleBase) RuleBaseFactory.newRuleBase();
+        ruleBase.addProcess(process);
+
+        //Create a new Process (with name= "SubProcess") with the following structure:
+        //Start -> Action -> End
+        //This process is used as subprocess for the later process. The action
+        //node (with name="ActionX") will throw an exception when invoked.
+        process = new RuleFlowProcess();
+        process.setId("org.drools.process.subprocess");
+        process.setName("SubProcess");
+
+        startNode = new StartNode();
+        startNode.setName("Start");
+        startNode.setId(1);
+        process.addNode(startNode);
+        endNode = new EndNode();
+        endNode.setName("EndNode");
+        endNode.setId(2);
+        process.addNode(endNode);
+        ActionNode actionNode = new ActionNode();
+        actionNode.setName("ActionX");
+        DroolsAction action = new DroolsConsequenceAction("java", null);
+        action.setMetaData("Action", new Action() {
+            public void execute(ProcessContext context) throws Exception {
+                throw new IllegalStateException("Something illegal just happened!");
+            }
+        });
+        actionNode.setAction(action);
+        process.addNode(actionNode);
+        new ConnectionImpl(
+            startNode, Node.CONNECTION_DEFAULT_TYPE,
+            actionNode, Node.CONNECTION_DEFAULT_TYPE
+        );
+        new ConnectionImpl(
+    		actionNode, Node.CONNECTION_DEFAULT_TYPE,
+            endNode, Node.CONNECTION_DEFAULT_TYPE
+        );
+
+        //Add the subprocess to ruleBase.
+        ruleBase.addProcess(process);
+
+        //The following 3 steps is the same as creating a new ksession and add
+        //a new instance of CustomListener as process listener.
+        InternalWorkingMemory workingMemory = new ReteooWorkingMemory(1, ruleBase);
+//        ProcessEventListenerWrapper wrapper = new ProcessEventListenerWrapper( new CustomListener() );
+//        workingMemory.addEventListener(wrapper);
+
+        //We spect the suprocess ("SubProcess") to fail inside action node ("ActionX")
+        //because of a IllegalStateException.
+        this.expectedResult = new ExpectedResult("SubProcess","ActionX", "java.lang.IllegalStateException");
+        try {
+            workingMemory.startProcess("org.drools.process.process");
+            fail("An exception should occurr!");
+        } catch (RuntimeException ex) {
+            //ok
+        }
+
+        assertEquals(1,this.exceptionCount);
+        this.exceptionCount=0;
+    }
+}


Property changes on: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/java/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/resources/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest_2.rf
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/resources/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest_2.rf	                        (rev 0)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/resources/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest_2.rf	2010-09-08 19:20:37 UTC (rev 35072)
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?> 
+<process xmlns="http://drools.org/drools-5.0/process"
+         xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+         xs:schemaLocation="http://drools.org/drools-5.0/process drools-processes-5.0.xsd"
+         type="RuleFlow" name="flow" package-name="org.drools.test.process1" id="org.drools.test.process1">
+
+  <header>
+  
+  	<imports>
+      <import name="org.drools.Person" />
+    </imports>
+    <globals>
+      <global identifier="person" type="org.drools.Person" />
+      <global identifier="list" type="java.util.List" />
+    </globals>
+  
+  </header>
+
+  <nodes>
+    <start id="1" name="Start" x="100" y="100" width="48" height="48" />
+     <actionNode id="2" name="Some Script" x="186" y="97" width="80" height="48" >
+      <action type="expression" dialect="java" >
+        System.out.println("Hello "+person.getName());        
+      </action>
+    </actionNode>
+
+
+
+     <workItem id="3" name="HumanTask" >
+      <work name="Human Task" >
+        <parameter name="ActorId" >
+          <type name="org.drools.process.core.datatype.impl.type.StringDataType" />
+          <value>John Doe</value>
+        </parameter>
+        <parameter name="TaskName" >
+          <type name="org.drools.process.core.datatype.impl.type.StringDataType" />
+          <value>Do something</value>
+        </parameter>
+        <parameter name="Priority" >
+          <type name="org.drools.process.core.datatype.impl.type.StringDataType" />
+        </parameter>
+        <parameter name="Comment" >
+          <type name="org.drools.process.core.datatype.impl.type.StringDataType" />
+        </parameter>
+      </work>
+      <onEntry>
+        <action type="expression" name="Print" dialect="mvel" >list.add("Executing on entry action");</action>
+      </onEntry>
+      <onExit>
+        <action type="expression" name="Print" dialect="java" >list.add("Executing on exit action1");</action>
+        <action type="expression" name="Print" dialect="java" >list.add("Executing on exit action2");</action>
+      </onExit>
+    </workItem>
+
+    <actionNode id="4" name="Illegal Action Node" x="186" y="97" width="80" height="48" >
+      <action type="expression" dialect="java" >
+        throw new java.lang.IllegalAccessError("This is illegal!");
+      </action>
+    </actionNode>
+
+    <end id="5" name="End" x="357" y="92" width="48" height="48" />
+  </nodes>
+
+  <connections>
+    <connection from="1" to="2" />
+    <connection from="2" to="3" />
+    <connection from="3" to="4" />
+    <connection from="4" to="5" />
+  </connections>
+
+</process>
\ No newline at end of file


Property changes on: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-compiler/src/test/resources/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest_2.rf
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -20,9 +20,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.drools.WorkingMemory;
 import org.drools.common.InternalKnowledgeRuntime;
-import org.drools.common.InternalWorkingMemory;
 import org.drools.definition.process.Connection;
 import org.drools.definition.process.Node;
 import org.drools.process.core.Context;
@@ -114,6 +112,20 @@
     		hidden = true;
     	}
     	InternalKnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
+        try {
+            internalTrigger(from, type);
+        } catch (ProcessNodeExecutionException ex) {
+            //We don't want to wrap a ProcessNodeExecutionException again.
+            throw ex;
+        } catch (Throwable t) {
+            if (!hidden) {
+            	((InternalProcessRuntime) kruntime.getProcessRuntime())
+        		.getProcessEventSupport().fireRuleFlowNodeExceptionOccurred(processInstance, this, kruntime, t);
+            }
+            //The exception is wrapped in a ProcessNodeExecutionException
+            throw new ProcessNodeExecutionException(t);
+        }
+    	
     	if (!hidden) {
     		((InternalProcessRuntime) kruntime.getProcessRuntime())
     			.getProcessEventSupport().fireBeforeNodeTriggered(this, kruntime);

Added: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/main/java/org/drools/workflow/instance/impl/ProcessNodeExecutionException.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/main/java/org/drools/workflow/instance/impl/ProcessNodeExecutionException.java	                        (rev 0)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/main/java/org/drools/workflow/instance/impl/ProcessNodeExecutionException.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -0,0 +1,14 @@
+package org.drools.workflow.instance.impl;
+
+/**
+ * Exception thrown when an unexpected Exception occurs while executing
+ * a node inside a process.
+ * @author esteban
+ */
+public class ProcessNodeExecutionException extends RuntimeException{
+
+    public ProcessNodeExecutionException(Throwable cause) {
+        super(cause);
+    }
+
+}


Property changes on: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/main/java/org/drools/workflow/instance/impl/ProcessNodeExecutionException.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/test/java/org/drools/event/process/ProcessEventSupportTest.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/test/java/org/drools/event/process/ProcessEventSupportTest.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-flow-core/src/test/java/org/drools/event/process/ProcessEventSupportTest.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -120,6 +120,10 @@
 				processEventList.add(event);
 			}
 
+            public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+                processEventList.add(event);
+            }
+
         };
         session.addEventListener( processEventListener );
 

Modified: labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-persistence-jpa/src/test/java/org/drools/persistence/session/PersistentStatefulSessionTest.java
===================================================================
--- labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-persistence-jpa/src/test/java/org/drools/persistence/session/PersistentStatefulSessionTest.java	2010-09-08 18:12:40 UTC (rev 35071)
+++ labs/jbossrules/branches/diega_esteban_jpm_integration_r34940/drools-persistence-jpa/src/test/java/org/drools/persistence/session/PersistentStatefulSessionTest.java	2010-09-08 19:20:37 UTC (rev 35072)
@@ -22,6 +22,7 @@
 import org.drools.event.process.ProcessCompletedEvent;
 import org.drools.event.process.ProcessEvent;
 import org.drools.event.process.ProcessEventListener;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
 import org.drools.event.process.ProcessNodeLeftEvent;
 import org.drools.event.process.ProcessNodeTriggeredEvent;
 import org.drools.event.process.ProcessStartedEvent;
@@ -535,6 +536,10 @@
 				System.out.println("Before process started");
 				events.add(event);				
 			}
+            public void processNodeExceptionOccurred(ProcessNodeExceptionOccurredEvent event) {
+                System.out.println("On node exception");
+                events.add(event);              
+            }
         };
         ksession.addEventListener(listener);
         



More information about the jboss-svn-commits mailing list