Please login or register to access secure site features.

Note: By continuing to use DevConnect Program Services you agree to our latest Registered Member Terms.

Sign in using DevConnect ID

Forgot password?

Trouble logging in?

Submit a ticket for Registration Support.

I have an SSO ID

?
sign in

Don't have a DevConnect or SSO ID ?

Create a DevConnect account or join the program.

register now
^

FAQ: Application Enablement Services

See All Content
X

FAQ: JTAPI

Programming

What are the basic steps to develop a JTAPI application?

The following list describes the basic steps that are common to virtually all JTAPI applications.

  • Obtain a JtapiPeer object using the JtapiPeerFactory class. For example:
    The TsapiPeer class, com.avaya.jtapi.tsapi.TsapiPeer, represents the Avaya JTAPI implementation.
    jtapiPeer = JtapiPeerFactory.getJtapiPeer("com.avaya.jtapi.tsapi.TsapiPeer")
  • Obtain a list of available tlinks by using the getServices() method of the JtapiPeer class. For example:
    String[ ] tlinks = jtapiPeer.getServices();
  • Obtain a Provider object using the getProvider() method of the TsapiPeer class. Specify the aeserver tlink name and aeserver login and password, for example:
    provider = tsapiPeer.getProvider("avaya#cstaserv#csta#aeserver;" + "login=user1;" + "passwd=user1pass;")
    where
    • avaya#cstaserv#csta#aeserver is the tlink name
    • aeserver is the name of the AE Services server (AE Server) that is running the JTAPI Service.
    • login and passwd refer to the authentication login and password.

What are call objects in the JTAPI Call Model?

Provider Object

The Provider object is an abstraction of telephony service-provider software. A Provider hides the service-specific aspects of the telephony subsystem and enables Java applications and applets to interact with the telephony subsystem in a device-independent manner.

Call Object

The Call object represents a telephone call, the information flowing between the service provider and the call participants.

Address Object

The Address object represents a telephone number. It is an abstraction for the logical endpoint of a telephone call.

Connection Object

A Connection object models the communication link between a Call object and an Address object.

Terminal Object

The Terminal object represents a physical device such as a telephone and its associated properties.

TerminalConnection Object

TerminalConnection objects model the relationship between a Connection and the physical endpoint of a Call, which is represented by the Terminal object.

Passing getJtapiPeer() a NULL and it is throwing an exception that says "Can not instantiate DefaultJtapiPeer". What is the reason behind the JTAPI Peer instantiation failure?

This may be because the JTAPI application has some classes that are not part of a "package" and thus have no path in an archive file such as a JAR, ZIP, or CAB file. The DefaultJtapiPeer class must exist in the ECSJTAPI archive files outside of the Avaya package. (This is forced by the JTAPI design specification). Some instances virtual machines cannot recognize classes without a package when multiple archive files are involved. This winds up being DefaultJtapiPeer and can cause this exception.

What is the difference between Listners and Observers?

Prior to JTAPI release 1.3, the Java observer/observable model was the pattern that JTAPI applications could follow to receive events from a JTAPI implementation using the JTAPI API.

With JTAPI releases 1.3 (packages Core, Media, Mobile) and 1.4 (packages Callcontrol, Callcenter, Phone, Private), applications could transition to using an event delivery scheme based in spirit on the Java 1.1 delegation-based event model (or "Listener model"). JTAPI releases 1.3 and 1.4 also include the Observer methods and events, but deprecate them.

When is the reason the method addAddressObserver on Address object throws an exception: com.avaya.jtapi.tsapi.TsapiResourceUnavailableException ?

CSTA Error 41 relates to 'SUBSCRIBED RESOURCE AVAILABILITY'. CTI login that is used for the login may not have the necessary privileges. Check on AE Server, in the CTI Users -> List All Users' page; check that application login credential has right privileges.

In JTAPI, when an agent is already logged in, why is their state not set to the initial state passed in to AgentTerminal.addAgent(..)?

