[jboss-svn-commits] JBL Code SVN: r34227 - labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-compiler/src/test/java/org/drools/integrationtests.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Tue Jul 27 13:18:13 EDT 2010
Author: eaa
Date: 2010-07-27 13:18:13 -0400 (Tue, 27 Jul 2010)
New Revision: 34227
Modified:
labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-compiler/src/test/java/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.java
Log:
JBRULES-2595: Extend ProcessEventListener to add support for low-level exceptions occurred in a process execution
- Updated test case for subprocesses
Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-compiler/src/test/java/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-compiler/src/test/java/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.java 2010-07-27 16:56:36 UTC (rev 34226)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-compiler/src/test/java/org/drools/integrationtests/ProcessNodeExceptionOccurredEventTest.java 2010-07-27 17:18:13 UTC (rev 34227)
@@ -1,8 +1,7 @@
package org.drools.integrationtests;
+import org.drools.impl.StatefulKnowledgeSessionImpl.ProcessEventListenerWrapper;
import org.drools.Person;
-import org.drools.runtime.process.WorkItem;
-import org.drools.runtime.process.WorkItemHandler;
import java.util.List;
import java.util.ArrayList;
import org.drools.KnowledgeBase;
@@ -14,30 +13,85 @@
import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
-import org.drools.runtime.process.WorkItemManager;
import org.junit.Assert;
import org.junit.Test;
+
+import org.drools.RuleBaseFactory;
+import org.drools.common.AbstractRuleBase;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.ruleflow.core.RuleFlowProcess;
+import org.drools.runtime.process.WorkItem;
+import org.drools.runtime.process.WorkItemHandler;
+import org.drools.runtime.process.WorkItemManager;
+import org.drools.WorkingMemory;
+import org.drools.spi.Action;
+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 static org.junit.Assert.*;
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;
- public ExpectedResult(String nodeName, 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();
@@ -56,6 +110,9 @@
}
}
+ /**
+ * A custom WorkItemHandler that will throw an exception when invoked.
+ */
private static class FailWorkItemHandler implements WorkItemHandler {
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
@@ -66,12 +123,31 @@
}
}
-
+ /**
+ * 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 onNodeException(ProcessNodeExceptionOccurredEvent event) {
exceptionCount++;
@@ -79,8 +155,15 @@
}
}
+ /**
+ * 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()) {
@@ -89,12 +172,12 @@
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());
-
- this.expectedResult = new ExpectedResult("Some Script", "java.lang.NullPointerException");
+ //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!");
@@ -104,19 +187,21 @@
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());
-
- this.expectedResult = new ExpectedResult("HumanTask", "java.lang.UnsupportedOperationException");
-
+ //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!");
@@ -128,4 +213,103 @@
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(KnowledgeHelper knowledgeHelper, WorkingMemory workingMemory, 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;
+ }
}
More information about the jboss-svn-commits
mailing list