This document introduces features and concepts behind Rhino SIP Servlet, a SIP Servlet 1.1 JSR 289 container that runs on the OpenCloud Rhino SLEE.

Topics

Architecture

An architectural overview of Rhino SIP Servlet

Developing a SIP Servlet Application

How to develop applications with Rhino SIP Servlet

SIP Servlet 1.1 Resource Adaptor Type

What’s in the Rhino SIP Servlet resource adaptor type

Hybrid Applications

How to write hybrid applications

Application Naming

How Rhino SIP Servlet manages application naming

Application Router

Rhino SIP Servlet’s application router support

SLEE Resource Adaptor Support

How to use SLEE resource adaptors in SIP Servlet applications

Example Applications

SIP Servlet example applications.

Other documentation for the Rhino SIP Servlet including the changelog and links to downloads, can be found on the Rhino SIP Servlet product page.

Architecture

Below is a high-level diagram, followed by descriptions, of the main components of Rhino SIP Servlet. Users can provide the items colored yellow, in the SIP Servlet resource adaptor, container services and management tools.

architecture overview

SIP Servlet resource adaptor

The SIP Servlet RA is a SLEE resource adaptor providing the core of the Rhino SIP Servlet platform, including:

  • a SIP transport layer for communicating with other SIP nodes on the network

  • mapping of SIP network messages to and from the SIP Servlet API’s SipServletRequest and SipServletResponse

  • application selection using the Application Router component

  • Proxy, SipSession, and SipApplicationSession implementation

  • management interfaces (MBeans) for configuration and deployment.

The RA implements a SLEE resource adaptor type (RA type) that wraps the SIP Servlet 1.1 API. The RA type defines the events and activities that may be used by SLEE services. The SIP Servlet Container Service uses the SIP Servlet RA type when it wraps a servlet application (as described below), but may also be used directly by native SLEE applications. See SIP Servlet 1.1 Resource Adaptor Type and Hybrid Applications.

Container services

The SIP Servlet Container Service is a SLEE service that wraps a SIP Servlet application, for deployment into the SLEE platform. When a SIP Servlet application is deployed, Rhino SIP Servlet generates a new container service that contains the SIP Servlet application, and deploys it in the SLEE. The diagram above shows two services, each of which represents a separate SIP Servlet application.

The container service is responsible for providing the runtime environment required by a servlet application. It manages the ServletContext and servlet lifecycle, so is responsible for creating and destroying the servlet application’s servlet and listener instances. The service will invoke the appropriate servlet methods when certain events are received from the RA, such as SIP requests or responses, ServletTimer events, SipApplicationSession, or SipSession events.

Tip The container services and SIP Servlet RA cooperate to provide a complete SIP Servlet 1.1 environment for servlet applications.

Management tools

You manage Rhino SIP Servlet using JMX MBeans. The distribution includes console commands and Ant tasks for installing and uninstalling servlet applications, and configuring the platform. See the Installation and Administration Guide for details.

Warning
Limitation: converged container support

SIP Servlet 1.1 allows "converged containers" — servlet containers that support SIP and HTTP servlets within the same application. Rhino SIP Servlet is not a converged container, it currently only supports SIP servlets.
HTTP servlet and converged container support may be added in a future release.

Developing a SIP Servlet Application

Developers who are already familiar with writing SIP Servlet applications need not change anything just to use Rhino SIP Servlet. They can continue to develop and test servlet applications using their existing tools, IDEs, and so on.

Developers new to SIP Servlet should review the SIP Servlet 1.1 specification (JSR 289) to get started and experiment with Rhino SIP Servlet’s example applications.

Package as a "SAR" file

SIP Servlet applications are packaged as a SAR (SIP Servlet ARchive) file, which like other SLEE or Java EE archive file types, is a JAR file containing the application’s classes, resources and a deployment descriptor, sip.xml.

The SAR file layout looks like this:

WEB-INF/sip.xml     # Deployment descriptor
WEB-INF/classes/... # Application classes (servlets, listeners etc)
WEB-INF/lib/...     # Third-party libraries (jar files)

Deploy with console or Ant commands

Once an application has been packaged as a SAR file, it can be installed into Rhino SIP Servlet using the install-ss (console) or <​sipservlet:install> (Ant) commands. See Application Deployment in the Installation and Administration Guide.

Unlike many other servlet containers, a newly-deployed Rhino SIP Servlet application is not automatically activated. Instead, it is deployed as a SLEE service, which requires an extra activation step before the SLEE will begin firing events to the service.

You can activate the service using standard rhino-console commands, or the <​sipservlet:activate> Ant task.

SIP Servlet 1.1 Resource Adaptor Type

