Photo by Eduardo Sánchez on Unsplash
The Java Telephony API (JTAPI) is a portable, object-oriented application programming interface for Java-based computer-telephony applications.
This article is an introduction to the Java Telephony API, presenting the most important elements of this and attempts to clarify some basic issues that will be the base for the following articles.
JTapi can be used to integrate CRM or other applications with a telephone system, create applications that handle incoming calls, create application that place outgoing call on behalf of a user, or in general provide an automated way for a user to handle his telephone set.
The purpose of JTAPI is to serve as an interface between a Java application and a telephone system. The point where this interface is located determines the degree of control an application has. In a first-party call control scenario the interface is located at a terminal. The application has the same degree of control a normal telephone user has. In a third-party call control scenario the interface is located inside the telephone system. Depending on the telephone system this internal access provides the application usually with more control capabilities than a first-party call control scenario.
First-party call control
Third-party call control
Figure 1: First-party and third-party call control in a Private Telephone Network with a PBX
A design goal of JTAPI has been to cover both scenarios. As a consequence JTAPI provides a model of the telephone system and of telephone calls that corresponds to the more general third-party view, even when JTAPI is used for first-party call control. A third-party view of a call does not distinguish between the local end and the remote end of a call. Instead, the two ends are symmetrical.
In this article, the discussion is about the third-party call capabilities of the JTAPI and more important how to control or monitor the elements that the JTAPI offers. Next is an introduction of what are the basic JTAPI elements.
Basic JTapi elements
Telephony applications, involve in the control or monitor of objects a telephone system exposes. Such objects could be logical objects, for example an Address, a Call, a Connection etc, or physical objects as a Terminal. Following is a list with the most important JTAPI objects that will be covered throughout this article series. This is an attempt to give an introduction so for everyone to be on the same page.
The JtapiPeer interface represents a vendor’s particular implementation of the Java Telephony API.
JtapiPeer is the first object an application must instantiate. Depending on the vendor’s implementation of this interface, one or more different services can be obtained by the JtapiPeer object.
A Provider represents the telephony software-entity that interfaces with a telephony subsystem.
A Provider is created and returned by the
JtapiPeer.getProvider() method which is given a string to describe the desired Provider. This method sets up any needed communication paths between the application and the Provider. The string given is one of the services listed in the
The rest of the JTAPI objects are derived from the provider and also the provider is responsible for the various actions the application is designed to make with the JTapi. For example, provider is will deliver Address events in case we monitor an Address or create a call between a local Address and a remote Address (example of an outgoing call).
Important to notice is the term Provider’s domain which refers to the collection of Address and Terminal objects which are local to the Provider, and typically, can be controlled by the Provider. For example,the domain of a Provider for a PBX may be the Addresses and Terminals in that PBX. The Provider implementation controls access to Addresses and Terminals by limiting the domain it presents to the application.
An Address object represents what we commonly think of as a “telephone number”.
The purpose of the address could be something different than a telephone number if the underlying network is not a telephone network. As an example if the underlying network is an IP network; then the address might represent an IP address (e.g. 192.168.0.100).
When the Address object is created, a unique string name is assigned to it (e.g. 15121) and does not change throughout the lifetime of the object. The method
Address.getName() returns the name of the Address object.
Address objects may be classified into two categories: local and remote. Local Address objects are those addresses which are part of the local telephone system domain, for example the extension numbers of a PBX. These Address objects are created by the implementation of the Provider object when it is first instantiated. All of the Provider’s local addresses are reported via the
Provider.getAddresses() method. Remote Address objects are those outside of the Provider’s domain which the Provider learns about during its lifetime through various happenings (e.g. an incoming call from a currently unknown address). Remote Addresses are not reported via the
Note that applications never explicitly create new Address objects.
A Terminal represents a physical hardware endpoint connected to the telephony domain. In other words, a Terminal is the telephone set of a PBX.
When the Terminal object is created, a unique string name is assigned to it and does not change throughout the lifetime of the object. The method
Terminal.getName() returns the name of the Terminal. Important to notice here is that in contrary with the Address name, the name of the Terminal may not have any real-world interpretation since in order to interact with a Terminal (e.g. call a Terminal) we use the Address assigned to this Terminal.
Terminal objects may be classified into two categories: local and remote. Local Terminal objects are those terminals which are part of the local telephone system domain, for example the telephone sets of a PBX. These Terminal objects are created by the implementation of the Provider object when it is first instantiated. All of the Provider’s local terminals are reported via the
Provider.getTerminals() method. Remote Terminal objects are those outside of the Provider’s domain which the Provider learns about during its lifetime through various happenings (e.g. an incoming call from a currently unknown address). Remote Terminal objects are not reported via the
Note that applications never explicitly create new Terminal objects.
Address and Terminal objects
Address and Terminal objects exist in a many-to-many relationship. An Address object may have zero or more Terminals associated with it. For each Terminal associated with an Address, that Terminal must also reflect its association with the Address. Since the implementation creates Address (and Terminal) objects, it is responsible for insuring the correctness of these relationships. The Terminals associated with an Address is given by the
Address.getTerminals() method and the Addresses associated with a Terminal is given by the
An association between an Address and Terminal object indicates that the Terminal contains the Address object as one of its telephone number addresses. In many instances, a telephone set (represented by a Terminal object) has only one telephone number (represented by an Address object) associated with it. In more complex configurations, telephone sets may have several telephone numbers associated with them. Likewise, a telephone number may appear on more than one telephone set.
A Call object models a telephone call.
A Call can have zero or more Connections. A two-party call has two Connections, and a conference call has three or more Connections. Each Connection models the relationship between a Call and an Address, where an Address identifies a particular party or set of parties on a Call.
A Call maintain a list of the Connections on that Call. Applications obtain an array of Connections associated with the Call via the
Call.getConnections() method. A Call retains a reference to a Connection only if it is not in the Connection.DISCONNECTED state. Therefore, if a Call has a reference to a Connection, then that Connection must not be in the Connection.DISCONNECTED state. When a Connection moves into the Connection.DISCONNECTED state (e.g. when a party hangs up), the Call loses its reference to that Connection which is no longer reported via the
The Provider maintains knowledge of the calls currently associated with it. Applications may obtain an array of these Calls via the
Provider.getCalls() method. A Provider may have Calls associated with it which were created before it came into existence. It is the responsibility of the implementation of the Provider to model and report all existing telephone calls which were created prior to the Provider’s lifetime. The Provider maintains references to all calls until they move into the Call.INVALID state.
Applications may create new Calls using the
Provider.createCall() method. A new Call is returned in the Call.IDLE state. Applications may then use this idle Call to place new telephone calls. Once created, this new Call object is returned via the
Address and Call objects
Address objects represent the logical endpoints of a telephone call. A logical view of a telephone call views the call as originating from one Address endpoint and terminates at another Address endpoint.
Address objects are related to Call objects via the Connection object. The Connection object has a state which describes the current relationship between the Call and the Address. Each Address object may be part of more than one telephone call, and in each case, is represented by a separate Connection object. The
Address.getConnections() method returns all Connection objects currently associated with the Call.
An Address is associated with a Call until the Connection moves into the Connection.DISCONNECTED state. At that time, the Connection is no longer reported via the
Address.getConnections() method. Therefore, the
Address.getConnections() method will never report a Connection in the Connection.DISCONNECTED state.
The Java Telephony API specification states that the implementation is responsible for reporting all existing telephone calls when a Provider is first created. This implies that an Address object must report information regarding existing telephone calls to that Address. In other words, Address objects must reports all Connection objects which represent existing telephone calls.
Terminal and Call objects
Terminal objects represent the physical endpoints of a telephone call. With respect to a single Address endpoint on a Call, multiple physical Terminal endpoints may exist. Terminal objects are related to Call objects via the TerminalConnection object. TerminalConnection objects are associated with Call indirectly via Connections. A Terminal may be associated with a Call only if one of its Addresses is associated with the Call. The TerminalConnection object has a state which describes the current relationship between the Connection and the Terminal. Each Terminal object may be part of more than one telephone call, and in each case, is represented by a separate TerminalConnection objet. The
Terminal.getTerminalConnections() method returns all TerminalConnection object currently associated with the Terminal.
A Terminal object is associated with a Connection until the TerminalConnection moves into the TerminalConnection.DROPPED state. At that time, the TerminalConnection is no longer reported via the
Terminal.getTerminalConnections() method. Therefore, the
Terminal.getTerminalConnections() method never reports a TerminalConnection in the TerminalConnection.DROPPED state.
The Java Telephony API specification states that the implementation is responsible for reporting all existing telephone calls when a Provider is first created. This implies that an Terminal object must report information regarding existing telephone calls to that Terminal. In other words, Terminal objects must report all TerminalConnection objects which represent existing telephone calls.
A Connection represents a link (i.e. an association) between a Call object and an Address object.
The purpose of a Connection object is to describe the relationship between a Call object and an Address object. A Connection object exists if the Address is a part of the telephone call. Applications use the
Connection.getAddress() methods to obtain the Call and Address associated with this Connection, respectively.
From one perspective, an application may view a Call only in terms of the Address/Connection objects which are part of the Call. This is termed a logical view of the Call because it ignores the details provided by the Terminal and TerminalConnection objects which are also associated with a Call. In many instances, simple applications (such as an outcall program) may only need to concern itself with the logical view. In this logical view, a telephone call is views as two or more endpoint addresses in communication. The Connection object describes the state of each of these endpoint addresses with respect to the Call.
Connection objects are immutable in terms of their Call and Address references. In other words, the Call and Address object references do not change throughout the lifetime of the Connection object instance. The same Connection object may not be used in another telephone call. The existence of a Connection implies that its Address is associated with its Call in the manner described by the Connection’s state.
Although a Connection’s Address and Call references remain valid throughout the lifetime of the Connection object, the same is not true for the Call and Address object’s references to this Connection. Particularly, when a Connection moves into the Connection.DISCONNECTED state, it is no longer listed by the
Address.getConnections() methods. Typically, when a Connection moves into the Connection.DISCONNECTED state, the application loses its references to it to facilitate its garbage collection.
Connections objects are containers for zero or more TerminalConnection objects. Connection objects represent the relationship between the Call and the Address, whereas TerminalConnection objects represent the relationship between the Connection and the Terminal. The relationship between the Call and the Address may be viewed as a logical view of the Call.
The relationship between a Connection and a Terminal represents the physical view of the Call, i.e. at which Terminal the telephone calls terminates.