Components

EAISystem
XMLConfigurable
Channel
PoolingFunction
ListeningFunction
WritingFunction
Resource
SubmiterAware

 

EAISystem
EAISystem is the main class of the Submarine engine. It is a Runnable class so the launcher class could create a thread to run it. The setConfig() method of this class initializes all the core elements (Channels, PoolingFunctions, ListeningFunctions, WritingFunctions and Resources) from the xml configuration file. The run() method is responsible to open the declared resources, to start the listeners, to create threads for driving the pooling functions and running the channels. The stop() method is used to terminate the engine in a clean way.

EAISystem implements two other interfaces.

  Submiter

The Submiter interface allows callers to send messages in the eai engine using the submit() method.
This interface permits also to retrieve the ConnectorControler by calling the getControler() method on the submitter.

  ConnectorsControler

The ConnectorControler interface gives caller a way to find the core elements declared in the configuration file using the methods getResourceById(), getWriterById(), getListenerById(), getPoolerById() and getChannelByName().

XMLConfigurable

The XMLConfigurable interface has a unique method init(org.w3c.dom.Element). This method allows implementers to receive an XML elements as its initialization parameters.
Conventionally, the implementer should not take care where the xml element come from. It should either not take care of the name of the element. It should only be interested with the content: attributes and children elements and text nodes.
All the core elements classes of the Submarine project implements this interface, in order to be initialized from the xml configuration file of the project.

There is two main advantages of this interface. The main is that all the configurations class could be stored in a single xml file. The second advantage is that a class configuration can be encapsulated in an other class configuration, giving classes the opportunity to reuse existing components. The ContextSerializer is a good example of that.

Channel
The Channel class is the second most important class in the Submarine project. Channel is a Runnable class because associated with a ChannelInfos class instance, it executes a set of transformations rules defined in the ChannelInfos (loaded from the configuration file) in a thread created by EAISystem.
The run() method sleep until a message is drop in the waiting queue of the EAISystem. Then, it loads the channel information associated with the message and execute the following steps:
  1. Archiving IN : Archiving the message (java.lang.Object) according to the configuration.
  2. Parsing : Transforming the message (java.lang.Object) into XML (org.w3c.xml.Document) using the parser description.
  3. Archiving IN_XML : Archiving the parsing result (org.w3c.xml.Document) according to the configuration.
  4. Transforming : Transforming the parsing result (org.w3c.xml.Document) into another document (org.w3c.xml.Document) using a XSLT processor (javax.xml.transform.Transformer).
  5. Archiving OUT_XML : Archiving the transformation result (org.w3c.xml.Document) according to the configuration.
  6. Serializing : Transforming the transformation result (org.w3c.xml.Document) into a java object (java.lang.Object)
  7. Archiving OUT : Archiving the serializing result (java.lang.Object) according to the configuration.
  8. Writing : Calling the writer putDocument() method with the serializing result as parameter.

The channel is responsible of managing errors. If an error (Exception) occur while processing the channel, an error message is created and written in the archive directory.

  Message
A channel process messages. A Message instance in the Submarine project is a set of information associated together to process correctly the initial object (the document) send to the Submarine engine by a client. These information are:
  • the document (java.lang.Object) itself 
  • the routing information (see class RouteInfos) that select the channel 
  • the channel information (see class ChannelInfos)
  • the message context (see Message.MsgContext class) that hold states and the unique message identifier (docId).

A message is uniquely identified in the engine by a docId. The docId is a string build in the following way: serverID-yyyymmdd-hhnnss-counter where ‘serverID’ is the Submarine engine identifier (see global/server/@id configuration value) and ‘counter’ a number starting from 0 to 9999.

  ConnectorsControler
The context of a message follow the message from its submission in the EAISystem to the processing by the writer. 
The context is designed to hold several data like quality of service, transaction or security. But in the actual implementation, context only hold string properties (java.util.Properties) in its attribute member.
PoolingFunction
The PoolingFunction interface (extends XMLConfigurable) is the contract passed between the Submarine engine and connectors to one kind of source.
This kind of source represents the systems containing documents to submit to the engine but that need a client request to return the new documents. Those systems has no way to notify a potential client of the arrival of a document. So the only way to integrate them in a light manner is to pool on the system at a particular frequency.
For instance file system is of that kind, EAI need to pool on a directory, waiting for new files.