A SLEE resource adaptor type (RA Type) is a specification of the SLEE activities, events and interfaces that a resource adaptor (RA) implements. Rhino SIP Servlet includes an RA type for the SIP Servlet 1.1 API, which adapts the SIP Servlet API for use by SLEE applications.

Note Developers of pure SIP Servlet applications may skip this section, as the Container services hides these details from SIP Servlet applications. This section is useful to those developing Hybrid Applications (SLEE applications directly on top of the SIP Servlet RA type).

Activities

The SIP Servlet RA type defines SIP Servlet SipApplicationSession and SipSession objects as SLEE activities. This means that SBBs may attach to them, use CMP attributes on their activity context interfaces, set timers, or use the Activity Context Naming Facility.

SipApplicationSession

The SIP Servlet creates SipApplicationSession activities automatically when it receives a new initial request for an application. An application can also create a new SipApplicationSession using SipFactory.createApplicationSession().

The SipApplicationSession activity ends when the session becomes invalidated in SIP Servlet 1.1, by:

  • calling SipApplicationSession.invalidate()

  • session expiration

  • invalidate-when-ready is enabled and all SipSessions are ready to invalidate.

SipSession

The SIP Servlet RA type creates SipSession activities when it receives new requests, or when an application sends an outgoing request using the SipFactory.createRequest() methods.

SipSession activities end when the session becomes invalidated in SIP Servlet 1.1, by:

  • calling SipSession.invalidate()

  • session expiration

  • invalidate-when-ready is enabled and the SipSession is ready to invalidate (for example, a dialog-ending request has been sent or received).

Events

The SIP Servlet RA Type defines events that correspond to SIP Servlet’s request-and-response callbacks, and also several listener events — summarized below.

EventTypeID (Name, Vendor, Version)
SIP Servlet equivalent
Description
Class

javax.servlet.sip.SipServletRequest.INVITE, OpenCloud, 1.1 SipServlet.doInvite()

An INVITE request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.ACK, OpenCloud, 1.1 SipServlet.doAck()

An ACK request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.CANCEL, OpenCloud, 1.1 SipServlet.doCancel()

A CANCEL request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.BYE, OpenCloud, 1.1 SipServlet.doBye()

A BYE request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.OPTIONS, OpenCloud, 1.1 SipServlet.doOptions()

An OPTIONS request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.REGISTER, OpenCloud, 1.1 SipServlet.doRegister()

A REGISTER request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.INFO, OpenCloud, 1.1 SipServlet.doInfo()

An INFO request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.PRACK, OpenCloud, 1.1 SipServlet.doPrack()

A PRACK request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.UPDATE, OpenCloud, 1.1 SipServlet.doUpdate()

An UPDATE request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.MESSAGE, OpenCloud, 1.1 SipServlet.doMessage()

A MESSAGE request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.SUBSCRIBE, OpenCloud, 1.1 SipServlet.doSubscribe()

A SUBSCRIBE request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.NOTIFY, OpenCloud, 1.1 SipServlet.doNotify()

A NOTIFY request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.REFER, OpenCloud, 1.1 SipServlet.doRefer()

A REFER request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.PUBLISH, OpenCloud, 1.1 SipServlet.doPublish()

A PUBLISH request was received.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletRequest.UNKNOWN, OpenCloud, 1.1 SipServlet.doRequest()

A request with an unrecognized method was received. Use SipServletRequest.getMethod() to obtain the method.
javax.servlet.sip.SipServletRequest

javax.servlet.sip.SipServletResponse.PROVISIONAL, OpenCloud, 1.1 SipServlet.doProvisionalResponse()

A provisional (100-199) response was received.
javax.servlet.sip.SipServletResponse

javax.servlet.sip.SipServletResponse.SUCCESS, OpenCloud, 1.1 SipServlet.doSuccessResponse()

A success (200-299) response was received.
javax.servlet.sip.SipServletResponse

javax.servlet.sip.SipServletResponse.REDIRECT, OpenCloud, 1.1 javax.SipServlet.doRedirectResponse()

A redirect (300-399) response was received.
javax.servlet.sip.SipServletResponse

javax.servlet.sip.SipServletResponse.ERROR, OpenCloud, 1.1 SipServlet.doErrorResponse()

An error (400-699) response was received.
javax.servlet.sip.SipServletResponse

javax.servlet.sip.SipErrorEvent.NoAckReceived, OpenCloud, 1.1 SipErrorListener.noAckReceived()

An OK response to an earlier INVITE was sent, but the ACK was never received (after 32s).
javax.servlet.sip.SipErrorEvent

javax.servlet.sip.SipErrorEvent.NoPrackReceived, OpenCloud, 1.1 SipErrorListener.noPrackReceived()

