This document contains the Frequently Asked Questions abaout the use of the Avaya Conferencing Provider Interface (ACPI) in Meeting Exchange Release 5.1 and later releases.
The Avaya Conferencing Provider Interface (ACPI) is an object-oriented, programming interface, written in Java. ACPI can be used by any application that can make a Java call and supports Java version 5.0 or newer.
ACPI consists of two components:
The first available implementation of ACP API is ACP-MODAPI-IMPL. MODAPI is a proprietary Avaya protocol used to control Meeting Exchange conferencing providers. It can be used to interface with the following supported conferencing providers:
The ACP API SDK includes the following JAR files and a detailed reference guide (javadocs):
Note: versionnumber is the version number for each JAR file.
The above JAR files are required to be on the classpath for ACP API.
In addition, the programmer's guide 'Meeting Exchange 5.0 Bridge Control API (BCAPI) Guide' provides a detailed description of the Bridge Control API methods and how to use them to manage conferences. The ACPI SDK, BCAPI SDK and programmer's guide are available on the DevConnect portal.
ACP API has a minimum system requirement of Java version 5.0 or above.
Recommended reading and reference for developers includes the following documentation available on the DevConnect portal:
Programmer's Guides:
Javadocs:
Sample Applications:
ACP API is a java based interface which is extensible and minimizes compile time and run time dependencies. It is a superset of BCAPI and supports all BCAPI conference control functionality in addition to new operator functionality. It is the recommended Bridge Control API for new customer development as it has better performance and functionality than BCAPI.
ACP API exposes the ability to control Conferences, Callers and Queues. This can used to write applications like BridgeTalk, Avaya Audio Console, etc
An application uses the ConferencingProviders.getConnection () method to connect to the conference bridge. The ConferencingProviders is used to get the Connection via Java SPI mechanism and requires a set of bridge parameters.
How does an application connect to the MX Enterprise 5.1 conference bridge?
The ACP-MODAPI-IMPL supports two URI syntax schemes:
By default, the command port (cmdport) is 20002 for modapi and 20004 for smodapi. The default UDP port for nat connections is 20008 while the TCP port is 20008 for modapi and 20010 for smodapi.
Some valid URI examples are:
Please refer to ACP API javadocs and sample examples for further details.
There is a bridge limit on the number of operators / API connections. The maximum limit is 140. These can be split between BridgeTalk, ACPI and BCAPI, but the total is still 140. In addition, the bridge may have been licensed / restricted to a lower limit.
The bridge has a hard limit of 2000 conference rooms (or possibly the bridge port capacity divided by 2, whichever is smaller).
No, it will use the next available port. It starts at 5020 and works its way up to 5040, after which it gives up and tries random ports above 0xB000
This is the same as it was with MX 5.0 and BCAPI, i.e. by using "dcbmaint" utility
Once the limit has been reached, no new conferences can be created. Attempts to create new conferences will fail.
The "modapi" and "smodapi" protocols communicate over three network connections:
A TCP connection from the client (from any unused port) to the conferencing provider (by default, to either port 20002 for modapi or 20004 for smodapi) used to send operations for execution to the conferencing provider.
A TCP connection from the conferencing provider (from any unused port) to the client (by default, to the first unused port in the range 5020 - 5040, otherwise any unused port) which is used to receive events from the conferencing provider.
A UDP connection from the conferencing provider (from 20008) to the client (by default, to the first unused port in the range 5020 - 5040, otherwise any unused port) which is used to receive active talker information from the conferencing provider.
This exception is thrown when the ACP API cannot find an implementation. There are two main causes for this exception:
By default, ACP API will use the class loader Thread.currentThread().getContextClassLoader() to search for ACPI implementations. Alternatively, the class-loader can be specified by using the alternate ConferencingProviders.getConnection() method which takes the class-loader to use as a parameter.
Most JavaSE applications do not modify the Thread.currentThread().getContextClassLoader(), for this class of application, the solution to this problem is to ensure that all the required JAR files for the ACPI implementation supporting the required protocol are on the class-path.
JavaEE applications run within a JavaEE container. JavaEE containers are designed to host multiple applications at the same time and often control the class-loaders of applications in order to isolate the applications running inside the container. For this class of application, it may be necessary to consult the JavaEE container's documentation to determine the deployment descriptor(s) and/or container configuration settings that should be applied in order to ensure that all the required JAR files for the ACPI implementation supporting the required protocol are on the class-path of the Thread.currentThread().getContextClassLoader().
This may occur due to the following reasons:
ACPI is the new Avaya API for real time conference control replacing BCAPI. In order to allow customers to migrate pre-5.1 releases of Meeting Exchange applications developed using BCAPI, the ACPI comes with a BCAPI legacy adapter that converts BCAPI objects, events and command model into corresponding ACPI objects, event and operation model. Due to limitations in the BCAPI design, it is not possible to expose the new functionality provided in ACPI through BCAPI. Therefore customers wishing to access new APCI functionality need to rewrite the conference control code to use ACPI.
No, ACPI does not support connections to Meeting Exchange 4.1 or Meeting Exchange 5.0.
During an upgrade to Meeting Exchange 5.1, the following API related issues that must be addressed:
Yes, in a scenario of mixed environment comprising of Meeting Exchange 4.1, Meeting Exchange 5.0 and Meeting Exchange 5.1 bridges, the following steps should be followed:
Before an operation can be executed, one needs to answer three questions:
If the application needs to execute operations without reference to a specific user/executor authentication, then the operation can be executed using the available connection object as shown below:
object.executeAs(connection, operation) or object.execute(operation)
Conference participants and moderators can mute lines in several ways, but only the endpoint participant can unmute themselves. A line can be in a muted state as a result of participant actions or applications invoking ACPI methods.
The line is muted as a result of lecture-mode or when the application invokes operationFactory.newMute().on() using ACP API . The line stays muted until the line is disconnected or endPoint participant unMutes themselves.
Once there is an established Connection with the bridge, one can use it to get an operationFactory and invoke a Silence operation as shown below:
One can also toggle between both the above states as shown below:
Once there is an established Connection with the bridge, one can use it to get an operationFactory and invoke a Hold operation as shown below:
One can also toggle between both the above states as shown below:
Once there is an established Connection with the bridge, one can use it to get an operationFactory and invoke a Hold operation as shown below:
One can also toggle the participant between moderator and conferee as shown below:
Once there is an established connection with the bridge, one can invoke the method getRooms() on the connection object and it will return an array of type Room. This array can be queried or iterated to get the size which is basically the number of sub-conference rooms as shown below:
Once a connection to a conference bridge is established, invoke the connection.getOperationFactory() method to get an OperationFactory object which can be used to move endpoints between conferences. The code for moving endpoints between conferences is shown below:
It is similar to moving endpoints between conferences. Once a connection to the bridge is established, invoke the getOperationFactory() method to get an OperationFactory object. It is followed by operationFactory.newPlaceInSubconference() and invoke the PlaceInSubconference.setRoom() method to set the sub-conference to move into.
Because all objects in Avaya Conferencing Provider API (ACP-API/ACPI) are remote, rather than
update the object directly the application will
need to execute a ModifyDetails
operation. This (as with all Avaya Conferencing
Provider API (ACP-API/ACPI) operations)
creates a Future
which is executed upon a specific object. The operation is
then dispatched to the bridge and the result
retrieved later.
The first thing to note is that ModifyDetails
is a masked operation –
that means that it only operates on the
specific values selected and thus you need only add
properties for elements that
you wish to change; all other properties
will remain unchanged. You will note from the javadocs that the
addPropertyValue
and setPropertyValues
take
String
to object
mappings. These map the property name (the
String
) to its value (the
object
).
If we look at EndPoint
(as an example) we will see things like ACTIVE,
FROM_DISPLAY, FROM_NUMBER, NAME, etc., which correspond
to the properties of the EndPoint
. We can then reference the appropriate get
operation in order to see the defined type
required for that property’s value. So, for example, the CUSTOM_FIELDS property has a
corresponding getCustomFields
function
which returns a List<String>
and, by association, we know the
ModifyDetails
operation must supply a
List<String>
. If we test this “get” function we will also note that it is
a List of length three, corresponding to the
three custom fields available.
The following snippet illustrates how to update the CUSTOM_FIELDS of an EndPoint:
/*[ ... ]*/ ModifyDetails modifyOperation = operationFactory.newModifyDetails() ; HashMap<String,Object> details = new HashMap<String,Object>() ; List< string > customFields = new Vector< string >() ; customFields.add( "Field 1" ) ; customFields.add( "Field 2" ) ; customFields.add( "Field 3" ) ; details.put( EndPoint.CUSTOM_FIELDS, customFields ); modifyOperation.setPropertyValues( hashMap ) ; try { endPoint.execute(modifyDetails).get() ; } catch (InterruptedException e1) { e1.printStackTrace() ; } catch (ExecutionException e1) { e1.printStackTrace() ; } /*[ ... ]*/ < /string >< /string >
NOTE: It's important to note that many Conferencing
objects reflect status and,
although it may seem intuitive to use the NAME
property to store a “name”, you should use the CUSTOM_FIELDS to store application specific
information.
NOTE: It is prudent to setValidating
to true in order to prevent partial
updates.
The behaviour is correct. Although the extended message suggests that the operation will be available in the future ...
Complete exception message from ModifyDetails
operation:
com.avaya.conferencing.api.acp.control.exceptions.OperationNotEnabledException: \ MODIFY_DETAILS operations on class \ com.avaya.conferencing.api.acp.control.EndPoint \ objects are allowed, howewever, they are not \ currently allowed on \ acp-control:op1483@smodapi://mx-server:20004/ep/c5682
... such a request will, in fact, be persistently rejected. This is because, although an
operator’s EndPoint
is modelled with the
same object as a participant EndPoint
, they are functionally quite different.
The application should not attempt to update an
operator’s EndPoint
. Instead, where the application needs custom properties for
operators in your application, you should model and
manage them locally (i.e. within your application).
This is a common problem; fundamentally, you might think of the bridge objects as existing in many places at the same time – most significantly, they exist both on the bridge AND in conferences; or, to state it inversely, they remain on the bridge, even when they are in a conference.
The most common manifestation of this is reception of duplicate events when the application
uses generic, top-level listeners, instead of
using the specific event listener functions provided. The following snippet illustrates a
common (but incorrect) means of listening
for children on the Connection
object.
Snippet illustrating the creation of a "generic" ChildListener
on the
Connection
/* ... */ public class GlobalChildListener extends ChildListener { @Override void childAdded( ChildEvent event ) /* ... */ @Override void childRemoved( ChildEvent event ) /* ... */ } /* ... */ public class Application { Connection bridge ; GlobalChildListener bridgeSpy ; /* ... initialise ACP-API connection ... */ bridge.addChildListener( bridgeSpy ); /* ... */ } /* ... */
When this application adds an EndPointListener
to Conference
objects (as in the snippet below) it will start to receive
duplicate events. This is because the EndPoint
and Conference
objects are children of the Connection
,
whilst the EndPoint
is also a child of the Conference
.
Snippet illustrating adding the EndPointListener
to the
Conference
object
/* ... */ public class GlobalChildListener extends ChildListener { @Override void childAdded( ChildEvent event ) { if( event.getChild() instanceof Conference ) { Conference c = (Conference)event.getChild() ; c.addChildListener( new GlobalChildListener() ) ; } /* ... */ } /* ... */ } /* ... */
This is further exasperated when we introduce the *PropertyChangeListeners
which
monitor property changes on child objects.
The solution is to manage where and how the application listens for changes; specifically,
the application should use the add listener functions
(e.g. addConferenceListener
, addEndPointListener
) wherever
possible, rather creating generic child listeners. It is thus
implied that listening for EndPoint
objects on the Connection
is
discouraged (because there is no function for it) and
by extension, the application should addConferenceListener
, and then
addEndPointListener
to those Conference
objects. The following illustrates the recommended implementation.
Snippet illustrating correct use of listeners for Conference
and
EndPoint
objects
/* ... */ public class EndPointListener implements com.avaya.conferencing.api.acp.control.events.ConferenceEndPointListener { @Override public void childAdded( ChildEvent addEvent ) { /* ... do something to endpoint upon arrival in conference ... */ } /* ... */ } /* ... */ public class ConferenceListener implements com.avaya.conferencing.api.acp.control.events.ConferenceListener { @Override public void childAdded( ChildEvent addEvent ) { addEvent.getChild() .addEndPointListener( new EndPointListener() ) ; } /* ... */ } /* ... */ public class Application { public static void main( String args[] ) { Connection bridge ; /* ... connect to bridge ... */ bridge.addConferenceListener( new ConferenceListener() ) ; /* ... */ } }