5 Creating an Application

Creating an application is as simple as defining an ECharts Machine encapsulating the desired logic and configuring an appropriate deployment descriptor. Each step is explained below. In Section  7 we describe a tool called appgen that assists with these steps. In Section  8 we describe a sample application that is included with the ECharts for SIP Servlets development kit.

5.1 Defining the Machine

Machines are created in .ech files as described in the ECharts Manual [2]. A typical machine declaration is:



package examples;

// machine that rejects all calls with "486 Busy Here"
public machine BusyFSM {
    ...
}

The machine will contain one or more constructors, state declarations, state transition rules, and any supporting Java code required to support the desired logic.

5.1.1 Creating Ports

The machine logic is required to create any ports required for the application (except for the BoxPort, which is automatically supplied to each box). The machine constructor provides a convenient place to create the required ports, as shown here:



package examples;

// machine that rejects all calls with "486 Busy Here"
public machine BusyFSM {
    <* SipPort caller; *>

    // top-level machines are called with this constructor
    public BusyFSM(FeatureBox box,
                       Properties servletProps,
                       ServletContext context) {
        this.caller = box.createSipPort("caller");
    }
    ...
}

5.1.2 Machine Constructors

A machine may have multiple constructors. This can promote reuse of the machine by allowing it to be easily invoked in more than one context. One typical use of multiple constructors is to allow a machine to be invoked directly both by the EChartsSipServlet (thus making it a top-level machine) or by another machine (thus making it a nested machine). A significant difference between the two contexts is that top-level machines generally create the ports they need, while nested machines may have ports passed in as parameters.

The example below shows multiple constructors, and adds the application logic as well:



package examples;

import java.util.Properties;
import javax.servlet.ServletContext;
import org.echarts.servlet.sip.*;
import org.echarts.servlet.sip.messages.*;

// machine that rejects all calls with "486 Busy Here"
public machine BusyFSM {
    <*
        FeatureBox box;
        SipPort caller;
        BoxPort boxPort;
    *>

    // top-level machines are called with this constructor
    public BusyFSM(FeatureBox box,
                       Properties servletProps,
                       ServletContext context) {
        this.box    = box;
        this.caller = box.createSipPort("caller");
        boxPort = box.getBoxPort();
    }

    // allow caller port to be passed in by another machine
    public BusyFSM(FeatureBox box, SipPort caller) {
        this.caller = caller;
        boxPort = box.getBoxPort();
    }

    initial state INIT;

    transition INIT - boxPort ? Invite / {
        caller.bind(message);
        caller ! caller.createResponse(486);
    } -> REJECTED;

    state REJECTED;

}

For such a simple application, there is no advantage to using the ECharts framework. Once the feature logic gets more complex, and the library of well-designed and debugged machines grows, the advantages become clearer.

5.2 Creating the Deployment Descriptor

In order to deploy an application, an appropriate deployment descriptor must be crafted. The servlet to invoke is always EChartsSipServlet; the Machine to invoke is specified by the machineClassName initialization parameter to the servlet. A special listener is required if any machines implement timed transitions.

Here is a sample sip.xml file for an E4SS application.



<?xml version="1.0" encoding="UTF-8"?>
<sip-app xmlns="http://www.jcp.org/xml/ns/sipservlet"
    xmlns:javaee="http://java.sun.com/xml/ns/javaee">

<app-name>busyapp</app-name>

<servlet>
<javaee:servlet-name>busyapp</javaee:servlet-name>
<javaee:servlet-class>
            org.echarts.servlet.sip.EChartsSipServlet
        </javaee:servlet-class>
        <javaee:init-param>
            <javaee:param-name>machineClassName</javaee:param-name>
            <javaee:param-value>examples.BusyFSM</javaee:param-value>
        </javaee:init-param>
        <!-- any other init-params are passed to machine
             as servletProps -->
        <javaee:load-on-startup>1</javaee:load-on-startup>
</servlet>

    <servlet-selection>
<servlet-mapping>
  <servlet-name>noAnswerTimeout</servlet-name>
  <pattern>
<equal>
  <var>request.method</var>
  <value>INVITE</value>
</equal>
  </pattern>
</servlet-mapping>
    </servlet-selection>

<session-config>
<javaee:session-timeout>0</javaee:session-timeout>
</session-config>

<listener>
<javaee:listener-class>
            org.echarts.servlet.sip.TransitionTimerManager
        </javaee:listener-class>
</listener>
<listener>
<javaee:listener-class>
            org.echarts.servlet.sip.EChartsSipServlet
        </javaee:listener-class>
</listener>
    <javaee:display-name>Busy Application</javaee:display-name>
</sip-app>