A reliable provisional response was sent, but the PRACK was never received (after 32s).
javax.servlet.sip.SipErrorEvent

javax.servlet.sip.SipApplicationSessionEvent.Created, OpenCloud, 1.1 SipApplicationSessionListener.sessionCreated()

A new SipApplicationSession was created.
javax.servlet.sip.SipApplicationSessionEvent

javax.servlet.sip.SipApplicationSessionEvent.Created, OpenCloud, 1.1 SipApplicationSessionListener.sessionCreated()

A new SipApplicationSession was created.
javax.servlet.sip. SipApplicationSessionEvent

javax.servlet.sip.SipApplicationSessionEvent.Expired, OpenCloud, 1.1 SipApplicationSessionListener.sessionExpired()

A SipApplicationSession has expired.
javax.servlet.sip.SipApplicationSessionEvent

javax.servlet.sip.SipApplicationSessionEvent.Expired, OpenCloud, 1.1 SipApplicationSessionListener.sessionExpired()

A SipApplicationSession has expired.
javax.servlet.sip. SipApplicationSessionEvent

javax.servlet.sip.SipApplicationSessionEvent.ReadyToInvalidate, OpenCloud, 1.1 SipApplicationSessionListener.sessionReadyToInvalidate()

A SipApplicationSession has become ready to invalidate.
javax.servlet.sip.SipApplicationSessionEvent

javax.servlet.sip.SipApplicationSessionEvent. ReadyToInvalidate, OpenCloud, 1.1 SipApplicationSessionListener. sessionReadyToInvalidate()

A SipApplicationSession has become ready to invalidate.
javax.servlet.sip. SipApplicationSessionEvent

javax.servlet.sip.SipSessionEvent.Created, OpenCloud, 1.1 SipSessionListener.sessionCreated()

A new SipSession was created.
javax.servlet.sip.SipSessionEvent

javax.servlet.sip.SipSessionEvent.ReadyToInvalidate, OpenCloud, 1.1 SipSessionListener.sessionCreated()

A SipApplicationSession has expired.
javax.servlet.sip.SipSessionEvent

javax.servlet.sip.SipSessionEvent.Invalidate, OpenCloud, 1.1 SipApplicationSessionListener.SessionReadyToInvalidate()

A SipApplicationSession has become ready to invalidate.
javax.servlet.sip.SipSessionEvent

javax.servlet.sip.SipSessionEvent.Invalidate, OpenCloud, 1.1 SipApplicationSessionListener. SessionReadyToInvalidate()

A SipApplicationSession has become ready to invalidate.
javax.servlet.sip.SipSessionEvent

Warning
Some things to note about SIP Servlet events
  • Initial requests and mid-dialog requests have the same event type. The application must distingush between them using SipServletRequest.isInitial(), just as SIP servlets do.

  • All events above are fired on the SipApplicationSession activity. Events that relate to a particular SipSession are still fired on the SipApplicationSession, but the SipSession can always be retrieved from the event object. The decision to fire all events on the SipApplicationSession was made only to avoid scenarios where the same event type could have been fired on either type of activity, depending on what made sense in particular circumstances. Just firing on the SipApplicationSession makes it simpler for the developer to reason about the events.

  • There are no ServletTimer events, as the same functionality is already provided by the SLEE TimerFacility.

  • There are no "session destroyed" events. The SLEE ActivityEndedEvent can be used for the same purpose.

  • SipServletListener.servletInitialized() and the session attribute listeners are not part of this RA type. However they are implemented by the container service when running SIP Servlet applications.

Interfaces

The SIP Servlet RA type specifies these intefaces: SipFactory (the SBB Interface), SipSessionsUtil and ActivityContextInterface.

SipFactory

The SIP Servlet SipFactory interface is this RA Type’s SBB interface. An instance of SipFactory is bound in the SBB’s JNDI environment when the SBB declares an RA Type binding in their sbb-jar.xml deployment descriptor:

<resource-adaptor-type-binding>
  <resource-adaptor-type-ref>
    <resource-adaptor-type-name>SIP Servlet RA Type</resource-adaptor-type-name>
    <resource-adaptor-type-vendor>OpenCloud</resource-adaptor-type-vendor>
    <resource-adaptor-type-version>1.1</resource-adaptor-type-version>
  </resource-adaptor-type-ref>
  <activity-context-interface-factory-name>slee/resources/sipservlet/activitycontextinterfacefactory</activity-context-interface-factory-name>
  <resource-adaptor-entity-binding>
    <resource-adaptor-object-name>slee/resources/sipservlet/provider</resource-adaptor-object-name>
    <resource-adaptor-entity-link>slee/resources/sipservlet</resource-adaptor-entity-link>
  </resource-adaptor-entity-binding>
