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>