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
chainIdMember
configMember
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