Requirements of a plug-in class
Java and C++ plug-ins are identified in the
connectivityPlugins section of the configuration file for the connectivity plug-ins. See
Configuration file for connectivity plug-ins for detailed information.
The named
class must be a descendent of either
AbstractCodec or
AbstractTransport, unless it is a transport with a dynamic chain manager in which case the class must subclass
AbstractChainManager (see
Requirements of a transport chain manager plug-in class for more information about developing chain managers).
In most cases, the easiest way to write codec and transport classes is by subclassing AbstractSimpleCodec or AbstractSimpleTransport. However, in some cases, a plug-in can achieve better performance by directly subclassing the base class AbstractCodec or AbstractTransport; these classes support handling a batch of multiple messages in a single call.
The classes are summarized in the following table. They are all in the
com.softwareag.connectivity package (Java) or in the
com::softwareag::connectivity namespace (C++). 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, sendBatchTowardsHost |
AbstractTransport | Batches of messages | sendBatchTowardsTransport |
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. See also
Lifetime of connectivity plug-ins.
Plug-in class constructor
Subclasses should provide a constructor like the following, for Java:
public <ClassName>(org.slf4j.Logger logger,
TransportConstructorParameters params) throws Exception,
IllegalArgumentException {
super(logger, params);
...
}
or for C++:
public:
<ClassName>(const TransportConstructorParameters ¶ms)
: AbstractSimpleTransport(params)
{
...
}
The constructors for codecs follow the same pattern as for transports. The TransportConstructorParameters or CodecConstructorParameters object provides access to the plug-in's configuration and other useful information and capabilities, some of which are also made available as member fields for convenience.
Note that transports with an associated dynamic chain manager are created by the chain manager's createTransport method (for Java) or must have a public constructor with signature (const ManagedTransportConstructorParameters &, ...) where ... are any extra parameters passed in the createChain call (for C++).
In both Java and C++, there is a logger available using the
logger field (for Java, this is also passed into the constructor). Note that all messages logged using the logger will include the
chainId and
pluginName, so there is no need to explicitly add that information to each message. See the
API Reference for Java (Javadoc) and
API Reference for C++ (Doxygen) for detailed information.
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 there are 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.
Exporting the required symbols from C++ plug-ins
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 has one of the following names:
SAG_DECLARE_CONNECTIVITY_TRANSPORT_CLASS(class-name) This macro should not be used for transports with a chain manager.
SAG_DECLARE_CONNECTIVITY_CODEC_CLASS(class-name) SAG_DECLARE_CONNECTIVITY_TRANSPORT_CHAIN_MANAGER_CLASS(class-name) This macro is used for exporting a chain manager class.
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 MyTransport: public AbstractSimpleTransport
{
public:
MyTransport(const TransportConstructorParameters ¶ms)
: AbstractSimpleTransport(params)
{
...
}
virtual void deliverMessageTowardsTransport(Message &m)
{
logger.info("deliverMessageTowardsTransport()");
}
...
};
SAG_DECLARE_CONNECTIVITY_TRANSPORT_CLASS(MyTransport)
} // end my_namespace
Note:
For a chain manager, you should include the header file sag_connectivity_chain_managers.hpp instead of sag_connectivity_plugins.hpp which is used in the above example.