Simple JTAPI Applet – CISCO Implementation

JTAPI is a Java library intended to ensure communication between a Java client and a CTI server. There are many implementations of JTAPI, proprietary(AVAYA, CISCO,…) and open source(GJTAPI, XTAPI). I’ve been working on an Applet to replace the CISCO IP Communicator. This applet uses the CISCO JTAPI implementation to listen to incoming calls, emit consultation calls and execute a call transfer. A consultation call is a call to a target number (B) started by an agent while receiving another call from source (A). The active call from A is switched to “waiting mode” (listening to some music on the wait tone). The agent has the possibility to join source A to target B without listening to their conversation (not a conference).

To achieve this task, I’ve been reading the JTAPI developer guide. The test platform preparation is not discussed in this post. Two common problems to solve to make this applet work correctly: How to make the applet access to local resources(mainly client logging)? How to implement these functions with such a restricted community?

To enable the applet interaction with client local resources, I implemented a test one. the applet looks like :

<applet id="sph" code=""
archive="miniphone.jar,jtapi.jar,log4j.jar" />


The miniphone.jar holds my implementation of the applet (, “jtapi.jar” is the cisco JTAPI implementation and “log4j.jar” is the default logging library for CISCO JTAPI. Note that this applet also interacts with an SWF (the main application) via some JS code. To avoid paths problems, I moved those libraries to the root context of my application under the server.

To execute the applet in IE for example, you have first of all to sign you jar with a valid certificate (using jarsigner tool from the default JDK installation bin). You will have to update your browser plugin  to the latest java release. Next, you have to trust your host in the java configuration panel.

Trust Server

To manage logging params in JTAPI, use the given CISCO tool(Cisco Unified Communications Manager JTAPI Preferences). You need also to place the jtapi.ini side by side with jtapi.jar. If this file is not generated during installation process, use the following command:

java CiscoJtapiVersion -parms

Then you can manage logging properties. It is useful to enable all traces for tests for easier troubleshooting.

2014-12-04_1514Logging management












In the Log Destination tab, I used “c:\TEMP\” as logging path. This will create a rolling file where every action of the JTAPI is logged. You can also use the client java console as an output. An interesting tip here, is how to print an exception stack trace into a given text box for example (inConsole is an AWT TextField in this snippet).

  StringWriter sw = new StringWriter();
  PrintWriter ps = new PrintWriter(sw);

One more thing to add in the user home to enable the applet write in a local directory: Create a file called “.java.policy” in the user home dir, and assign wanted rights to your source server:

grant codeBase "http://localhost:8080/ctiapp/*" {
  permission "C:\\TEMP\\*", "read";
grant codeBase "http://localhost:8080/ctiapp/*" {
  permission "C:\\TEMP\\*", "write";

Now, as soon as I went to my applet web page,  IE asked me to accept this “hazardous” applet:

Applet warning signed jar

So, I’m done with the first problem. Let’s now focus on the JTAPI implementation.

First of all, we need a valid CUCM server with valid credentials. We have to implement the ProviderObserver interface with its providerChangedEvent (aProviderObserverImpl).

public void providerChangedEvent ( ProvEv [] eventList ) {
if ( eventList != null ) {
for ( int i = 0; i < eventList.length; i++ )
if ( eventList[i] instanceof ProvInServiceEv )

conditionInService.set ();

Then, we try to connect the applet to the CUCM (providerName=CUCM IP; Login=cucem username; passwd=cucm password):

 Provider provider;
 JtapiPeer peer = JtapiPeerFactory.getJtapiPeer ( null );
 String providerString = providerName + ";login=" + login + ";passwd=" + passwd; "INFCTI101 Trying to reach provider[Connection String :" + providerString + "]" );
 provider = peer.getProvider ( providerString );
 provider.addObserver ( aProviderObserverImpl);
 conditionInService.waitTrue ();

Next, we need to implement the CallObserver interface to listen to call events.

protected final void metaEvent ( CallEv [] eventList ) {
 //"INFCTI100 Received a CallEv array event - Length = "+eventList.length);
 for ( int i = 0; i < eventList.length; i++ ) {
 TerminalConnection tc = null;
 try {
 CallEv curEv = eventList[i];
 //"INFCTI101 Processing event item : "+i);
 if ( curEv instanceof CallCtlTermConnRingingEv ) {
 //"INFCTI102 Event type is : CallCtlTermConnRingingEv.");
 tc = ((CallCtlTermConnRingingEv)curEv).getTerminalConnection ();
 //"INFCTI103 CTI connection is : "+(tc!=null?tc.getState():"null"));
 tc.answer ();
 //"INFCTI104 Agent answered the call....");
 }else if (curEv instanceof CallControlCall) {
 CallControlCall ccc = (CallControlCall)curEv.getCall();
 String callerName = ccc.getCallingAddress().getName();
 System.out.println("Received a call from "+callerName);
 //"INFCTI105 Event type is : CallControlCall. Caller =["+callerName+"]");
 catch ( Exception e ) {
//redirect the e.printstacktrace to a textField for example

//still a draft…


About Salem Ben Afia

Big Data & Java developer

Posted on December 4, 2014, in Web and tagged , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: