|
©1996,1997 Enterprise Computer Telephony Forum This document is copyrighted and all rights are reserved by the Enterprise Computer Telephony Forum (ECTF)."ECTF technical implementation agreements are considered public domain and may be copied, downloaded, stored on a server or otherwise re-distributed."
(Unchanged for now) Post comments to the ECTF Portable API Mailing List: ectf-tgpapi@ectf.org
Thanks to all reviewers for their comments and feedback.
1. The Java Telephony API * 1.1 Overview of Contents * 2.2 Why JTAPI * 3.1.1 Structural Call Model * 3.1.2 Dynamic Call Model * 3.1.3 State in Call Model Objects * 3.2 Sample JTAPI Application Flow * 3.3 Obtaining a Provider * 3.4 Investigating Call Model Objects * 3.5 Determining Capabilities * 3.6 Registering Observers * 3.7 Making JTAPI Requests * 3.8 Beginning and Ending Calls * 3.8.1 "Terminal-less Addresses" and "Out-of-Provider-Domain" Connections * 3.8.2 Using JTAPI to end a Connection * 3.8.3 When "the far end" ends a Connection * 3.8.4 The end of Call Observation * 3.8.5 Ending Connections and ending Calls * 5. Frequently Asked Questions * 5.2 What is the relationship of JTAPI to other telephony APIs? * 5.3 Where can I get the class files for JTAPI? * 5.4 What Java packages are included in JTAPI? * 5.5 What do implementers need to implement? * 5.6 Is JTAPI "blocking" or "non-blocking"? * 5.7 Why are there so many kinds of observers? * 5.8 How can I make JTAPI do "X"? * 6.2 Rules for Participation *
1.The Java Telephony APIThis document provides an introduction to JavaSoft?s JTAPI (Java Telephony API). JTAPI is the product of JavaSoft and several "partner" companies. The specific release described in this document is JTAPI 1.2. The reference specification for JTAPI is at http://java.sun.com/products/jtapi/index.html. 1.1 Overview of ContentsThis document:
2 Rationale for a Java-based Telephony APIThe rationale for a Java-based Telephony API comes in two stages. 2.1 Why JavaThe driving force behind the use of Java for this specification is the desire to maximize application portability across vendor implementations. "Application Portability" is literal - the application itself, in compiled form, may be loaded onto any conforming implementation and executed. The Java programming language is used for this specification because of its support for "write once, run anywhere" application development. 2.2 Why JTAPIThe goals for JTAPI are simple, if ambitious - to create an API that allows applications to run on a variety of operating systems and hardware platforms, against a variety of telephony networks.JTAPI is intended to be a simple API as well. JTAPI still requires application developers to be knowledgeable about telephony, but reduces the amount of implementation-specific knowledge required to develop applications. The range of "targets" for JTAPI ranges from the largest call centers, to desktop systems, to network computers, to "network telephones". This range is the reason for the "core plus extensions" organization of JTAPI, discussed below. JTAPI blurs borders. It blurs the distinction between first-party and third-party call control, and it blurs the distinction between call control and media control. JTAPI isn't "just another telephony API" - although JTAPI can be implemented
without existing telephony APIs, it was also designed to allow implementers
to build on top of these existing telephony APIs.
3 Overview of OverviewsThis section of the document describes JTAPI at the 50,000-foot level. More detail is available in the Overviews of the various JTAPI packages, which in turn point to the actual specifications - the final arbiter of correctness. The reader may find it useful to refer to the JTAPI specifications for detailed definitions of JTAPI constants (shown in all caps, for example, ACTIVE) and methods (shown with parenthesized parameter lists, for example, addObserver()). Note: several references are made to "a well-behaved JTAPI application" in this section, in the context of what "well-behaved JTAPI applications" do and don?t do. These comments indicate desirable attributes of JTAPI applications wishing to be as robust, and as portable, as possible. For instance, JTAPI does not require applications to register as object observers; applications have the option of investigating call model objects on their own. "Well-behaved JTAPI applications" don?t do this, because an unregistered JTAPI application has no way to monitor call model objects for state changes except for polling. 3.1 Call ModelThe Call Model used in JTAPI contains six primary objects:
3.1.1 Structural Call ModelWhen a JTAPI implementation initializes, before it knows about any calls, it looks like Figure 1. The JtapiPeerFactory and JtapiPeer (used only to help applications locate the proper Provider), the Provider itself, and all configured Addresses and Terminals are known to the implementation. The point to notice here is that the relationship between logical and physical endpoints is modeled as a many-to-many relationship between Addresses and Terminals. This allows Terminals to have multiple Addresses, and allows Addresses to appear on multiple Terminals. ![]() This "Structural Call Model" is sufficient to allow JTAPI applications
to start executing.
3.1.2 Dynamic Call ModelWhen calls begin to happen, the dynamic relationships in JTAPI become more important. These are shown in Figure 2. (The structural relationships are shown as dotted lines, for reference).Again, the point to notice here is that JTAPI applications have access to both logical and physical endpoints in the call. The relationship between the Call and a logical endpoint (Address) is called a Connection; the relationship between the Connection and a physical endpoint (Terminal) is called a TerminalConnection. The relationship between Calls and Connections is zero-to-many. IDLE Calls have no Connections; ACTIVE Calls have at least one Connection. Each Connection is tied to a single Address. The relationship between Connections and TerminalConnections is zero-to-many. This allows JTAPI implementations to support multiple active Terminals for the same Address, if the underlying telephony environment allows this. Placement of JTAPI methods in this call model is based on whether the application is working with an entire Call, a single Address in the Call, or a single Terminal in the Call. For instance, JTAPI applications
![]() 3.1.3 State in Call Model ObjectsThe JTAPI call model, taken as a whole, does not have an internal state. Instead, individual call model objects have internal states, referred to as core states generically, or as core {provider, call, connection, terminalconnection} states when referring to the states of a particular object. These internal states make up what is loosely called the "call model state".Not all call model objects have internal state. These call model objects do:
For instance, the Core Connection state CONNECTED corresponds to the Call Control Connection states INITIATED, DIALING, NETWORK_REACHED, NETWORK_ALERTING, and ESTABLISHED. Core Observers see Core events, while extension package observers see extension package events. 3.2 Sample JTAPI Application FlowJTAPI applications typically perform these actions:
3.3 Obtaining a ProviderAll JTAPI applications must obtain a reference to a Provider in order to do almost anything interesting. This is a two-stage process:
3.4 Investigating Call Model ObjectsNow that the application has a "window" on the telephony domain, it looks out the window. What it is looking for is call model objects it will use to provide telephony services.The precise strategy the application uses to investigate call model objects is very application-dependent. Common strategies include:
3.5 Determining CapabilitiesTelephony environments vary widely in their ability to perform certain functions. This variation may reflect technical considerations or administrative considerations. JTAPI does nothing to reduce this variation (if you don?t subscribe to a conferencing feature, JTAPI won?t change this). What JTAPI does do is provide a mechanism for finding out exactly what an application (which, after all, may have been downloaded over the Internet) can do in its current execution environment. This mechanism, taken from existing telephony APIs, is called Capabilities.Capabilities takes two forms:
Many static capabilities can be determined at initialization time, but dynamic capabilities can come and go. For this reason, a well-behaved JTAPI application will query relevant capabilities at initialization time, in order to "gray out" unsupported/unavailable features in user interface displays, but will check again when preparing to invoke the relevant method. This will minimize the number of exceptions the application will encounter. A JTAPI application can still be "well-behaved" without checking capabilities, as long as it catches MethodNotSupportedException and InvalidStateException. This approach is simple, but does not allow the application to present an accurate user interface (the user may attempt actions which aren?t allowed by the implementation). Capabilities are aligned one-to-one with methods; if a method isn?t implemented in all environments, a capability exists to allow the application to check whether it is available at execution time. Every JTAPI call-model object has an associated capability object:
3.6 Registering ObserversFor reasons inherent to telephony, JTAPI applications will need to learn about state changes in call model objects that aren?t the result of anything the application has done. For instance, an application may want to know when an incoming call has arrived at a specific terminal, in order to update a user?s view of that Terminal on a graphical user interface.This is done using a mechanism called "entity-observer-events", loosely based on the "monitor" facility described in C.001, and commonly used in existing telephony APIs:
![]() Events correspond one-to-one with call model state transitions. In the general case, an application wishing to learn about state changes in JTAPI object X invokes the method X.addObserver(), providing an "event handling routine" as a parameter. Upon returning from X.addObserver(), the application will start to see the event handler called whenever the observed call model object changes state. These events will continue to arrive until the application invokes X.removeObserver(). When a JTAPI implementation has finished adding a new observer, it will send events to the observer which bring the application?s view of the call model?s state in line with the implementation?s view. This process is called "snapshotting". Snapshotting happens automatically when applications register observers. It is not necessary for the implementation to synthesize every event that has happened in the history of the call - if a party has been one-step-conferenced in, and then disconnected, the snapshot need not include these events. Only the events required to bring the Observer "up to speed" are required. Call Observers extend the single-object observer model. Call Observers get events for all the call model objects in the call. A variant exists for Addresses and Terminals. The application invokes Address.addCallObserver(), providing an "event handler routine" as in the previous examples. Each time a Call arrives at the Address, the implementation will add the event handler as a Call Observer for that call. The application?s event handler will receive events for the call until one of these things happens:
Terminal.addCallObserver() and Terminal.removeCallObserver() are exactly analogous to the Address.addCallObserver() and Address.removeCallObserver() methods. 3.7 Making JTAPI RequestsBecause telephony events can happen at any time, and because JTAPI methods can block for an arbitrarily long period of time, well-behaved JTAPI applications will use at least two threads (one for invoking methods on the implementation, and another for receiving events). More threads may be desirable, depending on the application and its environment. Well-behaved JTAPI applications will also not invoke (potentially blocking) JTAPI methods in the execution thread it uses to receive events, because these methods may generate additional events while the Observer is blocked. Fortunately, Java makes multithreading relatively painless. 3.8 Beginning and Ending CallsOutgoing Calls are created by the implementation at the request of JTAPI applications, by invoking Provider.createCall(). Incoming calls are created by the implementation when it receives an indication of an incoming Call through normal telephony signaling. Calls are created in IDLE state, with no Connections. When a JTAPI application invokes the "Call.connect()" method, to place an outgoing call, or when the implementation creates a Call to represent an incoming call, two Connections are created and associated with the Call. When a Call gets its first Connection, it becomes an ACTIVE Call, and it remains an ACTIVE Call until it has no Connections in the CONNECTED state. Typically, Connections are associated with one or more TerminalConnections. This is how a path to a logical endpoint - an Address - is mapped to a physical endpoint - a Terminal. In some cases (discussed in Section 3.8.1), no Terminal/TerminalConnection is created for the Connection. When a JTAPI application originates an outgoing Call, the "near-end" Connection advances to the CONNECTED state, and the corresponding TerminalConnection advances to ACTIVE, reflecting the real-world phenomenon of "dial tone". When a JTAPI application issues TerminalConnection.answer(), to answer an incoming Call, or when the implementation receives an indication via normal telephony signaling that an outgoing call has been answered, the "answered" Connection is advanced to the CONNECTED state, and the corresponding TerminalConnection is advanced to the ACTIVE state. This is what an average person would consider to be a useful phone call - an end-to-end path between two sets of logical/physical endpoints.
3.8.1 "Terminal-less Addresses" and "Out-of-Provider-Domain" ConnectionsWhen a Call refers to one or more Addresses "outside the Provider?s domain", the implementation will dynamically create these Addresses as needed. These Addresses are removed by the implementation when the corresponding Connection transitions to the DISCONNECTED state.Implementations may also create Terminals dynamically. This is appropriate when the implementation allows an application to manipulate Terminals and TerminalConnections on Connections to "out-of-Provider-scope" Addresses. In two cases, JTAPI Connections may not create Terminals dynamically, and may not create TerminalConnections corresponding to a Connection.
Methods like Provider.getAddresses() and Provider.getTerminals() return only Addresses and Terminals "within the Provider's domain". A fully-established JTAPI Call which includes a Connection to a Terminal "outside the Provider?s domain" may look like Figure 5. ![]() 3.8.2 Using JTAPI to end a ConnectionWhen a JTAPI application decides to end a Connection - an Address?s association with a Call - it invokes "Connection.disconnect()" on one of the Connections associated with the Call. From JTAPI?s perspective, either Connection will do; there is no concept of "originating" or "terminating" Connections in JTAPI. In many environments, implementations may limit the application?s ability to disconnect every Connection in the Call, based on the user?s permissions; "well-behaved" JTAPI applications invoke "canDisconnect()" to make sure they are disconnecting "the right" connection. Connection.disconnect() advances the Connection?s state to DISCONNECTED, and advances the state of all TerminalConnections associated with this Connection to DROPPED. When Connection.disconnect() returns control to the application, this action is complete, so the application can ignore events associated with this invocation of this method. 3.8.3 When "the far end" ends a ConnectionWhen "the far end" user (JTAPI or otherwise) ends her association with the Call, the JTAPI implementation is notified that "the connection has gone away", via normal telephony signaling, and the JTAPI implementation advances the appropriate Connection to DISCONNECTED state. Registered CallObservers are notified that this has happened by the implementation, using ConnDisconnectedEv ("Connection Disconnected Event") and TermConnDroppedEv ("Terminal Connection Dropped Event"). 3.8.4 The end of Call ObservationWhat happens next is dependent on how the JTAPI application associated its CallObserver with the Call.3.8.5 Ending Connections and ending CallsWhen a Call gets at least one Connection, it becomes ACTIVE; when the Call has at least two Connections and both Connections become CONNECTED, the Call becomes a useful telephone call to humans. Calls can add Connections - this is how conferencing is represented, in the Call Control extension package - and Connections can become DISCONNECTED, as Calls are transferred away from Addresses and participants leave conference calls.When an ACTIVE Call has only one CONNECTED Connection, the implementation may choose to set the remaining CONNECTED Connection to DISCONNECTED. In the case where a far-end party hangs up, this would be appropriate. However, having only one CONNECTED Connection does not automatically end the Call. If the implementation knows it is executing a "call transfer", and the implementation receives an indication that the "transferred from" Connection is DISCONNECTED, the implementation should not end the Call, because it is expecting to receive an indication that another Connection is being added to the Call as well. Because implementations are better placed to know when calls should be ended, implementations, and not applications, are responsible for detecting situations where the Call has only one CONNECTED Connection, and isn?t expected to add Connections. In these situations, the implementation should DISCONNECT the remaining Connection, remove all Connections from the Call, and advance the Call state to INVALID. So JTAPI applications should not attempt to detect the end of Calls and tear down Connections. They should, however, dereference the Call and its associated Connections and TerminalConnections when the implementation advances the Call state to INVALID. In a Core JTAPI two-party call, disconnecting a Connection is equivalent
to ending the call, because Core JTAPI does not include transfer and conferencing
capabilities - there?s no way to add Connections to a Call with only one
CONNECTED Connection. The Call Control package includes a CallControlCall.drop()
method, to provide a short-cut when the application wants to end a Call
which may have three or more ACTIVE Connections - this method is equivalent
to disconnecting all Connections.
4 "The Tao of JTAPI"JTAPI has these guiding principles:
5 Frequently Asked Questions
From Jim Wright?s presentation at 1997?s JavaOne conference: JTAPI "Enables portable JavaTM applications to setup, control and tear down calls (and control their associated data streams) to and from public and private networks, on a broad spectrum of host telephony platforms". It's important to note that JTAPI isn?t just a call control API - it also controls associated media streams. Providing a single API that covers both these areas is one of JTAPI?s design goals. As shown in Figure 6, JTAPI is independent of existing telephony APIs, but can be implemented using these APIs as primitives. Most of the JTAPI implementations we are aware of are based on these APIs, but as shown in Figure 6, JTAPI can be implemented entirely in Java if a switching platform supports this. ![]() We should mention that diagrams like this may give the impression that the JTAPI implementation has to run on the same platform as an existing telephony API, but this isn?t true. Figure 7 shows a very typical implementation architecture, called "thin-client", which uses Java?s Remote Method Invocation (RMI) technology to access a telephony server across a network. Other networking technologies could be used as well (JOE, etc.), as long as the client and the server understand the same technology. JTAPI is neutral on this issue. ![]() The JTAPI API provides a unified view of diverse underlying telephony environments. For instance, the JTAPI call model can express either first-party or third-party call control, although underlying implementations will typically support one or the other. This diversity, hidden from applications, falls squarely on JTAPI implementers. We believe it?s infeasible to write a JTAPI implementation that is portable across the underlying telephony APIs. So, unlike many Java APIs, you don?t download Java class files and run your application. JTAPI requires an implementation, specific to your telephony environment, in order to function. To meet this requirement, vendors provide JTAPI implementations that run in specific telephony environments. JTAPI uses a "core plus extensions" structure. The packages included in JTAPI 1.1.1 are: These packages are available from http://java.sun.com/products/jtapi/index.html. JTAPI 1.2 adds (with associated "events" and ""capabilities"): At the very least, implementers must support the javax.telephony, javax.telephony.capabilities, and javax.telephony.events packages. These packages constitute "Core JTAPI". Additional packages may be supported as necessary. The correct answer is "yes". JTAPI has design goals of minimizing application complexity and portability. Most JTAPI methods do not immediately return control to the application. Instead, most methods guarantee "post-conditions" when they return control to the application. These post-conditions are documented in comments on each method in the detailed specification. For instance, javax.telephony.connection.disconnect() guarantees that, when control is returned to the application, the connection has been DISCONNECTED, and the associated terminal connection has been DROPPED (among other post-conditions). This approach requires application execution threads to block until these post-conditions are met. The application doesn?t have to check to make sure these state transitions are really happening. So JTAPI is, strictly speaking, blocking. Application developers are responsible for knowing when their applications are likely to suspend execution. In particular, observer event delivery threads should not make potentially blocking JTAPI method calls, because this could lead to circular waiting deadlocks (the observer is waiting on the response to the method call, which the implementation can?t deliver because the observer is blocked). The exception to this rule is that JTAPI methods tend to wait on machines, but not on humans. Javax.telephony.connection.disconnect() waits until the connection is actually disconnected, because this happens fairly rapidly. Javax.telephony.call.connect() does not wait until the call is actually connected, because this would block the application while the called party wakes up, gets out of bed, walks down the hall, and answers the phone. And this is why a blocking API also uses an "entity-observer-event" model!
JTAPI doesn?t cover every possible situation in every possible telephony environment, and it never will. JTAPI wasn't designed top-down, to anticipate all requirements of computer telephony. The contents of JTAPI to date have been determined pragmatically. When people working on the specification encountered a situation or application that isn't covered, they contribute proposals extending JTAPI, and, if there is sufficient interest, the specification is extended to include these proposals as modified by the "JTAPI team". If JTAPI would be perfect for your application except that it doesn?t "do X", these are the suggested guidelines:
6 Work programThis section of the document describes the "rules of engagement" for JTAPI. 6.1 Areas of focusJTAPI specification work has taken place in a number of areas, including:
6.2 Rules for ParticipationBill Gogesch of JavaSoft is the coordinator for the JTAPI specification.Participants in the JTAPI specification team come from two primary sources:
| |||||||||||||||||||||||||||||||||||
Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.
|
| ||||||||||||