</resource-adaptor-type-binding>

In the above example, the SipFactory is bound to the name "slee/resources/sipservlet/provider". An SBB object can retrieve the SipFactory as follows:

public abstract class MySipSbb implements Sbb {
    private SipFactory sipFactory;

    public void setSbbContext(SbbContext context) {
        try {
            Context env = (Context) new InitialContext().lookup("java:comp/env");
            this.sipFactory = (SipFactory) env.lookup("slee/resources/sipservlet/provider");
        } catch (NamingException e) {
            ...
        }
    }
}

SipSessionsUtil

The SipSessionsUtil interface is made available to SBBs using a separate RA Type. To access SipSessionsUtil, SBBs must declare the following RA Type binding (in addition to the SIP Servlet RA Type as shown above):

<resource-adaptor-type-binding>
  <resource-adaptor-type-ref>
    <resource-adaptor-type-name>SIP Servlet-sessionsutil RA Type</resource-adaptor-type-name>
    <resource-adaptor-type-vendor>OpenCloud</resource-adaptor-type-vendor>
    <resource-adaptor-type-version>1.1</resource-adaptor-type-version>
  </resource-adaptor-type-ref>
  <resource-adaptor-entity-binding>
    <resource-adaptor-object-name>slee/resources/sipservlet/sessionsutilprovider</resource-adaptor-object-name>
    <resource-adaptor-entity-link>slee/resources/sipservlet</resource-adaptor-entity-link>
  </resource-adaptor-entity-binding>
</resource-adaptor-type-binding>

…​and obtain the reference from JNDI:

public abstract class MySipSbb implements Sbb {
    private SipFactory sipFactory;
    private SipSessionsUtil sessionsUtil;

    public void setSbbContext(SbbContext context) {
        try {
            Context env = (Context) new InitialContext().lookup("java:comp/env");
            this.sipFactory = (SipFactory) env.lookup("slee/resources/sipservlet/provider");
            this.sessionsUtil = (SipFactory) env.lookup("slee/resources/sipservlet/sessionsutilprovider");
        } catch (NamingException e) {
            ...
        }
    }
}

ActivityContextInterface

The ActivityContextInterface factory interface for the SIP Servlet RA Type is com.opencloud.sipservlet.ratype.SipServletActivityContextInterfaceFactory:

public interface SipServletActivityContextInterfaceFactory {
    public ActivityContextInterface getActivityContextInterface(SipSession session)
            throws UnrecognizedActivityException, FactoryException;
    public ActivityContextInterface getActivityContextInterface(SipApplicationSession session)
            throws UnrecognizedActivityException, FactoryException;
}

Hybrid Applications

As well as writing pure SIP Servlet applications, developers can use Rhino SIP Servlet to write hybrid applications: SLEE services that use the SIP Servlet RA Type API.

This means they can make use of the nice features in the SIP Servlet API (such as built-in proxying), while also using the SLEE component model (SBBs, events, activities, activity contexts, and so on).

Participating in application selection

Hybrid applications can take part in the application-selection process, controlled by the Application Router. SIP Servlet and hybrid applications can be composed together on the same SIP call.

Hybrid applications are normal SLEE services, so are identified by their ServiceID. The Application Router uses application names to refer to the applications it selects. When deploying a hybrid application, the deployer must also manually create an application name so that the Application Router can select it.

Hybrid application example

The examples/proxy-hybrid directory in the Rhino SIP Servlet package contains an example SLEE service that uses the SIP Servlet API to implement a simple proxy.

Run “ant deploy” in the examples/proxy-hybrid directory to deploy the service.

Note that the service does not perform any SIP registration lookups; it simply forwards requests to the next hop.

Application Naming

Applications deployed in a SIP Servlet container are identified using their application name, a string.

The application developer or deployer sets the application name in the <app-name> element of the sip.xml deployment descriptor, or by using the @SipApplication annotation’s name attribute. The container uses the application name as the unique identifier for the application, and the application router uses application names when selecting the applications to run.

Rhino SIP Servlet runs on the Rhino SLEE platform, and SIP Servlet applications are deployed as SLEE services. SLEE services are uniquely identified by their ServiceID, an identifier containing service name, vendor, and version strings.

When the application router determines the next application to invoke, it returns the application name to the container. But in this case the "container" is the SIP Servlet RA, which must translate the name to a SLEE ServiceID, so that it can trigger the SLEE service containing the servlet application.

For this reason, the SIP Servlet RA maintains a table that maps SIP Servlet application names to SLEE ServiceIDs, and vice versa. These mappings are called application name references in the Rhino SIP Servlet documentation.

