JTapi hands-on, part I

The story so far

In the first article there was an introduction to the basic interfaces of JTAPI, that is JtapiPeer, Provider, Address, Terminal, Call and Connection. These are the basis on which we will built upon and continue in this article.

Starting from this article, I will leave the plain theory behind, and I will delve into the Jtapi objects using code examples. Off course, each code snippet, will be supported by the appropriate theory in order to elaborate and deeply analyze each object.

This iteration will concentrate on the JTapiPeer and Provider interfaces, and will present the way can be used to further inside an application using two example classes. The first one ProviderService mainly shows how to use JtapiPeer in order to instantiate and supply the Provider object for the second class JTapiDiscovery which purpose is just to discover the Addresses and Terminals from the Provider’s domain.

Prerequisites for the source code

In the Resources section of this articles you can find the source code from the examples. In order to compile and run the source code you need the JTapi library in your classpath and of course a PBX equipped with the appropriate JTAPI software services. Most of the PBX vendors provides for free the JTapi library implementation for their platform. For any help please leave a comment.

ProviderService: A useful helper class for the rest of the tutorial(s)

Given that the instantiation of a Provider, is the first step for any application, i decided to create a helper class ProviderService that will be used for the rest of the tutorial in order to retrieve the Provider from the JTapiPeer.

The ProviderService class follows:

package org.devrealm.jtapitutorial.bootstrap;

import javax.telephony.JtapiPeer;
import javax.telephony.JtapiPeerFactory;
import javax.telephony.JtapiPeerUnavailableException;
import javax.telephony.Provider;

public class ProviderService {
private static ProviderService instance;
private static Provider provider;

private ProviderService () {
bootStrap();
}

public static Provider getProvider () {
if (instance == null) {
instance = new ProviderService();
}
return provider;
}

private void bootStrap () {
try {
JtapiPeer peer = JtapiPeerFactory.getJtapiPeer("");
String[] myServices = peer.getServices();
String providerString = myServices[0] + ";login=user;passwd=passwd";
provider = peer.getProvider(providerString);
} catch (JtapiPeerUnavailableException e) {
e.printStackTrace();
}
}
}

The ProviderService is a helper class that implements the Singleton pattern(see Resources for more). The class supply a public static method getProvider that returns a Provider object to any other class request it.

Besides the usual singleton stuff, this class presents the method _bootStrap()_. Using this method, the class creates the Provider object and make it available.

Recall from the previous article, the JTapiPeer interface represents a vendor’s particular implementation of the Java Telephony API. So the first thing this class is doing is to retrieve an instance of the the JTapiPeer using the static method of the JtapiPeerFactory, JtapiPeerFactory.getJtapiPeer("") as you can see at line 19. Having a JTapiPeer instance in place, the bootStrap method, fetches all the available services this peer can provide.

  • Depending on the vendor’s implementation of this interface, more than one service can be obtained if for example the telephony software-entity is connected to more than one telephony subsystems (e.g. a JTapi service/server connected to two PBX will result in two services).

The next step is to create the providerString, which will include the service in question, the username and password for the JTapi service user. Having the providerString in hand, we go on and request the Provider from the JTapiPeer with the method peer.getProvider(provideString).

Important things to remember from this class:

  • Using the _JtapiPeerFactory.getJtapiPeer("");_ we retrieve the vendor’s implementation of the Java Telephony API.

  • Having in hand the JtapiPeer, we construct the providerString which consists of the Jtapi service (most of the times will be only one), the user name and password for this service.

  • From the JtapiPeer object we retrieve the Provider object using _Provider provider = peer.getProvider(providerString);_

Bare in mind that the above three simple steps are the foundation in order to initialize all the Java Telephony applications.

Next we move on the JTapiDiscovery class where the Provider is getting into action.

JTapiDiscovery: Provider in action

One of the things any JTapi application is supposed to do is first retrieve all available addresses and terminals (or otherwise all the requested addresses and terminals) and maybe place them in a storage area in order to be used later from the rest of the application’s logic. This is exactly what the next class, JTapiDiscovery is doing.

The JTapiDiscovery class follows:

package org.devrealm.jtapitutorial.discovery;

import javax.telephony.Address;
import javax.telephony.Provider;
import javax.telephony.ResourceUnavailableException;
import javax.telephony.Terminal;