The PoolingFunction interface is not used directly either by the EAISystem. But it should be implemented by any constructor (or developer) that need to access to that kind of source.
The EAISystem drives these implementation in a dedicated thread. The call of the PoolingFunction methods are always in the same thread context so implementation can use internal members safely.
The implementation of this interface is based on the following methods:

  1. hasNewDocument() is called by EAISystem, after a sleep, to know if new documents are available. If true, EAISystem call getNextDocument().
  2. getNextDocument() is called by EAISystem in a loop until this method return a null value. In the other case, EAISystem submit the result in the engine using getRouteInfos().
  3. notifyResponse() is called by EAISystem after the submission to the engine (either synchronously or asynchronously) to tell the implementation what is the response and is the submission failed or not.
  4. getFrequency() is called after each call to hasNewDocument() that returns false or after a call to getNextDocument() that returns null in order to suspend the thread for a certain delay.
  5. getRouteInfos() is called after each call to getNextDocument() that returns an object in order to get the routing information for the submission. The result of this call could be dependant to the last document returned.

It exists a sub interface of the PoolingFunction interface, named PoolingFunctionWithContext. This interface add a parameter to the getNextDocument() method. This parameter is an initialised message context that could be used by the implementation to fill particular attributes associated to the resulting document.
The EAISystem know dynamically if the PoolingFunctionWithContext is implemented. If so, it prefers to call its getNextDocument() method in place of the PoolingFunction one.

ListeningFunction
The ListeningFunction interface (extends XMLConfigurable) is the contract passed between the Submarine engine and connectors to one kind of source.
This kind of source represents the other case of source that those represented by a PoolingFunction. A system connected to the EAISystem by a ListeningFunction is a system that notify its clients by a callback or a special event. ListeningFunction implementation is responsible to manage their threads (start and stop it) and to submit documents to the Submarine engine (using the Submiter and SubmiterAware interfaces).
A mail system is an example of this type of source because it knows how to informs a client of the arrival of new mail (see javax.mail.Folder.addMessageCountListener() ). Another example is the SubMLListener that wait xml documents on a TCP port.

The implementation is based on one method : listen(). This method is called in a dedicated thread by EAISystem. It must be a blocking implementation while the calling thread is interrupted. In that case, the implementation must release any resources and threads before returning. So it is required by the implementation to check as soon as possible the interrupted state of the calling thread.

WritingFunction
The WritingFunction interface (extends XMLConfigurable) is the contract passed between Submarine engine and connectors designed to send documents to the underlying system.

WritingFunction implementation are used by the channel processing thread. So, because writers are shared in Submarine, the implementation must be multithreaded. Implementation are based on two methods, both designed to send message to the system.

  • putDocument() is called when the write to the underlying system must be asynchronous. It returns true or false whether the write succeeded or not.
  • putSyncDocument() is called when the write to the underlying system must by synchronous. It returns an object as a response to the document write.
Resource

The Resource interface (extends XMLConfigurable) is designed for hosting data and objects linked to an underlying resource. For instance it is useful to host a connection pool to a database.
This implementation is based on two methods: 

  1. open() is called by the Submarine engine at its start time in order to tell the resource to create any underlying sessions and connections.
  2. close() is called by the Submarine engine just before the engine stops but after all the connectors were interrupted or destroyed. 

The implementation of a Resource must have its own interface to be used by connectors. The typical way to use a Resource instance is to get the ConnectorsControler interface (from a Submiter instance) and by calling the getResourceById() method, and then cast the result into the specific interface. Another way could be to pass through a jndi service.

SubmiterAware

The SubmiterAware interface should be implemented by any of the core components that need to have a Submiter reference. Each time a component is to be initialized, EAISystem previously check whether the class implements the SubmiterAware interface. In this case, the setSubmiter() method is called by EAISystem with the Submiter as a parameter. Then the init() method of the XMLConfigurable interface is called.
The implementation of this interface should save the Submiter reference in a private member in order to use it when it wants. The Submarine engine ensure that the reference will be valid until the engine stops.