Apama Documentation : Connecting Apama Applications to External Components : Working with Connectivity Plug-ins : Developing connectivity plug-ins : Requirements of a plug-in class
Requirements of a plug-in class
Java and C++ plug-ins are identified in the plugins section of the configuration file for the connectivity plug-ins. The configuration can specify the following for each plug-in:
*classpath. For Java plug-ins, a list of classpath elements (or a single entry), which can be absolute or relative to the location specified by the directory configuration option.
*libraryName. For C++ plug-ins, specifies the base name of the library file (excluding lib, .dll or .so) to load.
*directory. An optional path to the classpath elements (for Java plug-ins) or to the plug-in library file (for C++ plug-ins). Without this, the classpath elements should be absolute or relative to the correlator's current working directory, or plug-in library files should be on the correlator's LD_LIBRARY_PATH (UNIX) or PATH (Windows). See Deploying plug-in libraries for information about third-party libraries loaded by plug-ins.
*class. A required name of the class of the plug-in. For Java plug-ins, this must include the package. For C++ plug-ins, this must exclude the package name.
*globalConfig. An optional map of configuration values which are defaults for the plug-in instances used in chains. The globalConfig configuration can be overridden by configuration per chain.
For example:
plugins:
JSONCodec:
directory: ${APAMA_HOME}/lib/
classpath:
- json-codec.jar
class: com.softwareag.connectivity.plugins.JSONCodec
The named class must subclass AbstractCodec or AbstractTransport. This will typically be done by subclassing AbstractSimpleCodec or AbstractSimpleTransport which are themselves subclasses of AbstractCodec and AbstractTransport respectively.
If a transport (or in some circumstances, a codec) can achieve better performance by handling many events in a single call, then it would subclass AbstractCodec or AbstractTransport.
The classes are summarized in the following table. They are all in the com.softwareag.connectivity namespace. See the API Reference for Java (Javadoc) and API Reference for C++ (Doxygen) for more information.
Base class
Subclasses deal in
Minimum methods subclasses need to implement
AbstractCodec
Batches of messages
sendBatchTowardsTransport
AbstractTransport
Batches of messages
sendBatchTowardsTransport, sendBatchTowardsHost
AbstractSimpleCodec
Individual messages
transformMessageTowardsHost, transformMessageTowardsTransport
Note that every message results in at most one message out.
AbstractSimpleTransport
Individual messages
deliverMessageTowardsTransport
All of the above classes also provide members or default implementations of:
*Member chainId
*Member config
*Member LOGGER for logging (see below)
*Member hostSide - the next component in the chain towards the host
*Member transportSide - the next component in the chain towards the transport (for codecs only)
*start
*hostReady
*shutdown
The start, hostReady and shutdown methods can be overridden if required.
Plug-in class constructor
For Java, the Codec and Transport plug-ins must provide a public constructor with the following signature:
public <ClassName>(java.lang.Map<String, Object> config, String chainId, org.apache.log4j.Logger logger) throws Exception, IllegalArgumentException
For C++, the signature should be:
public: <ClassName> (const std::string &pluginName, const std::string &chainId, const map_t &config)
where:
*config is any instance-specific configuration.
*chainId is the chain's identifier as named in the configuration.
*logger is a log4j Logger object which can be used to log to the system log file (Java only - the C++ Abstract types have an accessible Logger member).
*pluginName is the plug-in's name. It must be passed to the AbstractCodec/AbstractTransport constructor.
Note that the Abstract classes all have a matching constructor, so a minimal implementation for Java would be:
public <ClassName>(java.lang.Map<String, Object> config,
String chainId, org.apache.log4j.Logger logger) throws Exception,
IllegalArgumentException {
super(config, chainId, logger);
}
Or for C++:
public:
<ClassName>(const std::string &pluginName, const std::string &chainId,
const map_t &config)
: AbstractSimpleTransport(pluginName, chainId, config) { }
These parameters are all available as members on the Abstract classes.
The constructor may examine the contents of the configuration and extract values from it. If there is an error in the configuration, an exception can be thrown. This will be logged as an error and will prevent the correlator from starting.
Using AbstractSimpleCodec and AbstractSimpleTransport
The AbstractSimpleCodec and AbstractSimpleTransport classes handle batches by iterating through each message within a batch and calling one of the methods listed above for each message. For Java codecs, the result of the transform method replaces that message in the batch. For C++ codecs, the transform method passes a reference to a message which can be mutated or the message discarded if the method returns false. By default, messages with a null payload are ignored by the AbstractSimpleCodec and AbstractSimpleTransport classes, but subclasses may override methods to handle them (see the API Reference for Java (Javadoc) and API Reference for C++ (Doxygen) for details).
Exceptions from processing one message are logged by default (this behavior can be overridden by implementing handleException) and the next message is then processed.
To deliver events to the correlator, transports call the sendBatchTowardsHost method on the hostSide member of AbstractSimpleTransport, passing a batch of messages as a List<Message> (they can use Collections.singletonList() if needed).
Using AbstractCodec and AbstractTransport
Chains are bidirectional, passing events to and from the correlator. The order of plug-ins within a chain is defined by the configuration file: first the host plug-in, then codecs, and finally a transport. Plug-ins are connected such that the hostSide and transportSide members of AbstractCodec point to the previous and next plug-in in the chain, and for AbstractTransport, hostSide points to the last codec (or the host plug-in if no codecs).
Events from the correlator are sent to the first codec (or transport if there are no codecs). Each codec should pass the message through to the next component, invoking the sendBatchTowardsTransport method on the transportSide member.
Events to the correlator originate from the transport and are delivered by invoking the sendBatchTowardsHost method on the hostSide member which delivers the events to the last codec. The last codec should invoke the sendBatchTowardsHost method on its hostSide object, thus traversing plug-ins in the reverse order. For Java, transports must always provide hostSide a batch of messages as a List<Message> (they can use Collections.singletonList() if needed). For C++ plug-ins, the batches are passed as a pair of start and end pointers to Message. The batch is defined as starting from the message pointed to by start and up to just before the message pointed to by end - similar to begin() and end() iterators on C++ containers. Thus, the messages in a batch can be iterated with a loop such as:
for (Message *it = start; it != end; ++it) {
handleMessage(*it);
}
Plug-ins are provided with a HostSide and (for codecs only) TransportSide interface view of the next component in the chain (as members of AbstractTransport or AbstractCodec).
Codecs are not required to maintain a one-to-one mapping of events going in and out. They may choose to discard or merge multiple messages or split a message into separate messages.
C++ plug-ins exporting symbols
C++ plug-ins also require a macro which exports the symbols that the correlator needs to create and manage the plug-in object. The macro takes the base name of the class - the class's name excluding any package. Software AG recommends declaring codecs and transports in a package to avoid name collisions, and using the macro within the namespace declaration, or where a using statement applies. For example:
#include <sag_connectivity_plugins.hpp>
using namespace com::softwareag::connectivity;
namespace my_namespace {
class MyPlugin: public AbstractSimpleTransport
{
public:
MyPlugin(const std::string &name, const std::string &chainId,
const map_t &config)
: AbstractSimpleTransport(name, chainId, config)
{
}
virtual void deliverMessageTowardsTransport(Message &m) {
LOGGER.info("deliverMessageTowardsTransport()");
}
...
};
SAG_DECLARE_CONNECTIVITY_TRANSPORT(MyPlugin)
} // end my_namespace
Copyright © 2013-2016 Software AG, Darmstadt, Germany.

Product LogoContact Support   |   Community   |   Feedback