This guide tells you how you can create new features and services using the SipExchange external call control framework. To understand this section fully, please make sure that you have read the following topics first:
- SipExchange Overview
- SipExchange Basics
- System Administration Howto
- SipExchange Architecture
- External Call Control
You will also need the javadocs for the SipExchange external call control API.
Table of Contents
- Conventions followed in this document
- Example service
- Service code development
- Setting up the development environment
- Packaging the service
- Deploying the service
- Developing user interface portlets
- We have used the term “directory” to specify a file location. This is a common Unix convention. In the Windows environment, the term “folder” is used to mean the same thing.
- We have used the Unix directory naming convention in this document. In the Unix environment, a directory hierarchy is specified by the “/” separator. In the Windows environment, the “\” separator is used. In addition, Unix systems do not use drive letters as in Windows. If you are using Windows, you will need to modify the commands accordingly. For example, if we stated $JIPLET_HOME/bin and you are using Windows, it may translate to C:\jiplet-standalone\bin.
- We have used $SIPEXCHANGE_HOME or similar names to specify variables. While installing/configuring, you will need to replace these variables with the actual value. For example, in this document, the variable $SIPEXCHANGE_HOME has been used to specify the directory where the SipExchange code binary is unpackaged. We have commonly used the following variables:
- $JAVA_HOME – directory where the Java Runtime Environment (JRE) is installed.
- $SIPEXCHANGE_HOME – directory where the SipExchange software is unpacked.
- $JBOSS_HOME – directory where JBOSS is installed.
- $HOST – host name/IP address of the system where the jiplet container is installed.
- $RUN – the JBOSS run mode (default, minimal, all, etc.)
- Commands are specified using bold. You need to enter the command by typing/pasting the command and pressing the Enter/Return key. Although in the Unix world this may seem natural, in the Windows environment, lots of users are lost when it comes to entering a command. Also, the prompts “#” or “C:\>” are shown, do not enter them.
To create a new feature or a service, you will have to create a Service Control Point (SCP) and configure triggers in the SipExchange system. Once triggers are configured, at specified point(s) of a call, SipExchange invokes a service call to the SCP. When the SCP service is invoked, the feature logic that you have created must be able to respond appropriately to the invocation.
To create a service, you need to be a proficient Java programmer with a good understanding of the Jboss Remoting API for the underlying infrastructure. As explained in the External Call Control section, SipExchange uses the JBoss Remoting API for communication between SipExchange and SCP. You can get more information and documentation about that API from here.
This section will demonstrate the use of the remoting API and how to use the API to develop a feature or a service. If you want to see the source code, download the source distribution of SipExchange and unpack the distribution. The source code for SipExchange is located in the “controller/src” directory and the Java class is org.cafesip.sipexchange.inservice.server.ExampleInServiceHandler.
The example service is a simple service that demonstrates many of the external call control features of the SipExchange server. You can create triggers for subscribers and domains with the “feature” and the “parameter” fields set in a predefined way as explained below. When a trigger is encountered, the SipExchange server invokes the SCP service. Based on the feature and parameter field settings, the SCP sends an appropriate response as explained below.
Here are the rules for how you set the feature and the parameter fields while creating a trigger.
When creating a subscriber trigger, you can set the “feature” field to any unique name. The “parameter” field is set as per the format – “action=something” where action is the name of the action and something is an action parameter. This is described in more details as follows:
- If you want the SCP to send a continue response, set the parameter field as “continue=something”.
- If you want the SCP to send a terminate response, set the parameter field as “disconnect=$reason”. Replace the $reason with a real reason phrase like – “you have not paid your bills”.
- If you want the SCP to send a redirect response, set the parameter field as “reroute=$sipaddress”. Replace the $sipaddress with a SIP address. Example: sip:email@example.com.
- If you want the SCP to send a forward response, set the parameter field as “forward=$sipaddresses”. Replace the $sipaddresses with one or more SIP address separate by a semi-colon (;) delimiter. Example: sip:firstname.lastname@example.org;sip:email@example.com.
When creating a domain trigger, you must set the feature name to any unique name. The parameter field is set as per the format - “pattern=$somepattern¶m=$someparam“. As explained in the External Call Control section, the $somepattern must be a regular expression against which the SipExchange server matches the called address. The $someparam uses the same syntax as described for the subscriber trigger above. An example of how a domain trigger parameter can be set is:
In the above case, a call to sip:operator@somedomain (where somedomain is the name of the domain for which you assigned the trigger), is routed to the SCP which directs the SipExchange server to forward the call to sip:firstname.lastname@example.org and sip:email@example.com. Note that we have used a plain string, not a regular expressions, in the pattern field but you can use regular expressions if you want to.
This example service is packaged with the SipExchange distribution and is installed as a part of SipExchange. To use this service, while adding a trigger, populate the “Service Controller” field with the URL socket://$HOSTNAME:6666 where $HOSTNAME is the host name or IP address of the server running SipExchange.
You can view the source code for the example service here.
Each feature that you create will be in the form of an SCP service. An SCP service can handle more than one feature if you think you want to do it that way. Creating a service involves creating a Java class that implements the interface org.jboss.remoting.ServerInvocationHandler as shown below.
public class InServiceHandler implements ServerInvocationHandler
The main method that you have to implement is the invoke() method as shown below:
* @see org.jboss.remoting.ServerInvocationHandler#invoke(org.jboss.remoting.InvocationRequest
public Object invoke(InvocationRequest req) throws Throwable
TriggerInfo t = (TriggerInfo) req.getParameter();
System.out.println(“Received an invoke from a client\n”
The Jboss service calls this method when the SipExchange server invokes the service and this is where you have to add your feature logic. The parameter to this method is used to pass the trigger information as shown in the first line of the method. For more details, read the javadocs for the TriggerInfo class. Note that TriggerInfo is the base class for call the Trigger classes. The actual trigger class that is passed as a parameter is one of the following:
- org.cafesip.sipexchange.inservice.shared.CalledAddressTermTrigger : for CalledAddress trigger
- org.cafesip.sipexchange.inservice.shared.CalledBusyTermTrigger : for CalledBusy trigger
- org.cafesip.sipexchange.inservice.shared.CalledNoAnswerTermTrigger : for CalledNoAnswer trigger
- org.cafesip.sipexchange.inservice.shared.CalledNotAvailableTermTrigger : for CalledNotAvailable trigger
- org.cafesip.sipexchange.inservice.shared.MakeCallOrigTrigger : for MakeCall trigger
- org.cafesip.sipexchange.inservice.shared.ReceivedCallTerTrigger : for ReceivedCall trigger
See the javadocs for the above classes for details. If you have written a service that can receive multiple types of trigger in the same invoke() method, you can determine the trigger type by using the instanceof operator. For example:
if (t instanceof org.cafesip.sipexchange.inservice.shared.ReceivedCallTermTrigger)
// logic for handling the ReceivedCall trigger
else if (t instanceof org.cafesip.sipexchange.inservice.shared.MakeCallOrigTrigger)
// logic for handling the MakeCall trigger
The method returns an object which is received by the SipExchange server. The returned object must be of the type that the SipExchange server recognizes. They can be one of the following:
Read the javadocs for these classes for details on what parameters can be set on these classes. The following code segment demonstrates how a response is populated (continuing with the example service introduced previously) and returned:
if (action.equals(“forward”) == true)
RerouteResponse r = new RerouteResponse();
StringTokenizer addresses = new StringTokenizer(aparam, “;”);
int count = addresses.countTokens();
String addr = new String[count];
for (int i = 0; i < count; i++)
String address = addresses.nextToken();
addr[i] = address;
System.out.println(“Sending a forward response with address “
To set up the development environment, you will need the SipExchange binary distribution that you may have already downloaded and installed. Follow the steps outlined below:
- Add all the jar files in the top-level directory and in the lib/remoting directory into your CLASSPATH environment.
- Create a source directory and the Java source package that you want your class to be under. Example: org.cafesip.sipexchange.inservice.server .
- Create a Java class and the feature service as outlined in the above section.
- Compile the Java classes that you may have created using a Java compiler.
- Package the classes and libraries as explained below.
- Deploy the service as explained below.
The way you want to package your service depends on whether you want to run the service as a standalone Java application or whether you want to run the service inside Jboss. One important thing to note is that the service that you created does not have to be located in the same server where the SipExchange application is running. If you decide to run the service that you created on the same system, we recommend that you package your service as a Jboss service. If you are running the service in a different system, and you do not have Jboss J2EE server installed on the system or the system does not meet the requirements for installing a Jboss server, it may be easier to package the software as a standalone application.
To package your service as a standalone application, you may have to create the Main class as well as other classes that Jboss requires for you to setup the remoting service. Please refer to the Jboss web site for detailed documentation. You may also need shell scripts to start and stop the service as well as install the service as a Windows or Linux service.
To package your service as a JBOSS service, you can create a service archive (SAR).
You will need to have a directory structure as shown in the above diagram. The top-level directory, shown as “sipex-inservice”, above, must have the following:
- A sub-directory called META-INF
- All the jar files that are required by the service. In the above diagram, the JBOSS remoting API jar files are shown.
- The classes following the package directory structure if you decide to use classes instead of jars. The “org” directory contains the classes.
The META-INF directory contains the deployment descriptors.
- jboss-service.xml contains the service descriptor. Here is a sample jboss-service.xml. Look for the XML element<handler subsystem=”sipexchange”>org.cafesip.sipexchange.inservice.server.InServiceHandler</handler>and replace the class name with the fully-qualified name of the service class you created. For modifying further, read the documentation provided in the comments.
- A sample connector.xml is shown here. You may need to modify this page if you want to provide additional protocol support.
You can create the package using an Ant script. Once the directory structure is laid out as shown above and all the files are in place, using the jar utility, you can package all the directories and files under the sipex-inservice directory into a service archive (SAR). The following ant code segment shows you an example of packaging that we have used:
Once you have packaged your service as described above, you need to deploy the service.
For a standalone application, simply run the application or deploy it as a Linux or Windows service by running the shell script that you have created.
For deploying as a Jboss service, copy the sar file you created to the $JBOSS_HOME/server/$RUN/deploy directory.
Configure the triggers from the SipExchange console.
Now the SipExchange server is ready to access the service.
Now that you have developed your own service at the top of SipExchange, you may be wondering how to add user interface elements that will enable system administrators to administer the feature and subscribers to tune the features similar to how SipExchange provides the user interface for the built-in features. Starting with SipExchange 1.0.0b, we have moved to a portlet architecture for developing and deploying the user interface. As mentioned before, the SipExchange user interface is developed on the top of the Jboss portal. One of the reasons for moving into the portal architecture is to enable third-party user interface tools to be plugged in to the portal.
In order to add your own user interface for administering the services you have developed or to give subscribers capability to tune the features they have subscribed to, all you need to do is to develop portlets as per the portlet specification and deploying them on the Jboss server running SipExchange. The rest of the job including authentication and authorization, look and feel, etc. are handled by the portal server.
As far as the portlets accessing the back-end service layer for feature management, the portlets can use the remote interface of the session beans that SipExchange already provides. Alternatively, the portlets can use the web services layer that SipExchange provides.
For more details, see the section on third-party integration.