What is a 'custom action'?

Actions are SCXML elements that "do" something. Actions can be used where "executable content" is permissible, for example, within <onentry>, <onexit> and <transition> elements.

The SCXML specification (currently a Working Draft) defines a set of "standard actions". These include <var>, <assign>, <log>, <send>, <cancel>, <if>, <elseif> and <else>.

The specification also allows implementations to define "custom actions" in addition to the standard actions. What such actions "do" is upto the author of these actions, and these are therefore called "custom" since they are tied to a specific implementation of the SCXML specification.

Custom actions with Commons SCXML

Commons SCXML makes authoring custom actions fairly straightforward.

What can be done via a custom action

A custom action in the Commons SCXML implementation has access to:

  • The current Context (and hence, the values of variables in the current Context).
  • Any other Context within the document, provided the id of the parent <state> is known.
  • The expression Evaluator for this document, and hence the ability to evaluate a given expression against the current or a identifiable Context.
  • The list of other actions in this Executable .
  • The "root" Context, to examine any variable values in the "document environment".
  • The EventDispatcher, to send or cancel events.
  • The ErrorReporter, to report any errors (that the ErrorReporter knows how to handle).
  • The histories, for any identifiable <history>.
  • The NotificationRegistry, to obtain the list of listeners attached to identifiable "observers".
  • The engine log, to log any information it needs to.

Walkthrough - Adding a 'hello world' custom action

Lets walk through the development of a simple, custom "hello world" action.

Idea

We need a <hello> action in our (fictitious) namespace "http://my.custom-actions.domain/CUSTOM". The action "tag" will have one attribute "name". The action simply logs a hello to the value of the name attribute when it executes.

A simple example is here .

Custom action implementation

A custom action must extend the Commons SCXML Action abstract base class.

Here is the Java source for our custom Hello action. The execute() method contains the logging statement.

Using a custom SCXML digester

With the custom action(s) implemented, the document may be parsed using a custom SCXML digester that is aware of these actions like so:

      // (1) Create a list of custom actions, add as many as are needed
      List customActions = new ArrayList();
      CustomAction ca =
            new CustomAction("http://my.custom-actions.domain/CUSTOM",
                             "hello", Hello.class);
      customActions.add(ca);

      // (2) Parse the SCXML document containing the custom action(s)
      SCXML scxml = null;
      try {
          scxml = SCXMLDigester.digest(url, errorHandler, customActions);
          // Also see other methods in SCXMLDigester API
          // "url" points to SCXML document
          // "errorHandler" is SAX ErrorHandler
      } catch (Exception e) {
          // bad document, take necessary action
      }
    

This approach can only be used if the custom rule has no body content (child "tags") or if the custom action implements the ExternalContent interface, in which case, any body content gets read into a list of DOM nodes. For any other requirements, the digester rules can be added by directly by obtaining a Digester instance with the "default" SCXML rules using the newInstance() methods and further directly adding the necessary rules using the digester API .

Read in the 'custom' SCXML document

For documents without custom actions, the utility methods of the SCXMLDigester should be used. That section is here.

Launching the engine

Having obtained the SCXML object beyond step (2) above, proceed as usual, see the section on the Commons SCXML engine for details.