TeamCall / CAP JTAPI Application Developer's Guide

Version: $Revision: 1.15 $
Created on: $Date: 2017-02-22 17:36:02 $

Contents:

1.  JTAPI at a glance

2.  Implementation notes

2.1  Terminals and Address objects
2.2  Synchronous event notification
2.3  JTAPI method calls in event handler methods
2.4  Supported methods
2.5  Behaviour of the transfer() method
2.6  Event notification for call control observers
2.7  Empty meta event cycles for call listeners
2.8  Private extensions

3.  Examples

3.1.  Obtaining a provider instance
3.2.  Registering a call observer on an address
3.3.  Placing a call
3.4.  Answering a call

4.  Configuration

5.  References



1. JTAPI at a glance

JTAPI is Sun's definition of a vendor-neutral object oriented telephony API for Java. It consists of a number of interfaces that define the methods and behaviour of the abstractions for real-world objects such as a telephone number, a device, a call, etc.. Objects are the source of events that report certain changes of an object's state.

A JTAPI application client first obtains a Provider instance, then asks the provider for an Address object, the logical representation of a phone number. Afterwards, it may register a call listener or observer on that address to be notified of events arriving. It may also actively make calls, answer inbound calls, create conferences, etc..

To use the CAP JTAPI implementation, you must first install a few jar files. Please refer to the CAP JTAPI Installation Guide for further information.

Note: JTAPI 1.3 is not compatible with Java 2 SE 1.4. javax.telephony.ProviderUnavailableException defines a getCause() method that returns an int containing information why a provider is unavailable. Java 2 SE 1.4 re-declares the method getCause() on java.lang.Exception to return a java.lang.Throwable. For now (until JTAPI 1.4 is released) there is no way to use a JTAPI implementation in Java 2 SE 1.4. Use Java 2 SE 1.3.1 instead.



2. Implementation notes

This implementation supports the basic interface methods from javax.telephony plus some additional functions from the call control package javax.telephony.callcontrol. There are certain restrictions which will described in the next few chapters.

2.1 Terminals, Address and Provider objects

The implementation is limited to a first party only view. This means that all remote connections of a Terminal are modelled as "out-of-the-provider-domain", including devices that are in the same PBX . Application clients may need to obtain a local version of the remote object (via calling getAddress() on the Provider object). This object may support certain call control operations, that are disabled on the remote objects. Please see the JTAPI white paper's section about "out-of-the-provider-domain" objects for further details.

Please also note that the implementation supports a dynamic address space only, the addresses are not known to the provider implementation before they are requested. Calling getAddresses() on the Providerwill always return null.

The JTAPI specification allows an Address to have multiple Terminal objects assigned, this implementation will always return only one instance (one-to-one mapping).

The Provider connects to the SCC(P) upon creation. Thus it is always "IN SERVICE" as soon as JtapiPeer.getProvider() returns an instance without an exception. The provider will not send a javax.telephony.events.ProvInServiceEv to any observer or listener that is registered at any time. Don't wait for this event. When the provider looses its connection to the SCC(P), it notifies all listeners and observers by sending a javax.telephony.events.ProvObservationEndedEv. References to the provider instance should be removed from the client application and a new provider instance should be obtained from the JtapiPeer.

2.2 Synchronous event notification

Event messages are sent synchronously, i.e. each event handler is called one after the other directly from the underlying message transport thread. Clients are responsible for dispatching time critical operations in separate threads. The whole application is blocked until the event handler's method call returns. Using a fully synchronous callback mechanism gives the application developer a better control over the (otherwise excessive) thread generation during dispatching.

2.3 JTAPI method calls in event handler methods

Due to the synchronous callback mechanism it is not possible to perform JTAPI method calls directly from within the callback handler. This has to be done in a separate (or perhaps newly created) thread. Please also see the JTAPI white paper's section about blocking calls.

2.4 Supported methods

To check whether a method is support by a specific object, please obtain the Capabilities from the object. The capabilities for Call, Connection and TerminalConnection are call control capabilities that can be casted to their call control version (e.g. CallControlTerminalConnectionCapabilities) and then queried for extended call control features.
NOTE: The capability object returns "true" for some call control methods, which may in fact only work on certain combinations of PBX type, phone configuration, remote party type and call state. Please check your specific configuration manually by writing a short test program, as these methods (e.g. hold, transfer) are not guaranteed to work on all configurations.

2.5 Behaviour of the transfer() method

In contrast to the JTAPI specification for CallControlCall.transfer(), both calls involved might go directly to state INVALID after calling transfer(). This is due to the nature of the underlying monitoring concept. An observer on the transferring device will receive two CallInvalidEv events, since the transferred and the receiving party might be out of the provider domain and thus the clearing of the call would not be reported to this observer.

2.6 Event notification for call control observers

Observers that registered as call control observers (by implementing javax.telephony.callcontrol.CallControlCallObserver) will receive additional call control events directly after the normal event notification, i.e. they will receive two events for the same underlying state change. Observers therefor should check not to perform duplicate actions when receiving events. Example:

2.7 Empty meta event cycles for call listeners