Note The SIP Servlet RA ensures a one-to-one mapping between application names and ServiceIDs. So it’s impossible for more than one application name to map to the same ServiceID, or for more than one ServiceID to map to the same application name.

Automatic application naming

When SIP servlet applications are installed using Rhino SIP Servlet’s management commands (install-ss (console) or <sipservlet:install> (Ant)), the SIP Servlet RA generates a SLEE service that wraps the servlet application. During deployment, the RA automatically creates an application name reference that maps the application name to the new service’s ServiceID.

Manual application naming

It’s also possible to manually create application name references. This is only required when deploying Hybrid Applications, which are traditional SLEE services that use the SIP Servlet RA Type. These are deployed using Rhino’s normal installation commands, bypassing the SIP Servlet RA’s servlet deployment mechanisms. In this case it is necessary to manually setup the application name references, so that the application router can refer to hybrid applications by their servlet application names.

Warning If a SLEE service has no application name, it cannot be invoked by the SIP Servlet RA.

Application name references are managed using the createapplicationnameref, replaceapplicationnameref and removeapplicationnameref console commands, and corresponding Ant tasks. See the Installation and Administration Guide for details and examples.

Application Router

SIP Servlet 1.1 specifies the Application Router component. The Application Router is responsible for selecting the SIP Servlet applications that will process an initial request.

In other words, it determines how applications are composed. The servlet applications themselves do not have any knowledge of the Application Router, so they can be developed independently, and then composed together at deployment time, by configuring the Application Router for a particular scenario.

The Application Router is, by design, a separate component to the SIP Servlet container. This means that users are free to use third-party Application Routers, or write their own. An Application Router may use any criteria for selecting applications, such as source or destination addresses, SIP header fields, time of day, database lookup, and so on.

All SIP Servlet 1.1 containers must provide a Default Application Router, which is specified in SIP Servlet 1.1 Appendix C. Rhino SIP Servlet includes a Default Application Router, and users may also deploy their own.

Default application router

The default application router (DAR) supplied with Rhino SIP Servlet implements the behaviour specified in SIP Servlet 1.1 Appendix C. It is configured using the properties file format described in the appendix. Configuration files are installed in the DAR using Rhino SIP Servlet’s console or Ant commands.

A DAR configuration file is a properties file, where each line begins with a SIP request method (such as INVITE, REGISTER), followed by a list of applications that will process that type of request. For example:

REGISTER: ("Registrar", "DAR:From", "ORIGINATING", "", "NO_ROUTE", "0"), ("Presence", "DAR:From", "ORIGINATING", "", "NO_ROUTE", "1")
INVITE: ("CallBarring", "DAR:From", "ORIGINATING", "", "NO_ROUTE", "0"), ("LocationServiceProxy", "DAR:From", "ORIGINATING", "", "NO_ROUTE", "1")

This says that REGISTER requests will be processed by the "Registrar" application, then the "Presence" application. INVITE requests will trigger the "CallBarring" application, then the LocationServiceProxy" application. (The other arguments are described in SIP Servlet 1.1 Appendix C.)

The installed DAR configuration is used for all initial requests; there is no support for conditional or per-user rules.

Custom application routers

A custom application router can be used if more advanced application composition logic is required, such as subscriber lookup, or inspecting SIP header fields. See the Installation and Administration Guide for information on installing custom Application Routers.

SLEE Resource Adaptor Support

Servlet applications deployed on Rhino SIP Servlet can use any SLEE Resource Adaptor (RA) deployed in the platform.

The SLEE uses RAs to talk to external resources. They may implement any protocol. For example, OpenCloud provides RAs for SIP, HTTP, SS7 (CAP/INAP), Diameter, and many others.

SIP Servlet applications running on Rhino SIP Servlet can use these RAs just like any other SLEE application, so servlets are not just limited to communicating using SIP.

How do applications access the RAs?

Servlet applications need to use a subset of the SLEE API to access SLEE RAs. The SLEE specification defines how SLEE applications declare which RAs they need, how events are received from RAs, and how to access an RA’s interface to interact with external resources.

Rhino SIP Servlet provides the sipservlet-slee API that bridges between the SIP Servlet and SLEE containers. This allows servlet applications to use RAs in the same way as SLEE applications, without leaving the SIP Servlet application environment.

The following sections describe how a servlet application can be enhanced to use SLEE RAs:

Dependencies

A servlet application using SLEE RAs has the following compile-time dependencies, which may be found under lib/ in the Rhino SIP Servlet distribution.

  • slee-1.1.jar and jta-1.0.1B.jar — the JAIN SLEE 1.1 API jars

  • sipservlet-slee-<version>.jar — interfaces to bridge between SLEE and SIP Servlet

  • slee-annotations-<version>.jar — annotations for declaring which SLEE RA types and events are required by an application.

