Apama 10.5.3 | Connecting Apama Applications to External Components | Working with Connectivity Plug-ins | Developing Connectivity Plug-ins | Lifetime of connectivity plug-ins
 
Lifetime of connectivity plug-ins
Instances of connectivity chains can be created in different ways. See Static and dynamic connectivity chains for detailed information.
At correlator startup:
*Each codec, transport and dynamic chain manager class is loaded using the classpath or libraryName.
*Each dynamic chain manager listed in dynamicChainManagers is instantiated using its public constructor and passing the managerConfig from the configuration file.
*The start() method is called on any dynamic chain managers. Chain managers can create dynamic chains at any point after this, though in practice, dynamic chains are usually created after correlator startup, once the Apama application is injected and running.
*Each chain listed in startChains is created and started (see below).
The correlator is only pingable and available for external access after all of the above operations have completed.
Whenever a new chain instance is created (either during correlator startup if listed in startChains, or at any time dynamically by EPL or a chain manager):
*The correlator determines the list of codec and transport plug-ins in the chain and the configuration for each as follows:
*If the chain is statically configured, the plug-ins and plug-in configurations listed under startChains are used.
*If the chain is being created dynamically, the chain manager implementation or EPL createDynamicChain call specifies which of the chain definitions listed under dynamicChains is to be used, and the configuration for this chain instance is prepared by replacing any @{varname} runtime substitution variables in the chain definition using the map passed in to createCreate or supplied by the chain manager.
*A new instance of each transport and codec class in the chain is constructed using the public constructor, as described in Requirements of a plug-in class. If the transport has a dynamic chain manager, the manager's createTransport method is used instead of calling the transport constructor directly (for Java) or extra parameters to the createChain call are passed through to the constructor (C++), which gives the chain manager the opportunity to pass extra information required by the managed transport (such a reference to itself).
*hostSide and transportSide members are set on all transport and codec plug-ins in the chain.
*Static and EPL-created chains are started automatically once created. Chain managers must explicitly call start() on the newly created chain when they are ready.
*The start() method is first called on all codecs in the chain.
*Then the start() method is called on the transport.
*Messages may begin flowing.
If any of the constructors or start() methods invoked during correlator startup throw an exception, that will be logged as an error and the correlator will fail to start. These methods should complete quickly; delays here will delay the correlator starting up. Blocking or long running operations should be handled by a separate thread.
After start() is called on all members of the chain, events may flow through the chain in either direction (if an EPL application is emitting events to the chain, they will be delivered as messages and delivered through the codecs towards the transport). The transport is permitted to send events hostwards, but they will be queued by the correlator until the application is ready for them.
Soon after the EPL application has been injected (and, if necessary, it has performed initialization), the EPL application should call ConnectivityPlugins.onApplicationInitialized(). At this point:
*hostReady() is called on every codec.
*hostReady() is called on the transport.
Dynamic chains that are created after onApplicationInitialized has been called will have hostReady called as soon as the chain is created.
If an exception is thrown by a plug-in's hostReady() method or by the start() method of a dynamically instantiated plug-in, that will be logged as an error and the chain will be disconnected. These methods should complete quickly; delays here will delay the EPL application. Blocking or long running operations should be handled by a separate thread. Any events previously sent to the host will now be delivered, but the order of all events from a chain will be maintained.
When the correlator is shut down (for example, via engine_management -s) or when the dynamic chain is destroyed by EPL or a dynamic chain manager, chains will be stopped:
*shutdown() is called on all chain managers (if any exist)
*shutdown() is called on every codec.
*shutdown() is called on the transport.
The shutdown() method gives chain managers an opportunity to destroy any chains they are managing in an orderly fashion.
The shutdown method on transports should make the transport discard any further messages sent to the transport, and unblock if any threads are currently delivering messages to the transport and are blocked. If possible, the sendEventsTowardsTransport method should be written to allow any blocking behavior to be unblocked when a shutdown occurs. For example, if a socket is being used by a transport, it should be shut down or closed so that any threads reading or writing on the socket's streams terminate.
Any messages delivered to a plug-in once the shutdown method has been called may be discarded by the plug-in. Messages may be delivered to a plug-in even after the shutdown call has completed, and the plug-in should not crash if that occurs.
If threads are required by a transport to deliver events to the transport or read from a connection, they would normally be started by the hostReady method and stopped and joined in the shutdown method.
Note:
For C++ plug-ins only: the plug-in object of each plug-in is destroyed, so the plug-in class's destructor (if defined) is called. No events should be flowing through a chain at this point.
Exceptions thrown from any of sendBatchTowards, transformEvent or deliverEvent will be logged and not propagated to their callers. Exceptions are not a suitable means to provide information between plug-ins as they are ambiguous if a large batch of events are being processed, and some codecs may choose to send events on a separate thread. Use messages to send such events; these can be null payload with information stored in the metadata, in which case most codecs will ignore the messages and pass them through.