Build Your Own UA App

Create a WAR (or SIP application) with SIP Servlet and javax/javaee dependencies.

Create a SIP Servlet Application

  1. Create a SIP Servlet application packaged as a WAR (or SIP application archive) and include the SIP Servlet API dependencies required by your project.
  2. Add mediagateway-api and ags-impl to your project dependencies.
  3. Add sip.xml and, if needed, web.xml.
  4. If you do not want time-based session expiration, set session-timeout to 0.
<dependency>
    <groupId>oracle.occas</groupId>
    <artifactId>mediagateway-api</artifactId>
    <version>8.3.0.0.0</version>
</dependency>
<dependency>
    <groupId>oracle.occas</groupId>
    <artifactId>ags-impl</artifactId>
    <version>8.3.0.0.0</version>
</dependency>

Obtain the API Instances

  1. In your SIP servlet (or a service class), obtain both factory instances and their API objects.
    // Media Gateway
    MediaFactory mediaFactory = MediaFactory.getInstance();
    MediaGatewayServiceApi mediaApi = mediaFactory.createMediaGatewayServiceApi();
    
    // AI Gateway
    AIGatewayServiceFactory aiFactory = AIGatewayServiceFactory.getInstance();
    AIGatewayService aiApi = aiFactory.createAIGatewayService();
  2. Optional: Create a small application wrapper (for example, a MediaGatewayClient and AIUdpClient interface and implementation) so the rest of the application does not depend directly on MGS or AGS API types.

Map INVITEs to CreateMediaRequest

When you receive an INVITE that contains SDP, parse the SDP and metadata if present. For each media line you want to handle:
  1. Extract the call ID, stream ID, media type, direction, source IP, source port, and codecs.
  2. Create the STT session first via AGS to obtain the egress destination IP and UDP port for audio routing.
  3. Use the AIGatewayServiceFactory builders to construct the CreateAISessionRequest and call createSTTSession. Validate the response and read udpPort and incomingMediaIP from AISessionDetails.
  4. Use the egress IP and port from the AGS response as the egress destination in the EgressMediaStream.
  5. Use the MediaFactory builders to construct the Identifiers, OfferedSDP, IngressMediaStream, and EgressMediaStream.
  6. Build the CreateMediaRequest with one ingress and one egress stream.

You must set the call ID, stream ID, participant ID, session ID, and stream direction. This information is used to add metadata and headers for each egress UDP packet.

// Step 1 — Get WebSocket URL and create STT session
String wsUrl = aiApi.getWebSocketUrl(callId, participantId);

CreateAISessionRequest aiReq = aiFactory.createAISessionRequestBuilder()
    .callId(callId)
    .participantId(participantId)
    .participantName(participantName)
    .provider("oci")
    .headerSize(appConfig.getHeaderSize())
    .metaData(metaData)
    .build();

if (wsUrl != null) {
    aiReq.setExternalEndpoint(wsUrl);
}

AISessionResponse aiResp = aiApi.createSTTSession(aiReq);

// Step 2 — Validate AGS response
if (aiResp == null
        || aiResp.getSessionState() == null
        || "ERROR".equalsIgnoreCase(aiResp.getSessionState().name())
        || aiResp.getAiSessionDetails() == null
        || aiResp.getAiSessionDetails().getUdpPort() == null) {
    // trigger cleanup and return error
    return;
}

String egressIp   = aiResp.getAiSessionDetails().getIncomingMediaIP();
Integer egressPort = aiResp.getAiSessionDetails().getUdpPort();

// Step 3 — Create media session using AGS egress IP and port
CreateMediaRequest mediaReq = mediaFactory.createCreateMediaRequestBuilder()
    .callId(callId)
    .mediaSessionPurpose(MediaSessionPurpose.EXTERNAL_STREAM)
    .addIngressMediaStream(ingressStream)
    .addEgressMediaStream(egressStream)  // egressStream uses egressIp and egressPort from AGS
    .build();

Response mediaResp = mediaApi.createMediaSession(mediaReq);

Store session IDs and link to SIP dialog

  1. Store mediaSessionId and aiSessionId in your application call state, keyed by Call-ID and stream/label.
  2. If you use a MediaSessionErrorListener, register a mapping from mediaSessionId to SipSession (or dialog ID). This enables your application to correlate Media Gateway errors to the correct SIP dialog and trigger cleanup (including deleting both the media session and the STT session) for errors.

A listener dependency example:

<dependency>
  <groupId>oracle.occas</groupId>
  <artifactId>wlssapi</artifactId>
  <version>8.3.0.0.0</version>
</dependency>

To register the listener:

<!-- WEB-INF/sip.xml -->
<listener>
    <javaee:listener-class>
        com.oracle.occas.app.listener.MediaSessionErrorListenerImpl
    </javaee:listener-class>
</listener>

Handle re-INVITEs

If the caller sends a re-INVITE with SDP changes, update both the media session and the STT session:

// Update STT session
ModifyAISessionRequest modAiReq = aiFactory.modifyAISessionRequestBuilder()
    .metaData(metaDataUpdate)
    .build();

modAiResp = aiApi.updateSTTSession(aiSessionId, modAiReq);
aiApi.updateSTTSession(aiSessionId, modAiReq);

Use the responses to update your call state and build the 200 OK SDP.

Handle the BYE or CANEL

When the call ends, tear down both sessions for each call. Always delete the STT session alongside the media session to avoid resource leaks on the AGS side.
// Delete media session
MediaSessionActionRequest actionReq = mediaFactory.createMediaSessionActionRequestBuilder()
    .reason("BYE")
    .build();
mediaApi.deleteMediaSession(mediaSessionId, actionReq);
// Delete STT session
aiApi.deleteSTTSession(aiSessionId);
For CANCEL, send 487 as appropriate and follow the same cleanup sequence.

Deactivate

You can deactivate the media session without deleting it — for example, on call hold. The STT session transitions to PAUSED state and can be resumed via updateSTTSession.
mediaApi.deactivateMediaSession(mediaSessionId, actionRequest);

The actionRequest should carry the reason (for example, "call hold").

Deploy and Configure

Assuming you have set up and configured the Media Flow Engines, RTP Proxies, and IACs as documented in the Intelligent Media Connector Guide, the last step is to deploy your WAR or SIP application.