AgentTerminal.addAgent() should only be used when the agent is not logged in. Calling addAgent() when the agent is already logged in should fail and do nothing to the agents state. Developers should use setState() if the agent is already logged on and wish to change the agent's state.

In JTAPI, after adding an observer to the AgentTerminal why are no subsequent events on agent state changes received?

Agent state changes are not observed on an AgentTerminal object. To get these, the observer should be placed on the ACDaddress object. The only state changes reported are log-on and log-off.

How can one get the user-entered DTMF digits from RouteEvent?

public void routeEvent(RouteEvent event) {
LucentCallInfo xyz : (LucentCallInfo)event.getRouteSession();
UserEnteredCode d = xyz.getUserEnteredCode() ;
System.out.println('Entered Digits ['+d.getDigits()+']');
}

How can one send UUI information in the context of adjunct routing?

public void routeEvent(RouteEvent event) {
LucentRouteSession xyz : (LucentRouteSession)event.getRouteSession();
UserToUserInfo d = new UserToUserInfo(?MY user to user data?);
xyz.selectRoute(routeSelected, false, d);
}

How can one get trunk information from CallActiveEv event?

LucentCall call = (LucentCall) ((CallEv) event).getCall();
ACDAddress acdAddress = call.getDeliveringACDAddress();
String trunk = ((LucentCallInfo) call).getTrunk();

How to get trunk statistics from the switch?

Provider provider = jtapiPeer.getProvider( providerString );

If(provider instanceOf LucentProvider) {
TrunkGroupInfo tgi = ((LucentProvider)provider).getTrunkGroupInfo(trunkAccessCode);
System.out.println("Number of Idle trunks ["+ tgi.idleTrunks +"] Number of in-use Trunks ["+tgi.usedTrunks+"]");
}

Does Java Telephony API (JTAPI) SDK support "CallCenterCall.setApplicationData" and "CallCenterCall.getApplicationData" methods?

Avaya's JTAPI implementation doesn't support "setApplicationData" and "getApplicationData" methods of "CallCenterCall". One way of achieving this is to pass a key in the "UserToUserInfo" and perform a database query to get the necessary data.

How do I monitor call queue status for an ACD or hunt group using JTAPI?

First ensure that security database is enabled on AES simulator and the ACD/ hunt group is added as an ACD device in the device list.

To monitor a hunt-group or ACD, associated hunt-group need to be modified. Use 'change hunt-group' command, and set or select the check box for ACD.

Once you have completed the first task, follow these steps to query status on queue.

  • Call function CallProvider.getAddress(string) where an ACD extension is passed as an input.
  • Check that the returned Address object is an instance of ACDAddress.
  • Call ACDAddress.getNumberQueued();

You may need to create new CTI User login. Follow these steps to add the user:

  • Start the AES OA&M Web page and login with the 'avaya' user.
  • Then select
    User Management --> User Management --> Add User.
  • Set the User Id, Common Name, Surname, User Password and Confirm Password fields. Set CT User to "yes".
  • Submit the form.
Now restart the applicatioon and retry your query.

Does JTAPI support the 'HELD' event?

Yes. The 'CallCtlTermConnHeldEv' interface indicates that the connection is in the 'HELD' state. The call observer class must implement the interface 'CallControlCallObserver' in order to receive this and any other Call Control events.

Is Single Step Conference supported by JTAPI?

Avaya has not implemented 'transfer(String)' method in 'CallControlCall', So, the exception 'com.avaya.jtapi.tsapi.TsapiMethodNotSupportedException: unsupported by implementation' is raised. Use the method 'transfer(Call otherCall)' to achieve a transfer operation. This method moves all participants from one call to another, with the exception of a selected common participant.

What is the maximum (tested) number of monitors/observers that a JTAPI client thread can handle?

Currently, tests are conducted with over 625 simultaneous monitors/observers, where 400 monitors are generated using JTAPI. Full capacity testing is currently done with TSAPI monitors and not with JTAPI.