Note The actual version numbers may vary in different releases, so they are not shown above.

The Ant build file common.xml defines the path reference sipservlet.api.classpath, which contains the SIP Servlet 1.1 API and the jars above. If using Ant, your own project can be compiled simply by importing common.xml and using the path reference:

build.xml
<import file="/path/to/rhino-sip-servlet/common.xml"/>
...
<javac destdir="${classes}" srcdir="${src}" includes="**/*.java">
<classpath>
<path refid="sipservlet.api.classpath"/>
...
</classpath>
</javac>

Alternatively, make these jars available as appropriate for your own build environment. At runtime these dependencies are provided by the Rhino SIP Servlet platform, so do not need to be packaged with the servlet application.

You will also need to provide the resource adaptor type jars and any other jars required by the particular RA types your application needs. These will usually be found in the distribution package for each RA. The RA types and RAs will be deployed separately in the SLEE, and do not need to be bundled with the servlet application.

RA Type Bindings

Before an RA can be used, the application must declare a binding to an RA type.

Note

A resource adaptor type (RA type) is a SLEE component that specifies the interface between an RA and SLEE applications. It defines:

  • the event types that may be fired by the RA

  • the types of activities created by the RA

  • the RA interface (a Java interface) that applications may call to use the RA

  • the activity context interface factory interface (see below).

When an application declares a binding to an RA type, Rhino ensures that the RA type’s classes (and their dependencies) are available in the application’s classloader, and any interfaces provided by the RA type are bound into JNDI at locations specified by the application in the binding.

The same RA type may be implemented by more than one RA, and there may also be more than one instance of an RA (RA entity in SLEE terms) deployed at a time. For example, there may be multiple HTTP RA entities deployed, each listening on a different port. So the the application’s RA type binding can also specify which RA entity (or entities) it wants to use.

Package declaration for an application

To declare an RA type binding, a servlet application uses the @SleeRATypes annotation on a package. RA Type bindings apply to the entire application, so it makes sense to annotate the same package where @SipApplication is declared (if using SIP Servlet annotations), or the top-level package of the application. The @SleeRATypes must only be specified on one package in the application.

Here is the package declaration for an example application:

package-info.java
@SipApplication(name = "example", mainServlet = "main-servlet")
@SleeRATypes({
    @RATypeBinding(raType = @ComponentId(name = "HTTP", vendor = "OpenCloud", version = "2.2"),
        activityContentInterfaceFactoryName = "slee/resources/http/acifactory",
        resourceAdaptorEntityLink = "slee/resources/http",
        resourceAdaptorObjectName = "slee/resources/http/provider")
})
package com.example.app;

import com.opencloud.sipservlet.slee.annotation.SleeRATypes;
import javax.servlet.sip.annotation.SipApplication;
import javax.slee.annotation.*;

Here the application is declaring a binding to the OpenCloud HTTP 2.2 RA type. This is an actual RA type, and is included with the example application in examples/http-example/. The various elements that make up the binding are:

@SleeRATypes

This annotation is the "container" for one or more @RATypeBinding elements. If an application uses several RA types, then they must all be defined inside a single @SleeRATypes element. Order is not significant.

@RATypeBinding

The start of an RA type binding declaration.

raType = @ComponentId(name = "…​", vendor = "…​", version = "…​")

This attribute specifies the RA type’s component ID, a triple of name, vendor, and version strings. All SLEE components are identified in this way. At deploy time, this must match an RA type that is deployed in the SLEE.

activityContentInterfaceFactoryName = "…​"

Optional. This attribute specifies the JNDI object name for the RA type’s activity context interface factory interface. This is required if the application wants to attach to activities created by an RA, which is often the case. See [7.4 Activities and Activity Contexts].

resourceAdaptorEntityLink = "…​"

Optional. Identifies the link name of an RA entity. This is a reference to an RA entity deployed in the SLEE. The link name may be anything, but must be configured (using SLEE management commands) to point to an actual RA entity in the SLEE before the application is deployed.

resourceAdaptorObjectName = "…​"

Optional. This attribute specifies the JNDI object name for the RA interface provided by the RA entity linked to as above. This object implements the RA interface as defined by the RA type.

|---- @SleeListener

|This annotation marks those classes in the application that may receive SLEE events. Servlet and Listener classes may use this annotation.

|----
@EventMethod

|Marks an event handler method. The SLEE invokes this method when a matching event is received.

|---- eventType = @ComponentId(name = "…​", vendor = "…​", version = "…​")

|Like other SLEE components, event types are identified by name, vendor, and version.

