diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/event/BpmnError.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/event/BpmnError.java index e44ef6e6af114b90670b3251adc5d1928b64bc4a..6fd07d1a4fb3bcfa3b68d1dc8827f3d70afc54e9 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/event/BpmnError.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/event/BpmnError.java @@ -39,6 +39,12 @@ public class BpmnError extends ActivitiException { public BpmnError(String errorCode, String message) { super(message); + if (errorCode == null) { + throw new ActivitiException("Error Code must not be null."); + } + if (errorCode.length() < 1) { + throw new ActivitiException("Error Code must not be empty."); + } this.errorCode = errorCode; } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java index 983be2a15eadb991711354ba30810d0a71e610b3..dda34bd8b9e01b067c73e3d3bd36af002c559fbe 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java @@ -34,6 +34,7 @@ import org.activiti.engine.impl.context.Context; import org.activiti.engine.impl.delegate.ExecutionListenerInvocation; import org.activiti.engine.impl.delegate.TaskListenerInvocation; import org.activiti.engine.impl.pvm.PvmActivity; +import org.activiti.engine.impl.pvm.PvmScope; import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.pvm.delegate.SignallableActivityBehavior; @@ -120,25 +121,43 @@ public class ClassDelegate extends AbstractBpmnActivityBehavior implements TaskL } catch (BpmnError error) { // find error handler PvmActivity errorEventHandler = null; - for (PvmActivity activity : execution.getActivity().getActivities()) { - if (((ActivityImpl) activity).getActivityBehavior() instanceof BoundaryEventActivityBehavior) { - // TODO check error code of error handler - errorEventHandler = activity; - break; + // search for error handler with same error code as thrown Error + PvmScope scope = execution.getActivity(); + while (errorEventHandler == null && scope != null) { + for (PvmActivity activity : scope.getActivities()) { + if (((ActivityImpl) activity).getActivityBehavior() instanceof BoundaryEventActivityBehavior + && error.getErrorCode().equals(activity.getProperty("errorCode"))) { + errorEventHandler = activity; + break; + } + } + // search for generic error handler if no error handler with that error code has been found + if (errorEventHandler == null) { + for (PvmActivity activity : scope.getActivities()) { + if (((ActivityImpl) activity).getActivityBehavior() instanceof BoundaryEventActivityBehavior + && (activity.getProperty("errorCode") == null || "".equals(activity.getProperty("errorCode")))) { + errorEventHandler = activity; + break; + } + } + + } + // search for error handlers in parent scopes + if (errorEventHandler == null) { + if (scope instanceof PvmActivity) { + scope = ((PvmActivity) scope).getParent(); + } else { + scope = null; // stop search + } } } - // TODO search for error handlers in parent scopes - + + ErrorEndEventActivityBehavior errorEndEvent = new ErrorEndEventActivityBehavior(error.getErrorCode()); if (errorEventHandler != null) { - // continue execution - ErrorEndEventActivityBehavior errorEndEvent = new ErrorEndEventActivityBehavior(error.getErrorCode()); errorEndEvent.setBorderEventActivityId(errorEventHandler.getId()); - errorEndEvent.execute(execution); - // execution.executeActivity(errorEventHandler); - } else { - // throw error up - throw error; } + // continue execution + errorEndEvent.execute(execution); } } diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.java index 3c46db72e58da5ec2dafe215096da82c71adfc4b..122e305eefbc7f546519c49062c652d2f163faa1 100644 --- a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.java +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.java @@ -242,8 +242,50 @@ public class BoundaryErrorEventTest extends PluggableActivitiTestCase { @Deployment public void testCatchErrorThrownByJavaDelegateOnServiceTask() { String procId = runtimeService.startProcessInstanceByKey("catchErrorThrownByJavaDelegateOnServiceTask").getId(); - - // The service task will throw and error event, + assertThatErrorHasBeenCaught(procId); + } + + @Deployment + public void testCatchErrorThrownByJavaDelegateOnServiceTaskWithErrorCode() { + String procId = runtimeService.startProcessInstanceByKey("catchErrorThrownByJavaDelegateOnServiceTaskWithErrorCode").getId(); + assertThatErrorHasBeenCaught(procId); + } + + @Deployment + public void testCatchErrorThrownByJavaDelegateOnEmbeddedSubProcess() { + String procId = runtimeService.startProcessInstanceByKey("catchErrorThrownByJavaDelegateOnEmbeddedSubProcess").getId(); + assertThatErrorHasBeenCaught(procId); + } + + @Deployment + public void testCatchErrorThrownByJavaDelegateOnEmbeddedSubProcessInduction() { + String procId = runtimeService.startProcessInstanceByKey("catchErrorThrownByJavaDelegateOnEmbeddedSubProcessInduction").getId(); + assertThatErrorHasBeenCaught(procId); + } + + @Deployment(resources = { + "org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnCallActivity-parent.bpmn20.xml", + "org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnCallActivity-child.bpmn20.xml" + }) + public void testCatchErrorThrownByJavaDelegateOnCallActivity() { + String procId = runtimeService.startProcessInstanceByKey("catchErrorThrownByJavaDelegateOnCallActivity-parent").getId(); + assertThatErrorHasBeenCaught(procId); + } + + @Deployment(resources = { + "org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testUncaughtErrorThrownByJavaDelegateOnCallActivity-parent.bpmn20.xml", + "org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnCallActivity-child.bpmn20.xml" + }) + public void testUncaughtErrorThrownByJavaDelegateOnCallActivity() { + try { + runtimeService.startProcessInstanceByKey("uncaughtErrorThrownByJavaDelegateOnCallActivity-parent"); + } catch (ActivitiException e) { + assertTextPresent("No catching boundary event found for error with errorCode '23', neither in same process nor in parent process", e.getMessage()); + } + } + + private void assertThatErrorHasBeenCaught(String procId) { + // The service task will throw an error event, // which is caught on the service task boundary assertEquals("No tasks found in task list.", 1, taskService.createTaskQuery().count()); Task task = taskService.createTaskQuery().singleResult(); @@ -253,5 +295,5 @@ public class BoundaryErrorEventTest extends PluggableActivitiTestCase { taskService.complete(task.getId()); assertProcessEnded(procId); } - + } diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnCallActivity-child.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnCallActivity-child.bpmn20.xml new file mode 100644 index 0000000000000000000000000000000000000000..3cf9bdbaa11c01702b0029c010d984e01fb24a8f --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnCallActivity-child.bpmn20.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnCallActivity-parent.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnCallActivity-parent.bpmn20.xml new file mode 100644 index 0000000000000000000000000000000000000000..06fc3fbe8611f9c91d9b635012ad41cc4223fcc4 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnCallActivity-parent.bpmn20.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnEmbeddedSubProcess.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnEmbeddedSubProcess.bpmn20.xml new file mode 100644 index 0000000000000000000000000000000000000000..b9c71faf72027895bac6b874f7ebfa52f1d5bec8 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnEmbeddedSubProcess.bpmn20.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnEmbeddedSubProcessInduction.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnEmbeddedSubProcessInduction.bpmn20.xml new file mode 100644 index 0000000000000000000000000000000000000000..9aba693a750f1efe177236cb6f6264e802d6bb1a --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnEmbeddedSubProcessInduction.bpmn20.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnServiceTask.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnServiceTask.bpmn20.xml index b5f4aaa113d91ffe045f1974b0a26a6dab68bcee..58d306bb21f07701e17c53af7a3039a5125aa8df 100644 --- a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnServiceTask.bpmn20.xml +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnServiceTask.bpmn20.xml @@ -12,7 +12,7 @@ - + diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnServiceTaskWithErrorCode.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnServiceTaskWithErrorCode.bpmn20.xml new file mode 100644 index 0000000000000000000000000000000000000000..b67aeca61f1390ab819334ab75d7070a611b77a2 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testCatchErrorThrownByJavaDelegateOnServiceTaskWithErrorCode.bpmn20.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testUncaughtErrorThrownByJavaDelegateOnCallActivity-parent.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testUncaughtErrorThrownByJavaDelegateOnCallActivity-parent.bpmn20.xml new file mode 100644 index 0000000000000000000000000000000000000000..8329e3ff9d1fadf2e78635645dc9a96e1382e119 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/event/error/BoundaryErrorEventTest.testUncaughtErrorThrownByJavaDelegateOnCallActivity-parent.bpmn20.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file