In JTAPI, how does the application acquire a 'TerminalConnection' object for a dynamic device?

Avaya's implementation of JTAPI does not provide access to the state of the physical endpoint (i.e. Terminal) for 'off switch' parties. Therefore, it is not possible to expose the capabilities that allow the application to query the state of the dynamic device or manipulate it. The 'getTerminalConnection()' API method will return 'null', as there is no 'Terminal' object or 'TerminalConnection' object for 'off switch' parties.

Is it possible to write a Java application for outbound dialing to control an IP Agent interface using AE Services server?

Yes, Java Telephony API (JTAPI) provides the required functionality to accomplish this. The JTAPI interface 'javax.telephony.callcenter.Agent' implements this service. The DMCC Java SDK also provides call control capabilities in release 4.1.

How can my application access agent queue information (e.g.: number of calls in a queue)?

The Avaya JTAPI implementation supports the following requests related to agent queue information:

  1. getNumberQueued (returns the number of calls queued at an ACDAddress)
  2. getLoggedOnAgents (returns the Agents logged into the ACDAddress)
For more details, please refer to the AE Services 4.1 JTAPI Programmer's Reference, available on DevConnect. You can find the programmer's reference by performing a devconnect search on "JTAPI Reference".

How can an application simulate Login/Logout of the Agent using JTAPI? Which object from JTAPI SDK should be used for the simulation?

When an agent is added to a terminal (Agent Terminal), the application can specify the initial state for the agent. If this is selected as 'Agent.LOG_IN', then the agent will be logged in after adding to the terminal.

On the phone's terminal, call the LucentTerminal.addAgent() method.

Following are the required parameters:

  • AgentAddress - specifies the Address on this Terminal that this request is for, where the Terminal may support several addresses.
  • AcdAddress - specifies the address of the ACD that the Terminal is requested to be logged in to (may be null).
  • InitialState - specifies the initial state of the agent. Valid states are Agent.READY, Agent.NOT_READY and Agent.LOG_IN.
  • WorkMode - specifies the work mode this Agent should be set to. Valid values are LucentAgent.MODE_AUTO_IN and LucentAgent.MODE_MANUAL_IN.
  • AgentID - is the Agent's ID.
  • Password - is the Agent's password.

What would cause the error "Jtapi Client (conn X IP A.B.C.D) is not processing messages from its queue. Send to app failed 5 times with send:0, wait:64, retry:5. This connection will be dropped?"

This error occurs because of an overflowing queue in AE Services. One explanation could be a network outage that prevents AE Services from sending messages to the application. In the absence of a network issue, this failure may occur because the application reads from the queue at a rate slower than the rate at which messages are being written into it, i.e., the application is unable to retrieve messages from the client queue fast enough resulting in queue overflow. AE Services is forced to drop the connection because of excessive time taken by the application for reading consecutive messages from the queue. Some common application behaviors which trigger this issue are that the application uses the thread that receives messages from the library to do some amount of internal processing or that the thread has entered a sleep mode. It is recommended that the application have a dedicated thread which is only involved in shifting messages from the client queue to an internal application queue/dispatcher thread in the application's queue management portion.

When multiple calls are on hold, how can my JTAPI application un-hold a specific call?

