# Platform Development Studio - Developer’s Guide

# Service Enabler Example with SIP plug-in

This section describes the example network protocol plug-in for SIP connectivity provided in the Platform Development Studio:

- Overview

- High-level Flow for sendData (Flow A)
- High-level Flow for startNotification and stopNotification (Flow B)
- High-level flow for notifyDataReception (Flow C)

- Interfaces

- Web Service Interface Definition
- Network Interface Definition

- Directory Structure
- Classes
- SLA

## Overview

The SIP Plug-in example demonstrates the following:

- Structure and execution workflow in a Communication Service.
- Parameter validation
- Hitless upgrade
- Retry
- SIP connectivity using a SIP Servlet
- Testability with the PTE

The example is based on an end-to-end Communication Service, with a set of simple interfaces

- SendData, which defines the operation `sendData` used to send data to a given address.
- NotificationManager, which defines these operations:

- `startEventNotification`, that starts a subscription for network-triggered events.
- `stopEventNotification`, that ends the subscription for network-triggered events.

- Notification, which defines the operation:

- `notifyDataReception`, used to notify the application on a network-triggered event.

The SendData and NotificationManager interfaces are used by an application and implemented by the Communication Service.

The Notification interface is used by the Communication Service and implemented by an application.

The Communication Service to network node interface is a simple SIP based interface that defines the two commands:

- `send`, that sends data to the SIP network.
- `receiveData`, that is used by the network node to send data to a receiver - in this case the network protocol plug-in.

Figure 6-1 illustrates the flow for these operations.

Figure 6-1 Overview of example Communication Service with SIP plug-in

The flow marked A* is for`sendData`, the flow marked B* is for `startNotification` and s`topNotification`, and the flow marked C* is for `notifyDataReception`.

The modules marked with 1 are automatically generated based on the WSDL files that defines the application-facing interface and code generation templates provided by the Platform Development Studio. The modules marked with 2 are skeletons generated at build time.

### High-level Flow for sendData (Flow A)

1. A1: An application invokes the Web Service SendData, with the operation `sendData`.
2. A2: The request is passed on the EJB for the interface, which passes it on to the network protocol plug-in. The diagram is simplified, but at this stage the Plug-in Manager is invoked and makes a routing decision to the appropriate plug-in.
3. A3: The Plug-in Manager invokes the `sendData` method in the class SendDataPluginNorth. It will always invoke a class named PluginNorth, that has a prefix that is the same as the Java representation of the Web Service interface.
4. A4: The SIP request is created.
5. A5: The the SIPFactory is fetched from ExampleSIPHelper.
6. A6: The request is handed off to the network node.

### High-level Flow for startNotification and stopNotification (Flow B)

The initial steps (B1-B3) are similar to flow A*. Instead of translating the request to a command on the network node, NotificationManagerNorth uses the StoreHelper to either store a new or remove a previously registered subscription for notifications. The data stored, the NotificationData, is used in network-triggered requests to resolve which application started the notification and the destination to which to send it. In the example the notification is started on an address, so the address is stored together with information to which endpoint the application wants the notification to be sent.

### High-level flow for notifyDataReception (Flow C)

1. C1: The network protocol plug-in receives the network-triggered SIP message to ExampleSipServlet.
2. C2: SendDataPluginSouth can be used to add additional information to the request before passing in on.
3. C3: ExampleSipHelper finds a plug-in instance to pass on the request to.
4. C4: ExampleSipHelper calls NotificationHandlerSouth.
5. C5: StoreHelper is used to examine if the request matches any stored NotificationData. If so, the information in NotificationData is retrieved. This information includes which application instance that the request resolves to and on which endpoint this application wants to be notified about the network triggered event.
6. C6: NotificationCallbackFactory is used to get a hold of an active NotificationCallback EJB to pass on the request to.
7. C7: The request is passed on to the NotificationCallback EJB.
8. C8: The request is passed on to an application.

## Interfaces

The SIP plug-in translates between an application-facing interface, defined in WSDL, see Web Service Interface Definition and a SIP network interface, see Network Interface Definition.

### Web Service Interface Definition

The WSDL, and Service Facade used is the same as for the Example Communication Service, see Web Service Interface Definition in Communication Service Example.

### Network Interface Definition

The network interface is SIP and the plug-in uses the Oracle Converged Application Server SIP Servlet container to process and create SIP messages.

Application-initiated requests are converted to regular SIP messages. It is configurable whether to send it to a SIP Proxy or not.

All SIP messages that arrive to the plug-in are processed and passed on the application that has subscribed for notifications that matches the network-triggered request.

## Directory Structure