|===

== Event handler methods

As well as the `@EventMethod` annotation, event handler methods must have a particular signature.

* They must be public, not-static methods that return `void`.
* The method name must be on `<event-name>`. The event name must be a unique name within the servlet application.
* The first parameter is the event object. The parameter type is defined by the SLEE event type's definition, usually part of the RA type definition.
* The second parameter is the ACI of the activity that the event was fired on.
* The last parameter is the `SipApplicationSession` instance that is processing the event.

The event handler method can process the event just like a SLEE SBB event handler method. The activity object associated with the event can be obtained using `ActivityContextInterface.getActivity()` on the ACI passed to the event handler method.

== Initial events

SIP servlet application instances are typically created when a new initial SIP request arrives, which is not associated with any existing `SipSession`. A new `SipSession` and `SipApplicationSession` are created to process the request, and the `SipApplicationSession` will hold any state for the new application instance.

It is also possible to trigger a new application instance using events from other SLEE RAs. To do this, the application must declare that one or more event types are _initial events_. This is done by adding the `initialEvent=true` attribute to an `@EventMethod` annotation:

[source,java]

@EventMethod(eventType = @ComponentId(name = "com.opencloud.slee.resources.http.HttpRequest.GET", vendor = "OpenCloud", version = "2.2"), initialEvent = true) public void onHttpRequest(HttpRequest request, ActivityContextInterface aci, SipApplicationSession appSession) { log("servlet received HTTP request: " + request); }

Here this means that an HTTP GET request will create a new `SipApplicationSession` instance. It could then initiate a new `SipSession` with another SIP device, to implement a "click-to-dial" service.

Initial events can also enable bxref:converged-applications[converged applications].

:leveloffset!:

:ocdoc_current_file: /mnt/volume-01/jenkins/workspace/product/ra/sipservlet/release-1.1.0/Release-docs/sipservlet-docs/rhino-sip-servlet-overview-and-concepts/slee-resource-adaptor-support/converged-applications.adoc

:here: slee-resource-adaptor-support/
:idprefix: converged-applications

:leveloffset: 1

= Converged Applications
:sortorder: 760

// DevPortal author: ~jonh



Often it is desirable to have initial events be processed by the same application instance.

For example, a conferencing service might want to have all calls to the conference address be handled by the same application instance, so the state of all participants can be easily managed in a single `SipApplicationSession`.

== Session targeting mechanisms

SIP Servlet provides several _session targeting_ mechanisms that allow initial SIP requests to be directed to the same `SipApplicationSession`. The most generic session targeting mechanism is the `@SipApplicationKey` method. The SIP Servlet container invokes a `@SipApplicationKey` method with the initial request, and the method returns a string which identifies a `SipApplicationSession`, creating the session if it doesn't exist.

`@SipApplicationKey` only applies to SIP requests, but Rhino SIP Servlet provides an equivalent session targeting mechanism for non-SIP initial events. This means that events from different protocols can be directed to the same application instance, enabling converged applications.

=== @SleeApplicationKey session targeting

To implement session targeting for non-SIP events, a servlet application defines a `@SleeApplicationKey` method. This is very similar to `@SipApplicationKey` methods, in that it takes an initial event and returns a string. The string identifies a `SipApplicationSession` instance, which is created automatically if it doesn't already exist.

TIP: The `@SleeApplicationKey` method is only used for non-SIP initial events; SIP events will still use `@SipApplicationKey`. To enable SIP and non-SIP initial events to select the same application instance, the application developer just has to ensure that these two methods return the same values for related events.

The signature of the `@SleeApplicationKey`-annotated method looks like this:

[source,java]

@SleeApplicationKey public static String anyMethodName(Object event, Object activity) { …​ }

The method must satisfy these properties:

* Only one method in the application can be annotated with `@SleeApplicationKey`.
* The method must be public and static.
* The method may have any name.
* The method must return `String`.
* The method must have two `Object` parameters, which are the SLEE event and its activity object.

The body of the method can do anything, but it should be idempotent. It should inspect the event and activity parameters and extract the required information, such as user IDs or session IDs, to generate the return value.

=== Default session targeting behaviour

If there is no `@SleeApplicationKey` method defined in the application, Rhino SIP Servlet will just create a new `SipApplicationSession` instance for each new non-SIP activity.

:leveloffset!:

:ocdoc_current_file: /mnt/volume-01/jenkins/workspace/product/ra/sipservlet/release-1.1.0/Release-docs/sipservlet-docs/rhino-sip-servlet-overview-and-concepts/slee-resource-adaptor-support/slee-libraries.adoc

:here: slee-resource-adaptor-support/
:idprefix: slee-libraries