Here are the steps to un-hold a specific call on a device:

  • Obtain the Connection list: Connection list can be obtained from an address as well as from a call object. The getConnections method returns all the connections associated with the supplied address or call object, on which the method is invoked. If getConnections is invoked on a call object, the connections associated with the desired address can be obtained as below:
    
    Connection connection[] = call.getConnections();
    	String desiredAddressName = "46001";
    	  for ( int i = 0; i < connection.length; i++ )
    	  {
    	   Connection conn = connection[ i ];
    	   if ( conn.getAddress().getName().equals(desiredAddressName) )
    	   {
    		Connection localConn = conn;
    	   }
    	  }
    							
  • Get the TerminalConnection list: From the connection obtain the Terminal connections:
    TerminalConnection[]terminalConns = 	localConn.getTerminalConnections();
    			
  • Putting the call on hold/unhold for specific TerminalConnection object: Select the appropriate terminal connection and invoke method hold or un-hold:
    for ( int i=0; i < terminalConns.length; i++ )
    	 {
    	   TerminalConnection termConn = terminalConns[ i ];
    	   if ( termConn instanceof CallControlTerminalConnection  )
    {
    		String name = termConn.getTerminal().getName().
    		if(name.equals(desiredAddressName)
    		{
    		   // To hold the call
    	  ((CallControlTerminalConnection)termConn).hold();
    	   // To unhold the call
    	   ((CallControlTerminalConnection) termConn).unhold();
      }
     }
    							
Refer to the JTAPI documentation available with JTAPI SDK 4.2 for more details.

How can the agent ID be obtained from the call event information?

The procedure to get the agent ID from the call event information is described below:

  1. Every call event is associated with a call object. Get the connections on the call using call.getConnections(). getConnections method will return an array of connections associated with this call. Ideally, there should be at least two connections, one referring to the calling party and the other referring to the agent to which the call is redirected.
  2. On each of the returned connections, use the connection.getTerminalConnection() method, which will return an array of TerminalConnection objects associated with this Terminal.
  3. Now check the type of the terminal returned. In case of a terminal connections referring to agent, type will be AgentTerminal.
  4. Using AgentTerminal.getAgent() on the terminal matched by the above step, get a list of agents (Agent Objects) logged into this terminal. Note that in the case of a call involving more than one agent, multiple terminals will return a type of AgentTerminal.
  5. On this Agent Object, invoke AgentTerminal.getAgentID() method, which returns the agent's identification.
A sample code snippet for the above scenario is provided below:

/* The function callChangedEvent handles the various call events 
 * that are received at the extension on which call observer is added.
 */


public void callChangedEvent(CallEv[] eventList) 
{
    for ( int eventIndex = 0; eventIndex < eventList.length; eventIndex++ )
    {
        CallEv e = eventList[eventIndex ];
        /* Retrieve the call object from the call event.*/
        Call call = e.getCall();

     	 /* Get the connection array. 
         * getConnections returns an array of   
         * Connections associated with this call
         */

        Connection[] connectionArray = call.getConnections(); 

        if (connectionArray == null)  /* Check Connections*/  
	 {                                                  
	     System.out.println("No active connections present");  
	     return;
	 }
        for ( int connIndex = 0; connIndex < connectionArray.length; 
              connIndex++ )
        {
	    Connection conn = connectionArray[connIndex ];
	    /* get the terminal connections */
	    TerminalConnection[] terminalConns = conn.getTerminalConnections;        
	    if (terminalConns == null)
	    {
		   System.out.println("No valid TerminalConnection found.");
		   return;
	    }

	    for ( int termIndex=0; termIndex < terminalConns.length; termIndex++ )
	    {
		   if (terminalConns[termIndex] instanceof AgentTerminal)
		   {
			   /*get the agent array*/
			   Agent[] agents = terminalConns[termIndex].getAgents();  
			   for (int agentIndex = 0; agentIndex < agents.length; 
                            agentIndex++ )
			   {
				  /* get the agentID*/
				  String agentID = agents[agentIndex].getAgentID();
				  System.out.println("Agent ID :"+agentID);
			   }
		   }
	    }
       }
    }
		

Can my application update the TSAPI.pro file at runtime and use the updated information in the application without restarting the application?

The information from the TSAPI.pro file is read when the library is loaded. There is no provision to force the TSAPI.pro file to be reloaded. Hence, it is not possible to access the updated TSAPI.pro file without closing the JTAPI application which is running. You must shutdown and restart, or launch a second instance of the application driver level and have the driver level applications communicate with a top level process.

How can my application observe/monitor VDNs (Vector Directory Number) using JTAPI?

Invoke the RouteAddress interface for the address.addCallObserver() method to monitor a VDN on its address.

What causes the OBSERVER_LIMIT_EXCEEDED error to occur while adding a call observer to a logged-on extension?

When a resource is unavailable to complete an operation, JTAPI throws the ResourceUnavailableException exception. If the number of already existing observers reaches the limit, the exception is set with the Error field set to OBSERVER_LIMIT_EXCEEDED. In some cases, the number of allowed observers is zero.

The OBSERVER_LIMIT_EXCEEDED error is encountered when the addCallObserver() method is used on an AgentTerminal in cases where the AgentTerminal object is obtained using an Agent ID. If the agent's login ID is passed as an extension (to obtain an AgentTerminal object), the addCallObserver() method (when invoked on this AgentTerminal object), will throw this error. If the AgentTerminal is obtained by using the station extension where the agent logs in (using the getAgentTerminal() method), a Call Observer can be put on the returned AgentTerminal object.

For more details, please refer to the document Avaya Java Telephony API (JTAPI) javadoc, version 4.2, available on the Avaya DevConnect website at http://www.avaya.com/devconnect.

Is Single Step Transfer (SST) supported by JTAPI?

Yes, Avaya JTAPI supports SST starting from the AE Services server Release 4.1 onwards.

SST feature in JTAPI is accessed by using CallControlCall.transfer() method. This method transfers the participant(s) currently in a call to another address. This method takes address string as an argument indicating where the call is to be transferred and returns a new connection associated with the destination address.

Before performing SST, a Transfer Controller needs to be set up for the call. The Transfer Controller represents a TerminalConnection that is getting transferred. The application can set the transfer controller using the CallControlCall.setTransferController() method. The terminal connection set as the Transfer Controller must be in the CallControlTerminalConnection.TALKING state for the transfer to complete. The other terminal connection(s) in the call can be in the TALKING or HELD state.

The code snippet below illustrates how to perform SST.

// <summary>
// Perform's single step transfer.
// </summary>
// @param call - an existing call on which SST is to be performed.
// @param transferController - terminal connection object of the
// terminal from which the call is to be transferred.
// @param transferTo - address to which the call is to be transferred.
// @return - returns a new connection associated with the transferTo address.

public Connection singleStepTransfer(Call call, 
	TerminalConnection transferController, String transferTo) {

	Connection newConn = null;

	try {
		// Type cast Call object to CallControlCall object
		// to access transfer() & setTransferController() methods.
		CallControlCall callCtlCall = (CallControlCall) call;

		// Set transfer controller
		callCtlCall.setTransferController(transferController);

		// perform SST
		newConn = callCtlCall.transfer(transferTo);

	} // End of try block
	catch (Exception e) {
		System.out.println("Error :" + e.getMessage());
		// handle exception here.
	}// End of catch block
return newConn;
	}// End of method.
						

How can an application obtain the longest call waiting time, average call distribution, and expected wait time using JTAPI?

JTAPI does not provide an API method to access longest call waiting time. An application can calculate the longest call waiting time interval by calculating the difference in timestamp values saved on arrival of the CallCtlConnQueuedEv and the CallCtlConnEstablishedEv events for each call.

For example, if calls are routed through a VDN prior to delivery to a hunt group that the application wants to measure queue interval times for, then the application must set a call observer on the VDN address object:

String vdn_extension = "12345";
....
Address vdn = provider.getAddress(vdn_extension);
vdn.addCallObserver(timestampsCollectingCallObserver);
....
						
Then the application will begin receiving the events mentioned above (along with others), and can populate a data structure with Call object reference as well as the arrival time in queue, and when the call is answered use that information to calculate longest call waiting, average call distribution, and expected wait times. Note that a CallCtlConnQueuedEv is only provided if the call enters the hunt group's queue. If the call is delivered directly to an agent, there is no CallCtlConnQueuedEv event.