import org.devrealm.jtapitutorial.bootstrap.ProviderService;

public class JTapiDiscovery {
public static void main (String[] args) {
Provider provider = ProviderService.getProvider();
//Print all the available addresses of the system.
try {
Address[] addresses = provider.getAddresses();
System.out.println("Avaialable Addresses : ");
for (int i = 0; i < addresses.length; i++) {
System.out.println("Address : " + addresses[i].getName());
}
} catch (ResourceUnavailableException e) {
e.printStackTrace();
}
//Print all the available terminals of the system.
try {
Terminal[] terminals = provider.getTerminals();
System.out.println("Avaialable Terminals : ");
for (int i = 0; i < terminals.length; i++) {
System.out.println("Terminal : " + terminals[i].getName());
}
} catch (ResourceUnavailableException e) {
e.printStackTrace();
}
//Always remember to shutdown the provider,
//otherwise the application won't return.
provider.shutdown();
}
}

So the JTapiDiscovery class, utilizing the previous ProviderService class, first retrieves the Provider object and start working with this.

If you take a look at the Javadoc of the Jtapi, the Provider interface supply a bunch of useful methods to retrieve the Addresses, Terminals, Capabilities etc, from the Provider’s domain. Thus, an array of Addresses is being retrieved and printed out. Similarly, an array of Terminals is being retrieved and printed out.

Notice, that its not the actual object that is printed out, but the name of the Address or the Terminal in question each time. As we will see in a future articles, an Address or Terminal interface among other methods, provides a getName() method in order to retrieve the unique name of the object. The getName() method is the main way to interact with the end users, since an Address object is known to the user only by its name, for example the extension number of his telephone set.

Also notice that the Provider’s methods _provider.getAddresses()_ and _provider.getTerminals()_ throw an exception of type ResourceUnavailableException that must handled when for example someone request an Address or Terminal that doesn’t exist or is not provided by this Jtapi service.

Finally, there is a call to the Provider’s method _provider.shutdown()_. This method, request the Provider to move the the state Provider.SHUTDOWN and the application to return. Provider’s states and state-transitions is the next issue to discuss.

Provider states

The Provider object can be in any of the following three states:

  • Provider.IN_SERVICE: This state indicates that the Provider is currently alive and available for use.

  • Provider.OUT_OF_SERVICE: This state indicates that a Provider is temporarily not available for use. Many methods in the Java Telephony API are invalid when the Provider is in this state. Providers may come back in service at any time, however, the application can take no direct action to cause this change.

  • Provider.SHUTDOWN: This state indicates that a Provider is permanently no longer available for use. Most methods in the Java Telephony API are invalid when the Provider is in this state. Applications may use the Provider.shutdown() method on this interface to cause a Provider to move into the Provider.SHUTDOWN state.

When first the Provider is instantiated using the _JtapiPeer.getProvider(providerString)_ method, the Provider object returned is in the state IN_SERVICE and can be used straight away.

When an application calls _provider.shutdown()_, Provider is moving to the SHUTDOWN state, JTAPI loses communications permanently with the telephony subsystem and the application can assume that the Provider will not come up again, so the application must handle a complete shutdown. Applications invoke the Provider.shutdown() method when they no longer intend to use the Provider, usually, right before they exit. This method is intended to allow the Provider to perform any necessary cleanup that would not be handled when the Java objects are garbage collected. The
Provider.shutdown() method causes the Provider to move into the Provider.SHUTDOWN state where it will stay indefinitely. If the Provider is already in the Provider.SHUTDOWN state, this method does nothing.

Useful also for a developer, might be the Provider’s method, _provider.getState()_. This method will return a constant integer value that denotes the state of the provider as follows:

  • Provider.IN_SERVICE: Constant Value 16

  • Provider.OUT_OF_SERVICE: Constant Value 17

  • Provider.SHUTDOWN: Constant Value 18

The figure below shows the allowable state transitions for the Provider object.

Provider states transition

Provider states transition

Conclusion

Any kind of Java Telephony application you plan to implement will use the Provider object as the initial object to start interacting with the telephony subsystem. The Provider interface supplies additional methods that haven’t discussed over here but future articles that will describe the rest of the futures of JTapi, will present the full potential of Provider interface.