JTAPI Hands-On: Part I
Join the DZone community and get the full member experience.
Join For FreeStarting 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 order to compile and run the source code you need the JTapi library in your classpath and off 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();
}
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();
}
}
public static Provider getProvider(){
if (instance == null){
instance = new ProviderService();
}
return provider;
}
}
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() line 17. 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 (line 20).
- 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 ,at line 21, 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) at line 23.
Important things to remember from this class:
- Using the JtapiPeerFactory.getJtapiPeer(""); we retrieve the vendor's implementation of the Java Telephony API (line 19).
- 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 (line 21).
- From the JtapiPeer object we retrieve the Provider object using Provider provider = peer.getProvider(providerString); (line 23).
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 (line 13) 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, at line 17, an array of Addresses is being retrieved and printed out. Similarly, at line 28, 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, at line 39, 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.
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.
Resources:
Opinions expressed by DZone contributors are their own.
Comments