The most fundamental element in FABRIQ is a message handler. The simplest possible message handler implements the interface IMessageHandler, which has a single method called bool Process(Message msg).

Message handlers are CLR classes that can be declared as “handler types” for use in a FABRIQ configuration file using an expression like:

<handlerType name="myHandlerType" class="MyClass, MyAssembly" codebase="http://codeserver/myAssembly.dll" />

The handler-type name is a unique name that is used to refer to the handler-type from a handler declaration that maps a handler-type into a pipeline (more on that later). The class does of course refer to the class that implements the message handler and the optional codebase attribute points to a location from where the assembly can be automatically downloaded by the FABRIQ runtime as needed (does that smell like “grid” to you?)

Message handlers can be composed with other message handlers into a pipeline if and only if they support another interface, which is, in fact, mandatory for any message handlers that want to play within the FABRIQ. Simple message handlers are only used internally for a few things. The additional interface IChainableMessageHandler has a single property IMessageHandler Next {get; } and allows creating single-linked lists of message handlers. (This is indeed and almost inevitably a bit similar to the guts of the Indigo connector or Remoting’s message sink model, but the similarity quite rapidly ends at this point and after those four net code lines of interface definitions).

A handler declaration declares an instance of a handler-type inside a pipeline. The handler declaration may contain an XML element with handler-specific configuration data that is read to the handler if it implements the additional interface IMessageHandlerConfiguration.

<handler type="myHandlerType">
   <
mycfg:data xmlns:mycfg="…">
      ...
   </
mycfg:data>
</
handler>

A pipeline is a special type of message handler that wraps around a chain of message handlers. A pipeline has explicit “head” and “tail” handlers that frame the handler sequence. Because the pipeline is a message handler itself, pipelines can also be composed into other pipelines. Reusable pipelines are declared as pipeline-types in configuration files.

 

<pipelineType name="myPipelineType">
   <
handler type="myHandlerType">
      <
mycfg:data xmlns:mycfg="…">
         ...
      </
mycfg:data>
   </
handler>
   <
handler type="otherHandlerType"/>
   <
handler type="yetAnotherHandlerType"/>
</
pipelineType>

To compose a pipeline-type into another pipeline-type, you refer to it with the pipeline element.

<pipelineType name="myPipelineType">
   <
handler type="myHandlerType"/>
   <
pipeline type="otherPipelineType"/>
   <
handler type="otherHandlerType"/>
   <
handler type="yetAnotherHandlerType"/>
</
pipelineType>

If you want to use the built-in pipeline composition rules, you need to use the endpoint element in the pipeline that marks the “middle” of the pipeline and the anchor for composing pipelines. The name “endpoint” seems a bit odd, but that element also serves to declare a single handler within the pipeline that acts in a request/response way (this is the facility to dispatch to “normal code” that doesn’t work in a one-way fashion). In that case, the endpoint element may refer to a handlerType. The name “endpoint” simply stems from the fact that that handler is considered to be the final destination for an incoming message and that it yields a new message as a result.

<pipelineType name=”P1”>
   <
handler type="A"/>
   <
endpoint>
   <
handler type="B"/>
   <
handler type="C"/>
</
pipelineType>
...
<
pipeline type="P1" composition="inside">
   <
handler type="D"/>
   <
endpoint />
   <
handler type="E"/>
</
pipelineType>
<
pipelineType type="P1" composition="outside">
   <
handler type="D"/>
   <
endpoint />
   <
handler type="E"/>
</
pipelineType>

With the composition rules, you can wrap a predefined pipeline (pipeline-type) or place your own handlers inside a predefined pipeline. The first pipeline in the above example (inside) yields the sequence D>A>B>C>E, the second (outside) yields the sequence A>D>E>B>C.

 

Next stop: Node-types and nodes.