Skip Headers
Oracle® Communications Converged Application Server SIP Application Development Guide
Release 5.0

Part Number E17654-02
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

3 Requirements and Best Practices for SIP Applications

This chapter describes requirements and best practices for developing applications for deployment to Oracle Communications Converged Application Server:

Overview of Developing Distributed Applications for Converged Application Server

In a typical production environment, SIP applications are deployed to a cluster of Converged Application Server instances that form the engine tier cluster. A separate cluster of servers in the SIP data tier provides a replicated, in-memory database of the call states for active calls. In order for applications to function reliably in this environment, you must observe the programming practices and conventions described in the sections that follow to ensure that multiple deployed copies of your application perform as expected in the clustered environment.

If you are porting an application from a previous version of Converged Application Server, the conventions and restrictions described below may be new to you, because the 2.0 and 2.1 versions of WebLogic SIP Server implementations did not support clustering. Thoroughly test and profile your ported applications to discover problems and ensure adequate performance in the new environment.

Applications Must Not Create Threads

Converged Application Server is a multi-threaded application server that carefully manages resource allocation, concurrency, and thread synchronization for the modules it hosts. To obtain the greatest advantage from the Converged Application Server architecture, construct your application modules according to the SIP Servlet and Java EE API specifications.

Avoid application designs that require creating new threads in server-side modules such as SIP Servlets:

Servlets Must Be Non-Blocking

SIP and HTTP Servlets must not block threads in the body of a SIP method because the call state remains locked while the method is invoked. For example, no Servlet method must actively wait for data to be retrieved or written before returning control to the SIP Servlet container.

Store all Application Data in the Session

If you deploy your application to more than one engine tier server (in a replicated Converged Application Server configuration) you must store all application data in the session as session attributes. In a replicated configuration, engine tier servers maintain no cached information; all application data must be de-serialized from the session attribute available in SIP data tier servers.

All Session Data Must Be Serializable

To support in-memory replication of SIP application call states, you must ensure that all objects stored in the SIP Servlet session are serializable. Every field in an object must be serializable or transient in order for the object to be considered serializable. If the Servlet uses a combination of serializable and non-serializable objects, Converged Application Server cannot replicate the session state of the non-serializable objects.

Use setAttribute() to Modify Session Data in "No-Call" Scope

The SIP Servlet container automatically locks the associated call state when invoking the doxxx method of a SIP Servlet. However, applications may also attempt to modify session data in "no-call" scope. No-call scope refers to the context where call state data is modified outside the scope of a normal doxxx method. For example, data is modified in no-call scope when an HTTP Servlet attempts to modify SIP session data, or when a SIP Servlet attempts to modify a call state other than the one that the container locked before invoking the Servlet.

Applications must always use the SIP Session's setAttribute method to change attributes in no-call scope. Likewise, use removeAttribute to remove an attribute from a session object. Each time setAttribute/removeAttribute is used to update session data, the SIP Servlet container obtains and releases a lock on the associated call state. (The methods enqueue the object for updating, and return control immediately.) This ensures that only one application modifies the data at a time, and also ensures that your changes are replicated across SIP data tier nodes in a cluster.

If you use other set methods to change objects within a session, Converged Application Server cannot replicate those changes.

Note that the Converged Application Server container does not persist changes to a call state attribute that are made after calling setAttribute. For example, in the following code sample the setAttribute call immediately modifies the call state, but the subsequent call to modifyState() does not:

Foo foo = new Foo(..);
  appSession.setAttribute("name", foo); // This persists the call state.
  foo.modifyState(); // This change is not persisted.

Instead, ensure that your Servlet code modifies the call state attribute value before calling setAttribute, as in:

Foo foo = new Foo(..);
  foo.modifyState();
  appSession.setAttribute("name", foo);

Also, keep in mind that the SIP Servlet container obtains a lock to the call state for each individual setAttribute call. For example, when executing the following code in an HTTP Servlet, the SIP Servlet container obtains and releases a lock on the call state lock twice:

appSess.setAttribute("foo1", "bar2");
appSess.setAttribute("foo2", "bar2");

This locking behavior ensures that only one thread modifies a call state at any given time. However, another process could potentially modify the call state between sequential updates. The following code is not considered thread safe when done no-call state:

Integer oldValue = appSession.getAttribute("counter");
Integer newValue = incrementCounter(oldValue);
appSession.setAttribute("counter", newValue);

To make the above code thread safe, you must enclose it using the wlssAppSession.doAction method, which ensures that all modifications made to the call state are performed within a single transaction lock, as in:

