Interface IWorkflowExecutor


  • public interface IWorkflowExecutor
    Handler for affecting how the workflow is executed. Contains method to run other nodes during the execution of a task, methods for triggering other events, and methods for special flow control operations such as looping and exception stack handling.
    Since:
    7.0.0
    Author:
    XIMA MEDIA GmbH
    • Method Detail

      • attemptToExecute

        IWorkflowNodeResult attemptToExecute​(WorkflowNode node)
        For advanced usage only. Similar to execute, see their for more details. This method wraps the outcome in a result wrapper, never throwing when the node completes abruptly.

        Usually you should use execute, this method is intended for advanced use cases when you need to handle different completion types, such as needed by try-catch-finally statements.

        Parameters:
        node - The node to execute.
        Returns:
        A wrapped result with either the normal or abrupt completion result from the execute method.
        Throws:
        ExecutionAbortedError - When the execution of the task was aborted, such as when certain limits were exceeded. Usually you should not catch this exception and allow it to propagate upwards.
        Since:
        8.1.0
        See Also:
        execute(WorkflowNode)
      • attemptToExecuteChild

        IWorkflowNodeResult attemptToExecuteChild​(WorkflowNode parentNode,
                                                  int childIndex)
        For advanced usage only. Similar to executeChild, see their for more details. This method wraps the outcome in a result wrapper, never throwing when the node completes abruptly.

        Usually you should use executeChild, this method is intended for advanced use cases when you need to handle different completion types, such as needed by try-catch-finally statements.

        Parameters:
        parentNode - A node with one or more children.
        childIndex - 0-based index of the child to execute
        Returns:
        A wrapped result with either the normal or abrupt completion result from the execute method.
        Throws:
        ExecutionAbortedError - When the execution of the task was aborted, such as when certain limits were exceeded. Usually you should not catch this exception and allow it to propagate upwards.
        Since:
        8.1.0
        See Also:
        executeChild(WorkflowNode, int)
      • execute

        @Nullable
        INormalCompletionResult execute​(WorkflowNode node)
                                 throws AbstractAbruptCompletionException
        Executes the given node. This should be used by workflow nodes that contain children, such as selection nodes (if-else, switch etc), iteration nodes (for-each-loop, while-loop, etc.), or error handler nodes (try-catch block etc.).

        Loops are allowed in general - but execution may be terminated when a certain limit (instruction count or time-based) is reached.

        Please note that you should usually NOT catch ExecutionAbortedError unless you have a very special reason to do so. Subclasses of AbstractAbruptCompletionException should also not be caught usually, but certain subclasses may be caught by control flow nodes.

        For example, an error handling node like a try-catch block might catch NodeThrewException and delegate control to the error handler. Iteration nodes such as a while-loop block might catch NodeTransferredControlException of type break or continue and adjust the loop execution accordingly. Simple action nodes, or selection nodes such as an if-else or switch block, should not catch any errors and simply allow any exceptions thrown by child nodes to propagate upwards.

        Parameters:
        node - The node to execute.
        Returns:
        The result returned by the given node. In case the execution of the node was skipped (such as because the node is not active), null is returned.
        Throws:
        AbstractAbruptCompletionException - When the node's execution did not finish normally, see below for subclasses.
        NodeThrewException - If this exception was thrown by the execute method of the given node. Indicates that a node could not be completed successfully. This exception can be caught by control flow nodes with custom error handling, such as a try-catch node.
        NodeReturnedException - If this exception was thrown by the execute method of the given node. Indicates that the node wishes to return, i.e. to stop the execution of the current processing chain (="function"). This exception can be caught by control flow nodes with custom finalization handling, such as a try-finally node (which should rethrow this exception afterwards).
        NodeTransferredControlException - If this exception was thrown by the execute method of the given node. Indicates that a control transfer should take place. The matching node for the control transfer target should catch this exception and proceed according to the type of the control transfer.
        ExecutionAbortedError - When the execution of the task was aborted, such as when certain limits were exceeded. Usually you should not catch this exception and allow it to propagate upwards.
        RuntimeException - A runtime exception may be thrown to indicate an unforeseen error, such as general database errors. For all errors you expect to happen, you should throw an appropriate NodeThrewException with the details of the exception. When a runtime exception is thrown, it is wrapped in a NodeThrewException and treated as if that exception had been thrown.
        See Also:
        executeChild(WorkflowNode, int)
      • executeChild

        @Nullable
        INormalCompletionResult executeChild​(WorkflowNode parentNode,
                                             int childIndex)
                                      throws AbstractAbruptCompletionException
        Executes the given child of the node. This should be used by workflow nodes that contain children, such as selection nodes (if-else, switch etc), iteration nodes (for-each-loop, while-loop etc), or error handler nodes (try-catch block etc.).

        Loops are allowed in general - but execution may be terminated when a certain limit (instruction count or time-based) is reached.

        Please note that you should usually NOT catch ExecutionAbortedError unless you have a very special reason to do so. Subclasses of AbstractAbruptCompletionException should also not be caught usually, but certain subclasses may be caught by control flow nodes.

        For example, an error handling node like a try-catch block might catch NodeThrewException and delegate control to the error handler. Iteration nodes such as a while-loop block might catch NodeTransferredControlException of type break or continue and adjust the loop execution accordingly. Simple action nodes, or selection nodes such as an if-else or switch block, should not catch any errors and simply allow any exceptions thrown by child nodes to propagate upwards.

        Parameters:
        parentNode - A node with one or more children.
        childIndex - 0-based index of the child to execute
        Returns:
        The result returned by the given node. In case the execution of the node was skipped (such as because the node is not active), null is returned.
        Throws:
        AbstractAbruptCompletionException - When the node's execution did not finish normally, see below for subclasses.
        NodeThrewException - If this exception was thrown by the execute method of the given node. Indicates that a node could not be completed successfully. This exception can be caught by control flow nodes with custom error handling, such as a try-catch node.
        NodeReturnedException - If this exception was thrown by the execute method of the given node. Indicates that the node wishes to return, i.e. to stop the execution of the current processing chain (="function"). This exception can be caught by control flow nodes with custom finalization handling, such as a try-finally node (which should rethrow this exception afterwards).
        NodeTransferredControlException - If this exception was thrown by the execute method of the given node. Indicates that a control transfer should take place. The matching node for the control transfer target should catch this exception and proceed according to the type of the control transfer.
        ExecutionAbortedError - When the execution of the task was aborted, such as when certain limits were exceeded. Usually you should not catch this exception and allow it to propagate upwards.
        See Also:
        execute(WorkflowNode)
      • executeLoopBody

        boolean executeLoopBody​(WorkflowNode parentNode,
                                int childIndex)
                         throws AbstractAbruptCompletionException
        Executes the given child of the given node. This is a convenience method intended only for iteration nodes that wish to execute the child representing the loop body. If you need more control, use execute or executeChild directly and handle the NodeTransferredControlException exception accordingly.

        This method handles NodeTransferredControlException of type break and continue by checking whether the loop node is a valid target. If so, this method returns true if the node completed normally or abruptly by issuing a continue statement; and false if then node completed abruptly by issuing a break statement. Otherwise the exception is propagated upwards.

        Parameters:
        parentNode - The loop node with a loop body.
        childIndex - Index of the node representing the loop body.
        Returns:
        true if the loop body completed normally or abruptly by issuing a continue statement, and false otherwise.
        Throws:
        AbstractAbruptCompletionException - When the node's execution did not finish normally, other than by issuing a break or continue statement that targets the given parent node.
        ExecutionAbortedError - When the execution of the task was aborted, such as when certain limits were exceeded. Usually you should not catch this exception and allow it to propagate upwards.
      • isValidControlTransferTarget

        boolean isValidControlTransferTarget​(WorkflowNode node,
                                             IControlTransferringCompletionResult controlTransfer)
        Whether the node is a valid target for the given control transfer, i.e. whether it matches the target and supports the transfer type.
        Parameters:
        node - Node to check against the control transfer.
        controlTransfer - Control transfer to check against the current node.
        Returns:
        true if the given node is a valid target for the given control transfer, false otherwise.
      • isValidControlTransferTarget

        boolean isValidControlTransferTarget​(WorkflowNode node,
                                             IControlTransferringCompletionResult controlTransfer,
                                             String... types)
        Whether the node is a valid target for the given control transfer, i.e. whether it matches the target and supports both the transfer type as well as one of the given types.
        Parameters:
        node - Node to check against the control transfer.
        controlTransfer - Control transfer to check against the current node.
        types - Types to which to limit the check.
        Returns:
        true if the given node is a valid target for the given control transfer, false otherwise.
      • loopEnd

        void loopEnd​(WorkflowNode node)
        Ends a loop started by loopStart(). Each call to loopStart() must be followed with a call to loopEnd. loopNext() must be called in between.

        The intended flow for executing a loop is as follows:

        1. Call loopStart() to initialize the loop
        2. Repeat for each loop iteration
          • Optionally, set additionally data accessible during the execution of the loop node via params.currentValue(). Data provided via currentValue().withBuilder(...) can be accessed by other other nodes in the workflow designer via placeholders, such as the current index or the current iteration value. Data provided via provideExecutionData() can be accessed internally e.g. by placeholder replacer plugins.
          • Execute the child workflow node which should be run for the loop iteration.
          • Call loopNext() before the next loop iteration to increment the index.
        3. Always call loopEnd() once the loop is done. Usually this should be done inside a finally {} block.
        Parameters:
        node - The node which controls the loop, e.g. a while-loop node or a for-of-loop node.
        Throws:
        IllegalStateException - When no loop is active, e.g. loopEnd() was already called at least as often as loopStart() was called.
        Since:
        8.1.0
      • loopNext

        void loopNext​(WorkflowNode node)
        Moves to the next iteration of a loop started with loopStart(). Must be called after a loop iteration is done, before the next one starts to increment the index.

        The intended flow for executing a loop is as follows:

        1. Call loopStart() to initialize the loop
        2. Repeat for each loop iteration
          • Optionally, set additionally data accessible during the execution of the loop node via params.currentValue(). Data provided via currentValue().withBuilder(...) can be accessed by other other nodes in the workflow designer via placeholders, such as the current index or the current iteration value. Data provided via provideExecutionData() can be accessed internally e.g. by placeholder replacer plugins.
          • Execute the child workflow node which should be run for the loop iteration.
          • Call loopNext() before the next loop iteration to increment the index.
        3. Always call loopEnd() once the loop is done. Usually this should be done inside a finally {} block.
        Parameters:
        node - The node which controls the loop, e.g. a while-loop node or a for-of-loop node.
        Throws:
        IllegalStateException - When no loop is active, e.g. loopEnd() was already called at least as often as loopStart() was called.
        Since:
        8.1.0
      • loopStart

        void loopStart​(WorkflowNode node)
        Begins a new loop. Should be called by control flow nodes such as while or for-of loops before executing the loop children. loopEnd() must be called once the loop body is done, and loopNext() must be called in between.

        The intended flow for executing a loop is as follows:

        1. Call loopStart() to initialize the loop
        2. Repeat for each loop iteration
          • Optionally, set additionally data accessible during the execution of the loop node via params.currentValue(). Data provided via currentValue().withBuilder(...) can be accessed by other other nodes in the workflow designer via placeholders, such as the current index or the current iteration value. Data provided via provideExecutionData() can be accessed internally e.g. by placeholder replacer plugins.
          • Execute the child workflow node which should be run for the loop iteration.
          • Call loopNext() before the next loop iteration to increment the index.
        3. Always call loopEnd() once the loop is done. Usually this should be done inside a finally {} block.
        Parameters:
        node - The node which controls the loop, e.g. a while-loop node or a for-of-loop node.
        Throws:
        IllegalStateException - When loopStart() was previously called and not yet followed-up by a call to loopNext() or loopEnd().
        Since:
        8.1.0
      • popException

        void popException()
        Pops the exception on top of the exception stack, see IWorkflowVariableHandler.getException(int). This method should only be used by workflow nodes that represent a try-catch block.
        Since:
        8.1.0
      • provideExecutionData

        default void provideExecutionData​(WorkflowNode node,
                                          INodeExecutionData data)
        Sets additional data available while the node is executed , which can be accessed via getExecutionDataForNode(node). When called with a node that is currently not being executed, this is a no-op.

        You can set multiple data objects for the same node. Each call to this method clears the existing data and sets the data to a singleton set. Execution data is cleared when a node finishes execution.

        Parameters:
        node - Node for which to set the data.
        data - Data associated with the node's execution.
        Since:
        8.2.0
      • provideExecutionData

        void provideExecutionData​(WorkflowNode node,
                                  Iterable<? extends INodeExecutionData> data)
        Sets additional data available while the node is executed , which can be accessed via getExecutionDataForNode(node). When called with a node that is currently not being executed, this is a no-op.

        You can set multiple data objects for the same node. Each call to this method clears the existing data and sets the data to the given set. Execution data is cleared when a node finishes execution.

        Parameters:
        node - Node for which to set the data.
        data - Data associated with the node's execution.
        Since:
        8.2.0
      • pushException

        void pushException​(NodeThrewException exception)
        Pushes the given exception to the exception stack, see IWorkflowVariableHandler.getException(int). This method should only be used by workflow nodes that represent a try-catch block.
        Parameters:
        exception - Exception to push to the stack.
        Since:
        8.1.0
      • triggerEvent

        List<IWorkflowQueueItem> triggerEvent​(IWorkflowEventData event,
                                              EWorkflowEventLoopTiming timing)
                                       throws WorkflowEventRunnerException
        Triggers the given event. This method returns immediately, the tasks are run either after the current task is done, or after all tasks are done, depending on the given timing value.

        The given event should either IFormRecordProvidingEvent or otherwise make sure it applies only to the current form record that is being processed.

        The given events are assumed to have occurred simultaneously. Therefore, when a multiple triggers of a task react to the given events, the task is run only once.

        Parameters:
        event - Events that has occurred.
        timing - Whether the events should be processed immediately, or later.
        Returns:
        A list of all workflow tasks that were added to the event queue.
        Throws:
        WorkflowEventRunnerException - When the event could not be added to the queue, such as due to a database failure when trying to find matching tasks etc. Also thrown when the event applies to a form record different from the one currently being processed.