Cisco Unified Application Environment Application Developer Getting Started Guide
Building Language-Agnostic Containerless Applications
Downloads: This chapterpdf (PDF - 235.0KB) The complete bookPDF (PDF - 2.93MB) | Feedback

Building Etch-Based Applications

Table Of Contents

Building Etch-Based Applications

Understanding the Example Application

Creating the MakeCall Application

Declaring Services

Building the Application

Creating Configuration Items

Writing Application Code

MakeCall in Java

MakeCall in C#

Registering the Application

Packaging the Application

Installing the Application

Configuring the Application in the Cisco Unified Application Environment Administration

Running the Application


Building Etch-Based Applications


This chapter guides you through creating and building a new application using the CUAE command-line tool, Etch tools, and either Java or C#.

This chapter contains the following sections:

Understanding the Example Application

Creating the MakeCall Application

Declaring Services

Building the Application

Creating Configuration Items

Writing Application Code

MakeCall in Java

MakeCall in C#

Registering the Application

Packaging the Application

Installing the Application

Running the Application


Note Chapter 5, "Building the MakeCall Application with the Cisco Unified Application Designer" contains example applications build with the Cisco Unified Application Designer. Additional example applications and articles are available on the Cisco Unified Application Environment wiki.


Understanding the Example Application

The new MakeCall application will do the following:

1. Receive an HTTP Request that triggers an instance of the application.

2. Retrieve a phone number from the management service.

3. Call the phone number:

If the call initiates successfully, sends a response to the user that the intended endpoint should be ringing.

If the call does not initiate successfully, sends a response to the user that contains some common mistakes to check and end the application instance.

4. If the call is successful, plays a message:

If the message plays successfully, hangs up the correct call based on the call ID.

If the message fails to play, hangs up the call and end the application instance.

5. If the call is successful, but the answering party hangs up before the message plays, ends the application instance.

Creating the MakeCall Application

To create the MakeCall example application, follow these steps:

Procedure


Step 1 Create the application project using the CUAE command-line tool:

a. Run the cuae create command.

C:\workspace> cuae create MakeCall

b. Specify whether you are creating an application or plugin.

Project Type? [application or plugin] application

c. Specify the programming language.

Programming language? [java or csharp] java

d. Select the build format.

Build format? [ant or maven2] ant

e. Specify the project namespace.

Project namespace? [default: makecall]  

f. Choose a triggering event. For this example, an HTTP request triggers the application.

Available application triggering event:
  0: Skip this step
  1: cisco.uc.cuae.legacy.JTapi.JTapiIncomingCall
  2: cisco.uc.cuae.legacy.JTapi.JTapiCallInitiated
  3: cisco.uc.cuae.legacy.JTapi.JTapiCallEstablished
  4: cisco.uc.cuae.legacy.CallControl.IncomingCall
  5: cisco.uc.cuae.legacy.Http.GotRequest
  6: cisco.uc.cuae.legacy.Presence.SubscriptionTerminated
  7: cisco.uc.cuae.legacy.Presence.Notify
  8: cisco.uc.cuae.legacy.TimerFacility.TimerFire
Triggering event? [0-8] 5

The CUAE command-line tool generates the project template:

Generating:
   * application named "MakeCall"
   * with namespace "makecall"
   * with language "java"
   * with trigger event "cisco.uc.cuae.legacy.CallControl.Http.GotRequest"
   * in location C:\workspace\MakeCall
Created project "MakeCall" in directory
"C:\workspace\MakeCall\" 


Declaring Services

To declare the services that contain the methods you want to use in your application, follow these steps:

Procedure


Step 1 Open the C:\workspace\MakeCall\MakeCall.etch file in the editor of your choice.

The MakeCall.etch file contains the following code where you can declare services:

// You may add any additional service mixins that you require. For
    // example, if you'd like to make and receive phone calls, add the
    // following line:
    //     mixin cisco.uc.cuae.legacy.CallControl
	mixin cisco.uc.cuae.legacy.Http

This MakeCall application will answer an incoming HTTP request, make a phone call and play a media stream back to the caller. This means that you need to build it using methods from the Http, CallControl, and MediaControl service providers.