wlssAppSession.doAction(new WlssAction() {
       public Object run() throws Exception {
         Integer oldValue = appSession.getAttribute("counter");
         Integer newValue = incrementCounter(oldValue);
         appSession.setAttribute("counter", newValue);
         return null;
       }
     });

Finally, be careful to avoid deadlock situations when locking call states in a "doSipMethod" call, such as doInvite(). Keep in mind that the Converged Application Server container has already locked the call state when the instructions of a doSipMethod are executed. If your application code attempts to access the current call state from within such a method (for example, by accessing a session that is stored within a data structure or attribute), the lock ordering results in a deadlock.

Example 3-1 shows an example that can result in a deadlock. If the code is executed by the container for a call associated with callAppSession, the locking order is reversed and the attempt to obtain the session with getApplicationSession(callId) causes a deadlock.

Example 3-1 Session Access Resulting in a Deadlock

WlssSipApplicationSession confAppSession = (WlssSipApplicationSession) appSession;
confAppSession.doAction(new WlssAction() {  
  // confAppSession is locked
  public Object run() throws Exception {
    String callIds = confAppSession.getAttribute("callIds");
    for (each callId in callIds) {
      callAppSess = Session.getApplicationSession(callId); 
      // callAppSession is locked
      attributeStr += callAppSess.getAttribute("someattrib");
    }
    confAppSession.setAttribute("attrib", attributeStr);
  }
}

See "Modifying the SipApplicationSession" for more information about using the com.bea.wcp.sip.WlssAction interface.

send() Calls Are Buffered

If your SIP Servlet calls the send() method within a SIP request method such as doInvite(), doAck(), doNotify(), and so forth, keep in mind that the Converged Application Server container buffers all send() calls and transmits them in order after the SIP method returns. Applications cannot rely on send() calls to be transmitted immediately as they are called.

Caution:

Applications must not wait or sleep after a call to send(), because the request or response is not transmitted until control returns to the SIP Servlet container.

Mark SIP Servlets as Distributable

If you have designed and programmed your SIP Servlet to be deployed to a cluster environment, you must include the distributable marker element in the Servlet's deployment descriptor when deploying the application to a cluster of engine tier servers. If you omit the distributable element, Converged Application Server does not deploy the Servlet to a cluster of engine tier servers. If you mark distributable in sip.xml it must also be marked in the web.xml for a WAR file.

The distributable element is not required, and is ignored if you deploy to a single, combined-tier (non-replicated) Converged Application Server instance.

Use SipApplicationSessionActivationListener Sparingly

The SIP Servlet 1.1 specification introduces SipApplicationSessionActivationListener, which can provide callbacks to an application when SIP Sessions are passivated or activated. Keep in mind that callbacks occur only in a replicated Converged Application Server deployment. Single-server deployments use no SIP data tier, so SIP Sessions are never passivated.

Also, keep in mind that in a replicated deployment Converged Application Server activates and passivates a SIP Session many times, before and after SIP messages are processed for the session. (This occurs normally in any replicated deployment, even when RDBMS-based persistence is not configured.) Because this constant cycle of activation and passivation results in frequent callbacks, use SipApplicationSessionActivationListener sparingly in your applications.

Session Expiration Best Practices

For a JSR289 application, the container is more "intelligent" in removing sessions. For example, there is no need to explicity call invalidate() on a session or sipappsession.

However, if setExpirs() is used on a session and the application is of a JSR289 type then that call has no effect unless setInvalidateWhenRead(false) is called on the session.

Observe Best Practices for Java EE Applications

If you are deploying applications that use other Java EE APIs, observe the basic clustering guidelines associated with those APIs. For example, if you are deploying EJBs, you must design all methods to be idempotent and make EJB homes clusterable in the deployment descriptor. See the discussion on clustering best practices in the Oracle WebLogic Server Documentation for more information.

Optimizing Memory Utilization or Performance for a Standalone Domain

Converged Application Server provides a local serialization flag which enables you to optimize a standalone domain for memory utilization or performance, as required by a SIP application. The local serialization flag is a System property called wlss.local.serialization which must be provided to the Java Virtual Machine (JVM) that will start Converged Application Server.

Set the System property wlss.local.serialization with the appropriate value in the startWebLogic.sh script. The startWebLogic.sh script is located in the DOMAIN_HOME/bin directory where DOMAIN_HOME is the domain's home directory.

This flag can be set to one of the following values: