diff --git a/SpiffWorkflow/bpmn/specs/EndEvent.py b/SpiffWorkflow/bpmn/specs/EndEvent.py index fb4df115c..0ae347a0c 100644 --- a/SpiffWorkflow/bpmn/specs/EndEvent.py +++ b/SpiffWorkflow/bpmn/specs/EndEvent.py @@ -18,10 +18,11 @@ # 02110-1301 USA from .BpmnSpecMixin import BpmnSpecMixin +from ...specs.Simple import Simple from ...task import Task -class EndEvent(BpmnSpecMixin): +class EndEvent(Simple, BpmnSpecMixin): """ Task Spec for a bpmn:endEvent node. diff --git a/SpiffWorkflow/bpmn/specs/ScriptTask.py b/SpiffWorkflow/bpmn/specs/ScriptTask.py index a629b2854..724f3a607 100644 --- a/SpiffWorkflow/bpmn/specs/ScriptTask.py +++ b/SpiffWorkflow/bpmn/specs/ScriptTask.py @@ -16,9 +16,14 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA +import logging from .BpmnSpecMixin import BpmnSpecMixin +from ...task import Task from ...specs.Simple import Simple +from ...exceptions import WorkflowTaskExecException + +LOG = logging.getLogger(__name__) class ScriptTask(Simple, BpmnSpecMixin): @@ -40,5 +45,13 @@ def _on_complete_hook(self, task): if task.workflow._is_busy_with_restore(): return assert not task.workflow.read_only - task.workflow.script_engine.execute(task, self.script) + try: + task.workflow.script_engine.execute(task, self.script) + except Exception: + LOG.error('Error executing ScriptTask; task=%r', task, exc_info=True) + # set state to WAITING (because it is definitely not COMPLETED) + # and raise WorkflowException pointing to this task because + # maybe upstream someone will be able to handle this situation + task._setstate(Task.WAITING, force=True) + raise WorkflowTaskExecException(task, 'Error during script execution') super(ScriptTask, self)._on_complete_hook(task) diff --git a/SpiffWorkflow/exceptions.py b/SpiffWorkflow/exceptions.py index 65a9bd6c0..11901971b 100644 --- a/SpiffWorkflow/exceptions.py +++ b/SpiffWorkflow/exceptions.py @@ -28,13 +28,34 @@ def __init__(self, sender, error): """ Standard exception class. - :param sender: the task that threw the exception. - :type sender: Task + :param sender: the task spec that threw the exception + :type sender: TaskSpec :param error: a human readable error message :type error: string """ Exception.__init__(self, '%s: %s' % (sender.name, error)) - self.sender = sender # Points to the Task that generated the exception. + self.sender = sender # Points to the TaskSpec that generated the exception. + + +class WorkflowTaskExecException(WorkflowException): + """ + Exception during execution of task "payload". For example: + + * ScriptTask during execution of embedded script, + * ServiceTask during external service call. + """ + + def __init__(self, task, error): + """ + Exception initialization. + + :param sender: the task that threw the exception + :type sender: Task + :param error: a human readable error message + :type error: string + """ + WorkflowException.__init__(self, task.task_spec, error) + self.task = task class StorageException(Exception):