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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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.

Provider State Transitions

Provider State Transitions

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.

[print_link]


Resources

Tags: , , ,

36 comments

  1. [...] JTapi hands-on, part I | devRealm.org [...]

  2. Hello,

    I’m looking for the jtapi library implementation for the Panasonic KX-TDA series. Anyone know where I might find one? Many thinks for your help.

    Best,
    Amr

  3. Amir,

    As far as i know Panasonic KX-TDA series doesn’t provide a JTapi stack. But they provide TAPI 2 CTI interface (TAPI and CSTA).

    GvaG..

  4. Hi GvaG,

    Thank you for your answer, I did suspect as much. I’m wondering if there’s a generic jtapi driver out there that would sit on top of the tapi and would allow access to most (if not all the functionality)? I did some hunting on google but a lot of the implementations seem a little old (2002) and incomplete.

    Amir

  5. Hi,

    in code section for JTapiDiscovery occurs ‘<‘ in place of ‘<‘.
    You refer to line numbers in this article, it would be better to see the line numbers in code sections ;)

    Thanks and Regards,
    kads

  6. Kads,

    Thanks for you comment. I added the line numbers in code ;-)

    Regards
    GvaG

  7. I get an Exception, does anybody know what’s wrong?
    Thats the Exeption:

    javax.telephony.JtapiPeerUnavailableException: JtapiPeer: asd could not be instantiated.
    at javax.telephony.JtapiPeerFactory.getJtapiPeer(JtapiPeerFactory.java:135)
    at ProviderService.bootStrap(ProviderService.java:18)
    at ProviderService.(ProviderService.java:13)
    at ProviderService.getProvider(ProviderService.java:30)
    at JTapiDiscovery.main(JTapiDiscovery.java:10)
    Exception in thread “main” java.lang.NullPointerException
    at JTapiDiscovery.main(JTapiDiscovery.java:14)

  8. Oh sorry its wrong, this is the Eception:

    javax.telephony.JtapiPeerUnavailableException: JtapiPeer: DefaultJtapiPeer could not be instantiated.
    at javax.telephony.JtapiPeerFactory.getJtapiPeer(JtapiPeerFactory.java:135)
    at ProviderService.bootStrap(ProviderService.java:18)
    at ProviderService.(ProviderService.java:13)
    at ProviderService.getProvider(ProviderService.java:30)
    at JTapiDiscovery.main(JTapiDiscovery.java:10)
    Exception in thread “main” java.lang.NullPointerException
    at JTapiDiscovery.main(JTapiDiscovery.java:14)

  9. JtapiPeer peer = JtapiPeerFactory.getJtapiPeer(null);

    This piece of code throws the exception! I have the same code which is described on this page! The ProviderService.java and the JTapiDiscovery.java!

    • Boogy,

      There are two cases that might cause this exception:

      1. Try to call the JtapiFactoryPeer.getJtapiPeer() using a specific argument as provided by the vendor of the Jtapi Services.
      From the JavaDoc: …. Applications use the JtapiPeerFactory.getJtapiPeer() method to obtain a JtapiPeer object. The argument to this method is a classname which represents an object which implements the JtapiPeer interface. This object and the classname under which it can be found must be supplied by the vendor of the implementation.
      2. Check with the vendor documentation for any external configuration files needed. For example a vendor is using the file TSAPI.PRO to provide the IP Address of the Jtapi Services server.

      Let me know if any of the above worked for you.

      Regards

  10. hey gvag, thank you for your help!

    i’m using now the xtapi framework for jtapi, and it works!!!

    Thanks for you help!!!

  11. hey hi!
    I’m a newbie with java and it’s driving me crazy to start using JTAPII!
    Firstly WHAT is a PBX?? and after downloading JTAPI 1.4 from Sun’s WebSite how initialize them? they’re all *.java files!!

    Hope someone’ll answer!
    Thanks in advice

    • Napster,

      PBX is an telephone system for business such as Cisco, Avaya or Nortel. Unfortunately if you don’t have a PBX you can’t use JTapi unless if you use the emulator provided from the GJtapi project http://gjtapi.sourceforge.net/.

      Hope that helped.

  12. Hi,

    I am trying to use JTAPI to make a connection with a Panasonic PBX. I´ve installed the TSP that created the “Panasonic KX-TD TSP” provider over the Tapi list in my telephony options. Is there a possibility to make a connection with this provider using JTAPI?

    Thanks in advice!

  13. Hello,

    I am looking to develop a program for Pc to phone using Modem and HeadPhone without any PBX.I know JTAPI requires Implementation so which implementation will work for my requirement. Please help me out.Code return by you is very clear to me.

    Thanks and Regards
    Kapil Sharma

  14. hi,

    i hava run the class JTapiDiscovery and become the e
    “Exception in thread “main” java.lang.NullPointerException at jtapiextension.discovery.JTapiDiscovery.main(JTapiDiscovery.java:31)”

    My 31. code-line is:
    for (int i = 0; i< addresses.length; i++) {
    System.out.println("Address : "+addresses[i].getName());
    }
    After the exception i try to run the code again(c.a 5 times) and then i become the right output about my available address und available terminals. I don't know why the class JTapiDiscovery run not always right.

    Its very nice when you can help me. Thanks you.

    • Pink,

      Usually the JTapi services are using a kind of security database where the addresses and terminals are listed in order to be available for the JTapi services. That is if you have terminals with address 100, 101, 102, 103 and you want to make available to the JTapi services the terminals 101, 102, then you have to listed in the security database of the PBX component that is responsible to provide the JTapi services. Thats not the default way of working and this depends on the implementation of each vendor.
      I believe that the issue that you face have to do with PBX restrictions, aka none of your addresses/terminals can be accessed by the JTapi.

      Let me know if that helped. If not please provide the full code.

  15. Thank you for your answers. After checking the document of cisco under the link http://www.cisco.com/en/US/docs/voice_ip_comm/cucm/jtapi_dev/3_1/JTAP_con.html, i have known, that i must add Observer to see the available Address and Terminals of my provider.
    “Before continuing, applications must add a Provider observer and await a notification that the Provider is in service.”
    Now they work very fine. Here is my extra code:
    ……
    Provider myprovider = ProviderService.getProvider();
    final Condition inService = new Condition();
    myprovider.addObserver(new ProviderObserver(){
    public void providerChangedEvent(ProvEv[] eventList){
    if(eventList == null) return;
    for(int i = 0; i<eventList.length;i++){
    System.out.print("Provider Ereignisse Liste"+ eventList[i]+"n");
    if(eventList[i] instanceof ProvInServiceEv){
    inService.set();
    }
    }
    }
    });
    inService.waitTrue();
    try {Address[] addresses……..

    • Good.

      i was thinking create a forum or wiki section where specific vendor implementation notes could be kept and everybody will be able to contribute. What do you think?

  16. i find you have worked for a time with JTAPI. Your explanation is simply to understand about provider, terminal, connection, state of connection, state of call,…i will send you my note for your class in the cisco JTAPI. I have began since 4 weeks to code JTAPI for cisco, thus i have not much experience with JTAPI as you and i can’t speak english good. Keep it up. We wait your next entries about JTAPI.

    • What would you think about a series of tutorials for SIP development? I am thinking to start working on that soon.

  17. i work with CUCM 4.2.3 Cisco with SCCP.

  18. @pink Hi Pink

    I tried your code. It worked great. But the problem is if I try to Dial a new number that i have not called at all before I am getting “Address is out of service” Exception. But if I try the same number couple of times I am able to place a call. I am using cisco Call Manager. Please let me know if you have any Idea. Thanks.

  19. there are only one cause: you don’t have an observer for your provider. I have posted my extra code for this problem. Please look at my comment for gvag on 20.July.

  20. @pink
    I have the same code in my class. Say i am trying to a call a cell phone I get this error first time. If I try it again then the call is placed. I mean to say it has to be in my history that I called this number before.

  21. @pink

    Hi Pink

    I am not sure but do i need to have any pbx installed along with the call manager to route the calls to any phone. Please let me know.

  22. i need to build a screen using java in which i need to show the number when a call comes in. i need to pop the number when call comes in. i have cisco ip phone installed. i am new to telephony application. can you give me an idea how to start up and what is needed.

    • Hi chinna,

      You need to take a look at observers, that after you initialize the provider and have the terminal and addresses in place then you should place a callObserver.

  23. don’t mind, can you explain me in detail.

    thank you.

  24. hi gvag, to read the number of caller is not difficult, i use the code in the example of cisco-jtrace- and i can read. i tried to use only the classes of normal JTAPI and my programm works fine.

  25. Hello everyone!

    I am new with this stuff about TAPIs… but I have to develop a software with Java and using a Panasonic KX-TDA100. The main problem is that I don´t know how to connect Java with the PBX. Can I use JTAPI? I also read something about TAPI 2 CTI… but I don´t know what is that. As I said, It´s my first project in this area.

    Thanks. Alberto.