The HTTP service is already declared because you selected the HTTP.GotRequest triggering event when initially creating the application.

Step 2 To declare the additional services, append the following two lines to the MakeCall.etch file immediately after the declaration for the Http service provider.

	mixin cisco.uc.cuae.legacy.CallControl
    mixin cisco.uc.cuae.legacy.MediaControl

Note To learn which methods comprise the services provided with Cisco Unified Application Environment, see the API Reference for the version you have installed.



Building the Application

To build the source file templates and create the project structure, follow these steps:

Procedure


Step 1 Depending on the language you selected when creating the application, you need to run one of the following commands to generate source file templates:

ant (Java)

maven2 (Java)

msbuild (C#)

Enter the appropriate command from the project root folder. For example, if you are using ant to build, enter the following command:

C:\workspace\MakeCall> ant

In this case, ant uses the build.xml file to generate the appropriate project structure.

For both C# and Java, building generates two files you will use to write and configure your application logic, which are located in the src\project_name directory:

Impl<ProjectName>Client.<extension>

Main<ProjectName>Client.<extension>


Creating Configuration Items

For the MakeCall application, you must declare two runtime parameters: one for the phone number to call and one for the message to play when the call is answered.

To configure runtime parameters, follow these steps:

Procedure


Step 1 Open the config.yaml file, which is located in the cuae-resources directory.

Step 2 Add the following lines to the file to configure the runtime parameters for the variables you want passed to the application from the Cisco Unified Application Environment Administration interface:

- name: To   
 format: String   
 displayName: To   
 defaultValue: 

- name: TTSMessage   
 format: String   
 displayName: TTSMessage   
 defaultValue: Hello, welcome to answer and play demo application 

Step 3 After any change to the config.yaml file, rebuild your application.

Step 4 Run cuae update, if you have already installed the application, to update the meta data on the Cisco Unified Application Server.


Writing Application Code

You can write your application using Java or C#. This section provides step-by-step code samples in both of these languages for reference purposes:

MakeCall in Java

MakeCall in C#

MakeCall in Java

To build your application using Java, follow these steps:

Procedure


Step 1 Import the project into Eclipse:

a. Open Eclipse

b. Choose File > New > Other > Java Project from Existing Ant File.

c. Click Next.

d. Browse to C:\workspace\MakeCall\ and click the build.xml file.

e. Click Open.

f. Select "javac" task found in target "build[default]".

Step 2 Read the variables into your application:

a. Open the ImplMakeCallClient.java file in Eclipse. The file contains placeholders for your code.

// This file automatically generated by:
//   Etch 1.0.1 (LOCAL-0) / java 1.0.1 (LOCAL-0)
//   Sun Sep 14 18:10:18 CDT 2008
// This file is automatically created for your convenience and will not be
// overwritten once it exists! Please edit this file as necessary to implement
// your service logic.

package makecall;

/**
 * Your custom implementation of BaseMakeCallClient. Add methods here to provide
 * implementations of messages from the server.
 */
public class ImplMakeCallClient extends BaseMakeCallClient
{
	/**
	 * Constructs the ImplMakeCallClient.
	 *
	 * @param server a connection to the server session. Use this to send a
	 * message to the server.
	 */
	public ImplMakeCallClient( RemoteMakeCallServer server )
	{
		this.server = server;
	}
	
	/**
	 * A connection to the server session. Use this to send a
	 * message to the server.
	 */
	@SuppressWarnings( "unused" )
	private final RemoteMakeCallServer server;

	// TODO insert methods here to provide implementations of MakeCallClient
	// messages from the server.
}

b. Add the following two lines to declare variables that control the runtime behavior of the application.

String sTTSMessage;
String sTo;

	 

Step 3 When the gotRequest event occurs, read the runtime parameters. The application receives the current application partition configurations from the Cisco Unified Application Server in the getConfig event handler.


Note The sessionId argument that is that is passed in from the triggering event is a unique ID for the application instance. For information about other method arguments, see the API reference for the version of Cisco Unified Application Environment you have installed.


@Override
public void gotRequest(String sessionId, GotRequestOptions options) 
{
	 
	try {
			ConfigEntry[] configs = server.getConfig("Default");
         			if ( configs == null || configs.length == 0 )   
           			 return;   
              
         try  
         {   
              for ( int i=0; i<configs.length; i++ )   
              {   
                  if ( configs[ i ].name.matches("TTSMessage"))   
                    sTTSMessage = configs[ i ].configValue.toString();
                  else if ( configs[ i ].name.matches("To"))
                        sTo = configs[ i ].configValue.toString();  
              }   
          }   
          catch ( Exception e )   
          {   
              System.out.println( "Error reading application configs: " + 
e.getMessage());
           }             
       }
       catch (Exception e)
       {
            System.out.println( "Error calling server.getConfig: " + e.getMessage());
       }

Step 4 Make a phone call to the number passed into the To global variable you defined in Step 2.

		MakeCallResult mcr = server.beginMakeCall(sessionId, sTo, "", null, null, 
null);

Note This sample uses the beginMakeCall asynchronous method to start the example logic immediately after the MakeCall logic on the server begins, rather than waiting for the call to be answered and complete. You can optionally use the synchronous version of the method, MakeCall.


Step 5 If the call initiates successfully, send a text response (SendResponse) to the remote host that the intended endpoint should be ringing and print a message to the console that the MakeCall action was successful:

		
		if (mcr.returnValue == CuaeResult.SUCCESS)    	
		  {
			  	String body = "The call was initiated successfully. If the specified 
endpoint does not ring, check the Application Server log for errors.";       	    	    	    
			  	server.sendResponse(sessionId, options.remoteHost, 200, "text/plain", 
body, "OK", null);
				System.out.println("MakeCall Passed");
			 	return;

Step 6 If the call does not initiate successfully, send a response to the remote host, print a message to the console, and end the application instance:

		  }	else {
			  	
			  	String body = "The call was not initiated successfully.";       	    	    	
    
			  	server.sendResponse(sessionId, options.remoteHost, 200, "text/plain", 
body, "OK", null);
				System.out.println("MakeCall Failed");
			    server.removeCuaeSession(sessionId);
			    return;		 
		  }
	} 

Step 7 If the call completes, play the message defined by the TTSMessage global variable you defined in Step 2. If the beginPlay method does not succeed, print a message to the console and use the callId result parameter from the onMakeCallComplete method to hang up the correct call:

@Override
	public void onMakeCallComplete(String sessionId, MakeCallResult results, Object 
state) {
		
		  System.out.println("\nMakeCall completed..");	
		  System.out.println("\nBegin play..");
			    
		  // Play prompt in non-blocking fashion, pass in AnswerCallResult as state 
info  
		  if (server.beginPlay(sessionId, sTTSMessage, results.connectionId, null, 
null, null).returnValue != CuaeResult.SUCCESS)        	
		  {
			  System.out.println("beginPlay failed");
			  server.hangup(sessionId, results.callId, null);
			  server.removeCuaeSession(sessionId);
		  }
	}

Step 8 If the message plays successfully, hang up the correct call based on the call ID:

@Override
	public void onPlayComplete(String sessionId, PlayResult results, Object state) 
	{
	  System.out.println("\nPlay completed..");
		        
	  String callId = (String)state;
		    
	  System.out.println("\nHangup..");
	  if (server.hangup(sessionId, callId, null).returnValue != CuaeResult.SUCCESS)
	    System.out.println("Hangup failed");
	    
	  System.out.println("\nEndScript");
	  server.removeCuaeSession(sessionId);

Step 9 If the call is successful, but the answering party hangs up before the message finishes playing, end the application instance:

public void remoteHangup(String sessionId,RemoteHangupOptions options)
{
server.removeCuaeSession(sessionId);
}

Step 10 Handle default incoming events. The Cisco Unified Application Server generates these events to indicate significant changes to the state of the audio associated with this call. For this example, these events are merely informative and not needed for any pertinent logic. It is recommended that you add the following empty functions to handle the incoming events, to avoid unnecessary warnings:

@Override
public void startTx(String sessionId,StartTxOptions options)
	{        	        	
	}

@Override
public void stopTx(String sessionId,StopTxOptions options)
	{        	        	
	}	

@Override
public void startRx(String sessionId,StartRxOptions options)
	{        	        	
	}

MakeCall in C#

To build your application using C#, follow these steps:

Procedure


Step 1 Double-click the ProjectName.csproj file to open it in VisualStudio.

Step 2 Choose Build > Build Solution to build the project in VisualStudio and create a solution (.sln) file.

Step 3 Read the variables into your application:

a. Open the ImplMakeCallClient.cs file in VisualStudio. The file contains placeholders for your code.

// This file automatically generated by:
//   0.95.0 (ETCH-TRUNK-884) / csharp 0.95.0 (ETCH-TRUNK-884)
//   Mon Jun 23 11:44:14 CDT 2008

using System;


using cisco.uc.cuae.types.EtchBridge;
using cisco.uc.cuae.legacy.types.Http;

using makecall.types.MakeCall;

///<summary>Your custom implementation of BaseMakeCallClient. Add methods here to 
provide
///implementation of messages from the server. </summary>
namespace makecall
{
	///<summary>Implementation for ImplMakeCallClient</summary>
	public class ImplMakeCallClient : BaseMakeCallClient
	{
		/// <summary>Constructs the ImplMakeCallClient.</summary>
 		/// <param name="server">a connection to the server session. Use this to
 		/// send a message to the server.</param>
		public ImplMakeCallClient(RemoteMakeCallServer server)
		{
			this.server = server;
		}
		
		/// <summary>A connection to the server session. Use this to
 		/// send a message to the server.</summary>
		private readonly RemoteMakeCallServer server;
	
		// TODO: Implement delegates or provide implementation of MakeCallClient
		// messages from the server					
	}
} 

b. Add the following strings to the parent class to create global variables for the runtime parameters:

String sTTSMessage;
String sTo;

	 

Step 4 When the gotRequest event occurs, read the runtime parameters. The application receives the current application partition configurations from the Cisco Unified Application Server in the getConfig event handler:


Note The sessionId argument that is passed in from the triggering event is a unique ID for the application instance. For information about other method arguments, see the API reference for the version of Cisco Unified Application Environment you have installed.


          public override void gotRequest(string sessionId, GotRequestOptions options)
        {
            //base.gotRequest(sessionId, options);

            ConfigEntry[] configs = server.getConfig("Default");

            if (configs == null || configs.length == 0)
                return;

            try
            {
                for (int i=0; i<configs.length; i++)
                {
                    if (configs[i].name.matches("TTSMessage"))
                        sTTSMessage = configs[i].configValue.toString();
                    else if (configs[i].name.matches("To"))
                        sTo = configs[i].configValue.toString();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error reading application configs: " + 
e.getMessage());
            }

Step 5 Make a phone call to the number passed into the To global variable you defined in Step 2:

MakeCallResult smcr = server.beginMakeCall(sessionId, sTo, " ", null, null, null);

Note This example uses the beginMakeCall asynchronous method to start the example logic immediately after the MakeCall logic on the server begins, rather than waiting for the call to be answered and complete. You can optionally use the synchronous version of the method, MakeCall.


Step 6 If the call initiates successfully, send a text response (SendResponse) to the remote host that the intended endpoint should be ringing and print a message to the console that the MakeCall action was successful:

		if (smcr.returnValue == CuaeResult.SUCCESS)
            {
                String body = "The call was initiated successfully. If the specified 
endpoint does not ring, check the Application Server log for errors.";
                SendResponseResult srr = server.sendResponse(sessionId, 
options.remoteHost, 200, "text/plain", body, "OK", null);
                Console.WriteLine("MakeCall Passed.");
                return; 

Step 7 If the call does not initiate successfully, send a response to the remote host, print a message to the console, and end the application instance:

}
else
{
    String body = "The call was not initiated successfully.";
    SendResponseResult srr = server.sendResponse(sessionId, options.remoteHost, 200, 	 
    "text/plain", body, "OK", null);
    Console.WriteLine("MakeCall Failed");
    server.removeCuaeSession(sessionId);
    return;
 }
}		 

Step 8 If the call completes, play the message defined by the TTSMessage global variable you defined in Step 2. If the beginPlay method does not succeed, print a message to the console and use the callId result parameter from the onMakeCallComplete method to hang up the correct call:

public override void onMakeCallComplete(String sessionId, MakeCallResult results, 
Object state) {
            
              Console.WriteLine("\nMakeCall completed..");  
              Console.WriteLine("\nBegin play..");
                      
              // Play prompt in non-blocking fashion, pass in AnswerCallResult as 
state info  
              if (server.beginPlay(sessionId, sTTSMessage, results.connectionId, null, 
null, null).returnValue != CuaeResult.SUCCESS)              
              {
              Console.WriteLine("beginPlay failed");
                    server.hangup(sessionId, results.callId, null);
                    server.removeCuaeSession(sessionId);
              }
      }

Step 9 If the message plays successfully, hang up the correct call based on the call ID:

    public override void onPlayComplete(String sessionId, PlayResult results, Object 
state) 
      {
        Console.WriteLine("\nPlay completed..");
                    
        String callId = (String)state;
                
        Console.WriteLine("\nHangup..");
        if (server.hangup(sessionId, callId, null).returnValue != CuaeResult.SUCCESS)
          Console.WriteLine("Hangup failed");

      Console.WriteLine("\nEndScript");
        server.endCuaeScript(sessionId); 
} 
        

Step 10 If the call is successful, but the answering party hangs up before the message finishes playing, end the application instance:

public override void remoteHangup(String sessionId,RemoteHangupOptions options)
{
server.removeCuaeSession(sessionId);
}

Step 11 Handle default incoming events.

The following events are related to establishing and receiving audio channels. The Cisco Unified Application Server generates these events to indicate significant changes to the state of the audio associated with this call. For this example, these events are merely informative and not needed for any pertinent logic. It is recommended that you add the following empty functions to handle the incoming events, to avoid unnecessary warnings:

public override void startTx(String sessionId,StartTxOptions options)
	{        	        	
	}

public override void stopTx(String sessionId,StopTxOptions options)
	{        	        	
	}	

public override void startRx(String sessionId,StartRxOptions options)
	{        	        	
	}

Registering the Application

In the previous steps, you completed the core logic of the example application. However, before any Etch-based API calls can actually be made, you must register your application with the Cisco Unified Application Server.

To register your application, follow these steps:

Procedure


Step 1 Open the MainMakeCallClient.java or MainMakeCallClient.cs file (depending on the language you are using) in the /src directory. It contains the following content by default:

// Generated by:
// 0.95.0 (ETCH-TRUNK-840) / java 0.95.0 (ETCH-TRUNK-840)
// Sun Jun 08 22:47:33 CDT 2008

package makecall;

/**
 * Main program for MakeCallClient. This program makes a connection to the
 * listener created by MainMakeCallListener.
 */
public class MainMakeCallClient implements MakeCallHelper.MakeCallClientFactory
{
	/**
	 * Main program for MakeCallClient.
	 * 
	 * @param args command line arguments.
	 * @throws Exception
	 */
	public static void main( String[] args ) throws Exception
	{
		// TODO Change to correct URI
		String uri = "tcp://localhost:4001";
		
		RemoteMakeCallServer server = MakeCallHelper.newServer( uri, null,
			new MainMakeCallClient() );

		// Connect to the service
		server._startAndWaitUp( 4000 );

		// TODO Insert Your Code Here

		// Disconnect from the service
		server._stopAndWaitDown( 4000 );
	}

	public MakeCallClient newMakeCallClient( RemoteMakeCallServer server )
		throws Exception
	{
		return new ImplMakeCallClient( server );
	}
}

Step 2 To make a connection to the listener, add a server.registerApplication() request:

		// TODO Insert Your Code Here
		String key = server.registerApplication("MakeCall", "Default", "Username", 
"password");
		System.out.println("ShyHttpApplication is registered: " + key);
		System.in.read();

Step 3 Modify the String URI to match the IP address and port of the Cisco Unified Application Server:

		// TODO Change to correct URI
		String uri = 
      "tls://appserver_ipaddress:9000?TlsConnection.authReqd=false&filter=KeepAlive";

Note The above URI sets the connection protocol to TLS, which is on by default on the Etch Bridge. TlsConnection.authReqd=false disables TLS authentication. The KeepAlive filter is necessary to ensure that the Etch Bridge periodically checks the health of the client-server connection and resets it if it is not responsive. For more information about the connection string URI options, see the Cisco Unified Application Environment wiki at this URL: http://developer.cisco.com/web/cuae/wikidocs.




Packaging the Application

To package your application, follow these steps:

Procedure


Step 1 Execute a successful build request for your test application within your IDE.

Step 2 Execute the cuae package command from a DOS command shell in the parent directory of the test application.

C:\workspace\MakeCall> cuae package

The following files are created in the "\bin" sub-directory:

projectname_language_extension.mca—application bundle to be uploaded into the Cisco Unified Application Server.

INSTALLER.xml—Contains the configuration items in config.yaml.

MANIFEST.xml—Contains bundle details for the package command.


Installing the Application

To install your application, follow these steps:

Procedure


Step 1 Execute the cuae install command from a DOS command shell in the test application parent directory of the test application:

C:\workspace\MakeCall> cuae install

Step 2 Enter the Management Service IP address.

Enter the hostname or IP address of the management service (for example: localhost, 
1.1.1.1): appserver_ipaddress 

Step 3 Enter the connection protocol. For this example, the Etch Bridge has TLS enabled by default.

Protocol? [tcp or tls] tls 

Step 4 The tool displays the connection URI it generated from your entries.

Generated mgmt-service uri:
tls://appserver_ipaddress:9001?Packetizer.maxPktSize=0&TlsConnection.authReqd=false 

Step 5 Enter the Management Service username and password.

Enter management service login username: username
Enter management service login password: password 

Step 6 When prompted, enter yes or no to save management settings. This saves the answers to the above questions in the properties file for future installs.

Save the management settings with the project? [yes or no] no 


Note To view the command-line help, run the cuae install -h command.



Configuring the Application in the Cisco Unified Application Environment Administration

In this step, you must provide values for the configuration items you added in the "Creating Configuration Items" section. You must also configure the application to recognize URIs that trigger this application.

To add values, follow these steps:

Procedure


Step 1 Open the Cisco Unified Application Environment Administration URL by entering: http://<serverIPaddress>/cuaeadmin.

The Cisco Unified Application Environment Administration Login Screen opens.

Step 2 Enter the username administrator, and the password, then click Log In.

Step 3 Choose Applications > Find/List Applications in the global navigation.

The list of all applications appears.

Step 4 Select the MakeCall application from the list.

The Application Details page appears.

Step 5 Modify the To field to contain the phone number to call when the application is triggered.

Step 6 Modify the TTSMessage field to contain the text to speak when the message is played.

Step 7 Choose Applications > Find/List Triggers in the global navigation.

The list of all application trigger appears.

Step 8 Select the MakeCall application from the list.

The Trigger Details page appears.

Step 9 Modify the url trigger to a contain a value to distinguish HTTP requests with a particular URL from other HTTP requests sent to the application server. You will append this string after the application server IP address and port in the triggering URL. Figure 6-1 shows a properly configured Trigger Details page.

Step 10 Click Done.

Figure 6-1 Trigger Details Page


Running the Application

To run the example MakeCall application, follow these steps:

Procedure


Step 1 Execute your application. This registers the application with the Cisco Unified Application Server and changes its status to Enabled_Running.

Step 2 Open a web browser and enter the URL to the Cisco Unified Application Server with the trigger you assigned to the application in the "Configuring the Application in the Cisco Unified Application Environment Administration" section.

If the call initiates successfully, a message is displayed in the web browser, as shown in Figure 6-2, the phone you configured rings and when answered, plays a message.

Figure 6-2 Testing the MakeCall Application


Note If the test does not work, check the server logs for any errors. See the Cisco Unified Application Environment Administration Guide for more information about logging.