[Asterisk-java-cvs] CVS: asterisk-java/xdocs design.xml,1.1,1.2
Brought to you by:
srt
From: Stefan R. <sr...@us...> - 2005-07-11 17:58:19
|
Update of /cvsroot/asterisk-java/asterisk-java/xdocs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22374/xdocs Modified Files: design.xml Log Message: Finished first draft Index: design.xml =================================================================== RCS file: /cvsroot/asterisk-java/asterisk-java/xdocs/design.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -p -r1.1 -r1.2 --- design.xml 11 Jul 2005 01:05:00 -0000 1.1 +++ design.xml 11 Jul 2005 17:58:10 -0000 1.2 @@ -25,37 +25,247 @@ <meta name="keywords" content="Asterisk,asterisk,Java,java,Manager API,FastAGI,AGI"/> <body> <section name="Design"> - <p>This document shows a brief overview of the design of - Asterisk-Java and the requirements that lead to that + <p>This document gives a brief overview of the design of + Asterisk-Java and the requirements that lead to this design.</p> <subsection name="Introduction"> <p>When I first stumbled upon Asterisk there haven't been many options to integrate your own applications.</p> - <p> First of all you have the possibility to write your own + <p> First of all you had the possibility to write your own Asterisk applications. That's the way many internal functions are implemented, for example Asterisk's Dial, Voicemail and Queue commands. This approach usually requires writing a small - module in C that uses Asterisk's internal API an is + module in C that uses Asterisk's internal API. It is compiled into a shared object that is loaded when Asterisk starts. Your application is then tightly coupled to Asterisk but has access to any internal structure.</p> <p>The second approach is to write AGI scripts. An AGI script is to Asterisk what a CGI script is to an - HTTP server.</p> + HTTP server. You can think of AGI as a means to + make your dialplan more dynamic by handing control + to an external process. As with CGI in its early + days Asterisk had to spawn a new short + lived process for each AGI request. When using + external application that consume a lot of resources + at startup (like spawning a Java Virtual Machine + when launching a Java application) this approach + has major drawbacks. These shortcoming have been + mitigated with the introduction of FastAGI that + doesn't spawn a new process for each request but + communicates with a long running process via + TCP/IP.</p> + <p>The third approach is to use Asterisk's Manager API. + The Manager API allows an external application to + query and change Asterisk's state by sending actions + and listening to responses and events. Comminication + occors via TCP/IP. Compared to AGI the Manager API + works without the need to operate on a concrete call + (in Asterisk parlance a channel).</p> + <p>The last approach is to talk to Asterisk via IAX + (Inter Asterisk eXchange protocol), a + UDP based protocol used by Asterisk to communicate + with other Asterisk servers and IAX enabled phones. + In contrast to AGI and the Manager API IAX allows + passing media streams, for example sending and + receiving audio.</p> + <p>Regarding the first approach a JNI based solution + (JAsterisk) is available that spawns a Java Virtual + Machine from within Asterisk and exposes Asterisk's + internal API. Development of JAsterisk seems to be + discontinued. Due to the involved tight coupling this + approach is questionable anyway.</p> + <p>Regarding option two and three I realized + there were two implementations of FastAGI for Java + but none for the Manager API. So I decided to build + a library to make those interfaces accessible from + Java applications. This is what became Asterisk-Java.</p> + <p>Regarding IAX there is a C library available and a + Java wrapper using Java Native Interface (JNI). + Several people are working on a pure Java + implementation though up to now no usable implementation + is available to the public.</p> </subsection> <subsection name="Requirements"> - <p></p> + <p>So what are the requirements for a library like + Asterisk-Java that focuses on AGI and the Manager API?</p> + <p>In one sentence: Asterisk-Java must be flexible, robust + and easy to use and maintain.</p> + <p>Flexible means you should be able to use it in a variety + of different environments, like standalone Java GUI + applications running on a user's desktop, servlets running + in a JEE servlet container, Java webstart applications, + or maybe even applets if anybody is still using them. + Being flexible also means you should have access to any + feature exposed by the corresponding Asterisk interface + and not be limited in any way due to using Asterisk-Java. + And finally being flexible also means it should be easy to + extend Asterisk-Java to support additional features. + This extensibility is important when you choose to run a + modified version of Asterisk that supports additional + actions and events through the Manager API or addtional + commands via AGI.</p> + <p>Robust means you can focus on your own + application and rest asured that Asterisk-Java "just + works". This implies you don't have to worry about things + like reconnecting after restarting Asterisk. Being robust + also means that Asterisk-Java must still work as expected + when put under heavy load.</p> + <p>Easy to use means there should only be a small number of + well defined and easy to understand classes and interfaces + that an application developer must be aware of. The + programming model should follow the style Java developers + are used to.</p> + <p>And finally easy to maintain means being well structured and + allowing for automated testing. Of course being easy to + maintain also requires extensibility as stated above as + Asterisk itself is in active development and new features + that Asterisk-Java must keep track of are added all + the time.</p> </subsection> <subsection name="Overall Design"> - <p></p> + <p>Let's have a look at Asterisk-Java's overall design.</p> + <p>You might have noticed that Asterisk-Java is composed + of two packages: one to support AGI and one to support + the Manager API. + Although these two packages are quite different (due to + the conceptual differences in the Asterisk interfaces + they support) they share several common design + principles. This section will highlight them before we + dive into the details of the two packages.</p> + <p>Asterisk-Java is based on interfaces. As you will see + below starting to use Asterisk-Java usually implies + getting an implementation of the interface you want to + use (i.e. AGI-based or Manager API-based). This + approach allows you to easily integrate Asterisk-Java into + IoC (inversion of control) containers like the Spring + Framework. It decouples your application from the internal + implementation of Asterisk-Java and supports testability as + you can easily substitue Asterisk-Java by some mock objects. + You can see examples of what that means when looking at + the source of Asterisk-Java's unit tests where I am using + <a href="http://www.easymock.org">EasyMock</a> for that + purpose.</p> + <p>To provide extensibility the commands and replies (for + AGI) and actions, repsonses and events (for Manager API) are + designed as class hierarchies with one abstract base + class at the top of each one. Asterisk-Java does not need to know + the concrete classes upfront so you are free to extend these + hierarchies as needed. There is a little difference in how + the two packages implement this strategy, but the general + concept is the same.<br/> + Note that this looks like the GoF Command Pattern and in + fact both are fairly similar. The + difference is that Asterisk-Java's commands and + actions are not self-executable. Instead of an + execute method there is a uniform way to "render" them + to the format Asterisk understands (i.e. convert them to a + String that can be sent over the wire). When using AGI this + is done by the AGICommands themselves that provide + a <code>buildCommand()</code> method, when using the + Manager API there is an ActionBuilder that renders + ManagerActions by using reflection.</p> + <p>Asterisk-Java depends on no external libraries at runtime. + This decision is crucial when using Asterisk-Java in special + environments where size matters. It also ensures that no + conflicts arise from different components requiring different + version of the same external library.</p> </subsection> <subsection name="AGI"> - <p><a href="images/agi.png"><img src="images/agi-thumb.png"/></a></p> + <p>This section describes the design of Asterisk-Java's support + for FastAGI. The corresponding Java package is called + <code>net.sf.asterisk.fastagi</code>.</p> + <p><a href="images/agi.png"><img src="images/agi-thumb.png"/> + (enlarge)</a></p> + <p>As you can see on the diagram the AGI package of + Asterisk-Java consists of three fundamental interfaces: + AGIServer, AGIScript and MappingStrategy.</p> + <p>The responsibility of an AGIServer is to listen for new + incoming AGI requests that an Asterisk server directs to + that server. The AGIServer must then choose the right + processor for that request, invoke it and provide it with + a means to send commands to Asterisk and receive the + corresponding reply.<br/> + Asterisk-Java includes DefaultAGIServer that contains the + default implementation of this interface.</p> + <p>To choose the right processor for an AGIRequest, the + AGIServer uses a MappingStrategy that returns an executable + AGIScript based on the request.<br/> + Asterisk-Java includes a + simple implementation of a MappingStrategy that is + based on reading a resource bundle and matching the URL. + It is called ResourceBundleMappingStrategy. If you + have other requirements regarding the mapping you can provide + your own implementation of the MappingStrategy interface.</p> + <p>The third important interface in this package is the + AGIScript. An AGI Script is the piece of code that is + invoked to service the request. An AGIScript is to + Asterisk-Java what a servlet is to a servlet container. + So when you want to expose your own Java based services + to Asterisk you must implement this interface. The AGIScript + interface is really simple: It contains only one method called + <code>service()</code> that is passed the AGIRequest and an + AGIChannel, that allows you to send AGICommands back to + Asterisk.<br/> + Asterisk-Java also includes an abstract base class that + implements the AGIScript interface and provides convenience + methods for sending commands. You can choose whatever + you like more: either implementing AGIScript or extending + AbstractAGIScript works fine.</p> </subsection> <subsection name="Manager API"> - <p><a href="images/manager.png"><img src="images/manager-thumb.png"/></a></p> + <p>This section describes the design of Asterisk-Java's support + for the Manager API. The corresponding Java package is called + <code>net.sf.asterisk.manager</code>.</p> + <p><a href="images/manager.png"><img src="images/manager-thumb.png"/> + (enlarge)</a></p> + <p>The important interfaces of Asterisk-Java's Manager + API package are ManagerConnection, ManagerEventHandler + and AsteriskManager.</p> + <p>In contrast to AGI communication between the Asterisk + server and your application is not initiated by Asterisk + when using the Manager API but has to be initiated by you. + Asterisk-Java provides the ManagerConnection interface that + is well suited for this purpose. Its responsibility is to + establish a TCP/IP connection to Asterisk (and reestablish + that connection in case of a restart of Asterisk or a network + failure), to enable its clients to send ManagerActions + and receive the corresponding ManagerResponses and to + dispatch events received from Asterisk.<br/> + Once you are connected to + Asterisk you can not only actively send ManagerActions but + you will also receive MangerEvents from Asterisk. + ManagerEvents usually inform your application about state + changes that occur within your Asterisk server, for + example due to a user dialing an extension or hanging + up the phone. To recieve these events you can implement + the ManagerEventHandler interface and register your + handler with the corresponding ManagerConnection.</p> + <p>Instances of the MangerConnection interface are usually + obtained from the ManagerConnectionFactory unless you are + using an IoC container. Asterisk-Java provides a default + implementation of the ManagerConnection interface called + DefaultManagerConnection.</p> + <p>Finally there is the AsteriskManager interface that + provides a higher level abstraction on top of the + ManagerConnection. It keeps track of Asterisk's state + by listening to all state changing events and provides + support for domain objects like Channel, Call and Queue + that make it easier for your application to interact + with Asterisk without diving into details.<br/> + Asterisk-Java provides a default implementation of the + AsteriskManager interface called DefaultAsteriskManager + that is initialized by passing a ManagerConnection.<br/> + You can use both interfaces at the same time thus using + the abstracted AsteriskManager where it is sufficient and + going back to ManagerConnection where needed. If you choose + to do so be sure to initialize the AsteriskManager before + you register any of your own ManagerEventHandlers.</p> + <p>Please note that the AsteriskManager interface is still + in an early state and the functionality exposed through it + is rather limited. This interface will certainly change + in the future so be aware of that when using it.</p> </subsection> </section> </body> |