The directory structure is similar to the directory structure for the example Communication Service, see Directory Structure in Communication Service Example but adds a set of classes, descriptors, and artifacts as described below:

    | +- plugins

    | | +- sip

    | | | +- config

    | | | | +- sip

    | | | | | +- WEB-INF

    | | | | | | +- sip.xml

    | | | | | | +- web.xml

    | | | +- dist

    | | | | +- com.acompany.plugin.example.sip.store_4.0.jar

    | | | | +- example_sip_plugin.jar

    | | | | +- example_sip.war

    | | | +- src/com/acompany/plugin/example/sip/

    | | | |           +- context

    | | | |           +- management

    | | | |           +- notification

    | | | |           +- notificationmanager

    | | | |           +- senddata

    | | | |           +- servlet

    | | | |           +- store

    | | | +- storage

    | | | | +- wlng-cachestore-config-extensions.xml

### Differences Compared to the Example netex Plug-in

The source for the example SIP plug-in is very similar to the netex plug-in described in Communication Service Example. Below is a list of the classes that are added or changed.

The SIP plug-in has a different package structure compared to the netex plug-in:

    package com.acompany.plugin.example.sip.*

The following classes are new, and relates to the SIP protocol:

- `com.acompany.plugin.example.sip.servlet.ExampleServlet`
- `com.acompany.plugin.example.sip.ExampleSipHelper`

The class `com.acompany.plugin.example.netex.senddata.south.SendDataPluginToNetworkAdapter` has been replaced by direct calls from `SendDataPluginNorth` to `SendDataPluginSouth`.

The class `com.acompany.plugin.example.netex.notification.south.SendDataPluginToNetworkAdapter` has been replaced by `com.acompany.plugin.example.sip.notification.south.NotificationHandlerSouth`. The class also does a lookup for matching subscriptions. In the netex plug-in, this is done by NotificationHandlerNorth.

The class `com.acompany.plugin.example.sip.senddata.south.SendDataPluginSouth` has been updated to use `ExampleSipHelper`.

The MBean `com.acompany.plugin.example.sip.management.ExampleMBean` has been changed to contain SIP-related attributes.

The store definition classes:

- `FilterImpl`
- `NotificationData`
- `StoreHelper`

and the storage service configuration `wlng-cachestore-config-extensions.xml` is updated to use another store.

Configuration files for the SIP Servlet has been added:

- sip.xml
- web.xml

The build artifacts have been changed to:

- `com.acompany.plugin.example.sip.store_4.0.jar`
- `example_sip_plugin.jar`
- `example_sip.war`

## Configuration Files and Artifacts

The SIP Servlet-defined configuration files for the SIP application is added to `WEB-INF/sip.xml` in `example_sip.war`.

The Java EE standard configuration file for the Web application is added to `WEB-INF/application.xml` in `example_sip.war`.

Both configuration files are found in `$PDS_Home/example/communication_service/example/plugins/sip/config/sip`.

The following artifacts are generated when the plug-in is built:

- `com.acompany.plugin.example.sip.store_4.0.jar`, the store definition for the plug-in.
- `example_sip_plugin.jar`, the plug-in where most of the processing logic takes place.
- `example_sip.war`, the servlet part of the plug-in.

The build artifacts are created in `$PDS_Home/example/communication_service/example/plugins/sip/dist`

The deployable Service Enabler is created when the Communication Service is built. It is packaged in the EAR file `example_enabler.ear` in `$PDS_Home/example/communication_service/example/dis`t.

The store definition JAR file is also generated to this directory.

Note that both the netex plug-in and the SIP plug-in will be packaged in `example_enabler.ear`.

The configuration files:

- alarm.xml
- cdr.xml
- edr.xml

are provided in `$PDS_Home/example/communication_service/example/plugins/sip/config/edr`

Add the contents of these files to Oracle Communications Services Gatekeeper when deploying the Service Enabler.

## Classes

Below is a description of classes that are new or have been changed compared to the netex plug-in described in Communication Service Example.

### ExampleServlet

Package: com.acompany.plugin.example.sip.servlet

Extends javax.servlet.sip.SipServle

The SIP Servlet part of the plug-in. Uses ExampleSipHelper to manage network-triggered requests.

#### public void init()

Initialization for the SIP Servlet.

Calls init() on ExampleSipHelper and provides the ServletContext to ExampleSipHelper.

#### protected void doMessage()

Handles network-initiated SIP messages.

Returns a SIP 200 OK Response to the network.

Extracts the to and from URIs, and the content of the SIP message and calls notifyCallbacks with these parameters on ExampleSipHelper.

### ExampleSipHelper

Package: com.acompany.plugin.example.sip

