6.10.3. Actions

Actions are executed during the entry and exit phases of a user task, during the execution of an automated task, or during the processing of a RunActionTimerHandler. This means that an action is typically executed in the context of a task, but that it may be executed in the context of a process, too, if used with a timer handler.

By means of the interface Action, you can only implement server-side actions, that is, actions that run completely within the Workflow Server. Actions are run on the server on behalf of the workflow user as configured in the file workflowserver.properties.

The main method of an action is execute(WorkflowObject), where the argument is either a task or a process depending on the context of the action. While executing, the action implementation should only read and write variables of the argument workflow object and its view. It is recommended that the exact variable names are made configurable by means of bean-style getters and setters.

The method isExecutable(WorkflowObject), should return false, when it is not currently possible to execute an action. Normally, you should always return true from this method, but there are cases where you might want to wait for a workflow variable to be set correctly before processing an action.

After execution, you may return a new instance of ActionResult in order to indicate success or failure. If you use the attributes successVariable and/or resultVariable in your XML workflow definition, the action result is automatically evaluated to set those variables. The action result can also take exceptions that are interpreted as warnings. If you include warnings in your result, they are added to the list that is returned from the method getWarnings() of the affected workflow object.

The method abort() should be implemented to let all running execute calls return early, possibly by throwing an ActionAbortedException. This method is called when the Workflow Server is shutting down. There is no need to implement special logic if the execute method always returns early. If execution takes some time, you should also consider implementing a long action instead.

The name returned by the method getName() of an action is used solely for logging and for parameterizing exceptions. It does not carry any semantic meaning, so that you may choose it as you like.

In order to simplify the development of an action, you may derive your class from the predefined classes AbstractAction or SimpleAction. Thereby, it is enough to implement a single method, namely execute(Process) in the former and doExecute(Process) in the latter case. Because the exact task in which the action is executed is not included in the signature of these methods, this approach requires that all relevant variables are defined at the process level. This is the typical use case. A detailed example of an action sending mail implemented as SimpleAction is given in Section 6.11.3, “Example Code of the Mail Action”.

The server may run an action more than once, in particular when a transaction has to be restarted due to concurrent activity. Therefore, you should design your actions in such a way that either the second execution detects that the action has already been executed or that a repeated execution is acceptable. For example, it is preferable to set a variable to a certain value rather than to increment an integer or to toggle a flag