Call listeners may expirience situations, when only meta events are delivered to the listener. No actual call event is delievered between the starting and ending meta event. This behaviour results from the fact that certain call control events don't have an equivalent event in the standard package and the meta events are distributed whenever an event (call control or normal) occurs. Future versions of JTAPI will include listeners for the call control package and the problem will be re-adressed.

2.8 Private extensions

The JTAPI specification lacks support for certain important events and methods. To offer those additional functions, this implementation offers additional private extensions.

The following extensions are available:



3. Examples

The following examples show some of the typical usages of the JTAPI package.


3.1. Obtaining a provider instance

To obtain a JTAPI provider instance, perform the following steps:

a) Get a JTAPI peer for the implementation:

JtapiPeer peer = JtapiPeerFactory.getJtapiPeer("de.ilink.cti.cstajtapi.JtapiPeerImpl");
NOTE: JTAPI implementation may also support a "default peer" implementation that is created when JtapiPeerFactory.getJtapiPeer() is called with a null parameter. This function is NOT supported by this implementation, since it is most likely that this feature will be dropped in the next release of JTAPI. The lookup mechanism used by JtapiPeerFactory is incompatible with certain restrictions of Java 1.4 (all classes must be in packages).

b) Create a provider string.

The provider string must contain the hostname and port of the SCC(P) in a <port>@<hostname> format, the application identifier for the ACSE authentication request ("applicationID") and an optional username and password for authentication ("login","passwd").
String providerString = "26535@test;applicationID=CAP;login=testUser;passwd=testPass";

c) Get the provider instance:
Provider myProvider = peer.getProvider(providerString);

The provider should now be ready and connected to the remote CSTA XML server. If the initial authentication fails or the remote side signals that it is out of service, an exception is thrown during creation of the provider object.


3.2 Registering a call observer on an address

a) Get an address object from the provider:

Address addr = myProvider.getAddress("123");

If you are connected to an SCCP, you have to give a canonical number instead of the dialing number from the previous example:
Address addr = myProvider.getAddress("+49(30)12345-123");

b) Registering the observer.
Create a class that implements javax.telephony.callcontrol.CallControlCallObserver and register an instance as a call observer at the Address object:
CallControlCallObserver callObs = new MyObserver();
addr.addCallObserver(callObs);

Whenever call related events on the addr object occur, the callObs object's callChangedEvent method will be called. Note that in conformance with the JTAPI specification only call events for calls that were started after the observer was registered are reported.


3.3 Placing a call

This example shows how to place a call from the phone specified by the Address object addrto the phone number "5678":

a) Obtain a terminal instance from the Address:

Terminal[] termArr = addr.getTerminals();
Terminal term = termArr[0];

b) Create an empty call object:
Call call = myProvider.createCall();

c) Start the call to the remote party:
Connection[] connections = call.connect(term,addr,"5678");

Application clients that are registered as observers or listeners can to check for the connection objects to become connected. Note that the local side of the connection is already connected after a successfull connect() method call. The remote connection moves into connected state once the call is answered by the remote party.

d) To drop the call either use the handset or call disconnect on the local Connection object. By convention the local side of the connection (at least for a Call created by connect() that has not been part of a conference) is always the first array entry:
connections[0].disconnect();

No matter whether the connection is disconnected manually or programmatically, all events that report the dropped connection are send to the observers. See the JTAPI documentation for the details of the event flow.


3.4 Answering a call

This example shows how to answer a call using an event handler method. Note that the actual answer() method call has to be performed in a separate thread to avoid circular deadlocks.

a) Create a class that implements javax.telephony.callcontrol.CallControlCallObserver. Register an instance of this class on the address you want to answer calls on.

In the callChangedEvent() method of the class check for a TermConnRingingEv arriving on your observed address (via instanceof)

public class MyObserver
implements CallControlCallObserver
{
    public void callChangedEvent(CallEv[] anEventArr)
    {
        if (anEventArr[0] instanceof TermConnRingingEv) {
            final TerminalConnection tc = ((TermConnRingingEv)anEventArr[0]).getTerminalConnection();
            new Thread() {
                public void run() {
                    try {
                        tc.answer();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }.start();
        }
    }
}


In your main program:

CallControlCallObserver callObs = new MyObserver();
addr.addCallObserver(callObs);

Whenever a call arrives on the given address, a TermConnRingingEv is fired by the JTAPI implementation. The observer will then answer the call automatically by calling answer() on the affected TerminalConnection object. Real world applications could also present the user a popup window and ask whether they should answer the call or not.



4. Configuration

For special cases, TeamCall JTAPI supports a few optional configuration switches that subtly change the behavior in order to support non-standard situations.

These cases are not documented here, ilink support will let you know to use a specific configuration if that should become necessary.

The configuration switches are specified in a configuration file jtapi-config.properties which needs to be located in the Java working directory (i.e. the path specified by the Java environment variable user.dir).



5. References

JTAPI API documentation

JTAPI white paper

JTAPI installation guide

ECMA TR/82 - Scenarios for Computer Supported Telecommunications Applications (CSTA) Phase III