Singleton class that holds the SIPFactory, the SipSessionsUtil, and list of plug-in instances that can be used to process network-triggered messages.

#### public void init(ServletContext servletContext)

Initialization for ExampleSipHelper.

Called by ExampleSIPServlet, when it is being deployed.

Fetches the SipFactory and the SipSessionsUtil from the ServletContext and stores them in member variables.

#### public SipSessionsUtil getSessionsUtil()

Get method for SipSessionsUtil.

#### public SipFactory getSipFactory()

Get method for SipFactory.

#### public synchronized void registerCallback(NetworkCallback callback)

Called by the plug-in instance when it is being activated. Registers NotificationHandlerSouth in ExampleSipHelper. NotificationHandlerSouth is responsible for processing of network-triggered requests.

#### public synchronized void unregisterCallback(NetworkCallback callback)

Called by the plug-in instance when it is being deactivated. Unregisters NotificationHandlerSouth from ExampleSipHelper.

#### public synchronized void notifyCallbacks(String fromAddress, String toAddress, String message)

Called by ExampleSipHelper when a network-triggered SIP message arrives.

Resolves a plug-in instance to deliver a network-triggered request to. Since all plug-in instances register their own instance of NotificationHandlerSouth, there are as many possible plug-in instances to use as there are plug-in instances. In the example, only one instance is picked since they all have the same logic and access to the same notification data.

An alternative way to implement it is to call all instances. The notification data in the store may or may not be shared among plug-in instances. It is up to the designer of the plug-in to decide which pattern to use. If the notification data is tied to the plug-in instance, the alternatives are to call all plug-in instances or to establish communication channels between the different plug-in instances in order to resolve which instance that shall be targeted for the request.

### SendDataPluginSouth

Class.

Implements PluginSouth.

#### public SendDataPluginSouth()

Constructor.

Empty.

#### public void send(String address, String data)

Sends data to the SIP network.

Creates a SipApplicationSession and a SipServletRequest and sends the request to the SIP network.

The SipServletRequest is created as a SIP Message, with the From: address set to identify Oracle Communications Services Gatekeeper, and the To: address to the address provided by the application.

The content of the SIP message contains the SIP Proxy URI fetched from the configuration store.

The method is annotated with @Edr.

#### public String resolveAppInstanceGroupdId(ContextMapperInfo info)

Empty implementation that returns null. This method has meaning, and is used, only in network-triggered requests.

The application instance ID is already known in the RequestContext, since the class only handles application-initiated requests.

#### public void prepareRequestContext(RequestContext ctx, ContextMapperInfo info))

From interface com.bea.wlcp.wlng.api.plugin.PluginSouth

Gives the plug-in an opportunity to add additional values to the RequestContext before the application-initiated requests is passed on to public void send(String address, String data).

Empty in this example. Normally all data about the request should be known at this point, so no additional data needs to be set.

### NotificationHandlerSouth

Class.

Implements PluginSouth, NetworkCallback.

#### public NotificationHandlerNorth()

Constructor.

Empty.

#### public void receiveData(@ContextKey(EdrConstants.FIELD_ORIGINATING_ADDRESS) String fromAddress, @ContextKey(EdrConstants.FIELD_DESTINATION_ADDRESS) @MapperInfo(C) String toAddress, String data)

Handles network-triggered requests from ExampleSipHelper.

Generates EDRs, finds the application instance that has subscribed for notifications, and passes on the request to NotificationHandlerNorth.

#### public String resolveAppInstanceGroupdId(ContextMapperInfo info)

Resolves which application instance that has subscribed for notifications that matches the data in the network-triggered request. Use StoreHelper to find the subscription for notifications.

#### public void prepareRequestContext(RequestContext ctx, ContextMapperInfo info))

From interface com.bea.wlcp.wlng.api.plugin.PluginSouth

Empty implementation in this example. Normally all data about the request should be known at this point, so no additional data needs to be set. This method has meaning, and is used, only in network-triggered requests.

Gives the plug-in an opportunity to add additional values to the RequestContext before the network-triggered requests are passed on to NotificationHandlerNorth...

### ExampleMBean

Interface.

Management interface.

It defines the following methods:

- public void setProxyURI(String uri) throws ManagementException;
- public String getProxyURI() throws ManagementException;

Implemented by ExampleMBeanImpl.

Stores the URI to the SIP proxy to send application-initiated requests to in the configuration store for the plug-in instance.

All MBean methods should throw com.bea.wlcp.wlng.api.management.ManagementException or a subclass thereof if the management operation fails.

## SLA

The SLA is on Communication Service level and identical to the one for the example Communication Service, see Communication Service Example.