:leveloffset: 1

= SLEE Libraries
:sortorder: 770

// DevPortal author: ~jonh

Servlet applications may also use any library components deployed in the SLEE.

Like RA type bindings, library bindings are declared using annotations on a package within the application:

[source,java]

@SleeLibraries({ @LibraryReference(library = @ComponentId(name = "guava", vendor = "com.google.guava", version = "17.0")), @LibraryReference(library = @ComponentId(name = "protobuf-java", vendor = "com.google.protobuf", version = "2.5.0")), }) package com.example.app;

import com.opencloud.sipservlet.slee.annotation.; import javax.slee.annotation.;

Here the application has declared a dependency on two other libraries. These libraries must be deployed in the SLEE before the servlet application can deploy.

NOTE: Use of SLEE libraries is purely optional; servlet applications can also just put their dependencies in +
`WEB-INF/lib` in their SAR file. SLEE libraries may be useful if they are shared by many applications on the same SLEE platform.

:leveloffset!:

:ocdoc_current_file: /mnt/volume-01/jenkins/workspace/product/ra/sipservlet/release-1.1.0/Release-docs/sipservlet-docs/rhino-sip-servlet-overview-and-concepts/example-applications.adoc

:here:
:idprefix: example-applications

:leveloffset: 1

= Example Applications
:sortorder: 800

// DevPortal author: ~ben

Your Rhino SIP Servlet installation comes with example applications, in the `examples/` directory. Each subdirectory under `examples/` holds a self-contained SIP Servlet application, with source code and Ant deployment scripts.

Running `ant` inside an example application's directory executes the default `deploy` build target, which builds the application and deploys it into the SLEE.

Once deployed, the application can be tested using your preferred SIP testing tools, such as http://sipp.sourceforge.net[SIPp] or https://sourceforge.net/projects/sipsak.berlios/[sipsak], or SIP softphones such as http://mfnboer.home.xs4all.nl/twinkle/index.html[Twinkle], http://www.linphone.org[Linphone] or http://www.counterpath.com/x-lite/[X-Lite].


WARNING: You must gxref:rhino-sip-servlet-installation-and-administration-guide/installing-rhino-sip-servlet[deploy a Rhino SIP Servlet RA entity] before attempting to install the example applications.

Below are descriptions of the sample applications: bxref:#code-sipservlet-services-code[sipservlet-services], bxref:#code-proxy-hybrid-code[proxy-hybrid] and bxref:#code-http-example-code[http-example].

== sipservlet-services

[cols="1h,5a"]
|===

| What it does
| Implements some typical SIP services:

* Registrar
* Back-to-back user agent (B2BUA) & Proxy
* Presence.

| How to configure
| * Only one of the B2BUA or Proxy servlets should be enabled at a time.
* The B2BUA servlet is enabled by default.
* To enable the Proxy servlet, uncomment the `<servlet-mapping>` element for `proxy-servlet` in the deployment descriptor, and comment out the corresponding `b2b-proxy-servlet` element.
* Use the env-entry "`localDomains`" to specify a comma-separated list of domain names that the proxy and B2BUA consider to be local.

If these servlets receive a request with a Request-URI containing a SIP identity (a.k.a. _address of record_) that is within one of these domains, the servlets lookup the SIP identity in the registration database to find a registered contact address. If no entry is found, an error response is returned to the caller.
The registration database is populated by the Registrar servlet when SIP clients send REGISTER requests to register their current contact address.

The application's deployment descriptor can be found at `resources/WEB-INF/sip.xml`.

| Database it uses
| An embedded (in-process) Derby database to store SIP registrations; created automatically during deployment.
|===

== proxy-hybrid

NOTE: This is an example *hybrid application* -- a SLEE service that uses the SIP Servlet 1.1 RA Type, and uses the SIP Servlet Proxy interface to implement a simple proxy.

[cols="1h,5a"]
|===

| What it does
| Implements a _very simple_ proxy; does not attempt to lookup registered SIP identities, so it can only forward requests to their next hop.

| How to configure
| Edit the service's SBB deployment descriptor: `resources/META-INF/sbb-jar.xml`.

_The environment entries_ `proxyRecordRoute` _and_ `proxySupervised` _are applied to the_ `Proxy` _instances that are created when processing initial requests._
|===

== http-example

NOTE: This is an example of a servlet application using a bxref:slee-resource-adaptor-support[SLEE Resource Adaptor] to communicate using another protocol, in this case HTTP.

[cols="1h,5a"]
|===

| What it does
| A simple proxy that also uses the HTTP RA to make an HTTP request. Also processes incoming HTTP requests as initial events.

| How to configure
| No configuration required.

|===

:leveloffset!: