A brief tutorial on SCXML Templating

SCXML allows for reusability of a certain FSM externally. This is helpful when a certain sequence of states, events and actions occur frequently. Instead of repeating the sequence multiple times, an FSM can be designed seperately which can be referred as a state body using src attribute of a state.

Use Case

In a typical call control application, the sequence to connect to an end-point would be something like

  • waiting-for-connection [connection.alerting/conection.accept()] --> accepting-connection

  • accepting-connection [connection.connected] --> connection-connected

This sequence is a completely reusable one and can be templated

Example based on the use case above

<scxml
  xmlns="http://www.w3.org/2005/07/SCXML"
  version="1.0" 
  xmlns:ccxml="http://stack.mera.com/CCXML"
  initialstate="wait-for-connection-request">

  <state id="wait-for-connection-request">
    <transition event="connection.alerting" target="wait-for-connection-connected"/>
  </state>
  <state id="wait-for-connection-connected">
    <onentry>
      <ccxml:accept callid="incoming-line"/>
    </onentry>
    <transition 
        event="connection.connected"
        cond="_eventdata.ID eq 'incoming-line'">
      <send event="connection.connected"/>
    </transition>
  </state>
</scxml>

SCXML Using the template above

<scxml
  xmlns="http://www.w3.org/2005/07/SCXML"
  version="1.0" 
  xmlns:ccxml="http://stack.mera.com/CCXML"
  initialstate="wait-for-connection-request">

  <state id="wait-for-connection-request" src="accept-connection.scxml?call-id=incoming-line">
    <transition event="connection.connected" target="send-dtmf"/>
  </state>
  <state id="send-dtmf">
    <onentry>
      <ccxml:send-dtmf digits="'1234'"/>
    </onentry>
    <transition event="dtmf.sent" target="bye"/>
  </state>

  <state id="bye" src="send-bye.scxml" final="true"/>
</scxml>

_Note: not conforming to Working Draft -
As I understand the current Working Draft, a state element with a source attribute must not have children. See section 3.2.1. On the other hand, the implementation Commons SCXML v0.6 does accept both the src attribute and children for a state element at the same time. See issues.apache.org/jira/browse/SCXML-37

  • Wolfgang Frech_

Explanation

The example above is fairly elaborate and simple. As we can see, the otherwise complicated State Engine has been broken into three seperate FSMs, send-bye.scxml and accept-connection.scxml being fairly reusable.

Posting to external JSPs

In the example above, we used an SCXML doc to post the content to, we could also have used a JSP/Velocity Template which is able to return an SCXML doc. Using a JSP/Velocity template we can make the SCXML dynamic. Going back to the example above, the accept-connection.scxml accepts the connection in the incoming-line variable, to use a different value we could have used a JSP like in the example below

<state id="foo${param.id}">
 <!-- some content -->
</state>

placed at URL http://foo.bar/baz.jsp , then
src="http://foo.bar/baz.jsp?id=1" will get us:

<state id="foo1">
 <!-- some content -->
</state>

A word of caution

  • When the src attribute is used, it is highly recommended to use a path-resolver (Provide Link). This is done while creating the SCXML
SCXMLDigester.newInstance(SCXML, PathResolver);

API If the PathResolver is not used (By passing a null), then the src is taken as the path of the file.

  • In many cases, it might be required to re-use the same template in the same "master" scxml. i.e. In our example above, after the send-bye, it might be required to reconnect to the incoming-line. This will lead to the same states being duplicated and the SCXML Engine to be indeterminate. This can be avoided by using a param=value after the URL, this mangles the url and avoids duplicate IDs

Contributed By: Fasihullah Askiri

  • No labels