2010/06/28
28 Jun, 2010

“FIX” Your SOA with WSO2 ESB

  • Hiranya Jayathilaka
  • PhD student - WSO2

Contents

Introduction

WSO2 Enterprise Service Bus (ESB) is capable of sending and receiving messages on a range of application layer protocols and messaging standards. The following diagram provides a comprehensive classification of all the well-known communication protocols supported by WSO2 ESB.

Support for these protocols is implemented in a set of components known as the “transports”. Each transport component is composed of a transport receiver implementation which knows how to receive inbound messages from the network and a transport sender implementation which is responsible for writing messages to the network. All the transport components are implemented as independent modules which can be plugged into the ESB-core as extensions.

The FIX transport of WSO2 ESB enables the service bus to receive and send FIX messages. Received FIX messages can be filtered, transformed and routed using the collection of built-in mediators. With WSO2 ESB, it is also possible to switch messages between the FIX transport and other transports. To make a long story short, the FIX transport of WSO2 ESB, in conjunction with the mediators and other transports, provides a powerful framework for developing high performance finance data routers.

The rest of this article provides an introduction to the FIX protocol and explains how WSO2 ESB can be used to deal with FIX messages.

Applies To

WSO2 ESB 3.0
Quickfix/J 1.4

Financial Information eXchange (FIX) Protocol

The FIX protocol is an open standard for real-time electronic exchange of securities transactions. It came into existence in 1992 as a bilateral communication protocol between Fidelity Investments and Salomon Brothers. Since then, the protocol has evolved rapidly to become the de-facto standard in finance messaging. As of now there are six major versions of the FIX protocol in use.

The protocol specification for FIX is maintained in the public domain and governed by the FIX Protocol, Ltd. FIX protocol has been adopted by many investment companies, banks, stock exchanges and asset managers throughout the world. Since the technical details of the protocol are designed to meet the actual requirements of the finance industry, the FIX protocol is also known as the industry-driven messaging standard.

FIX is a session oriented communication protocol. Therefore it spans across the application layer and the session layer in the OSI reference model. Every application taking part in a FIX conversation must first establish a FIX session with the peer. FIX protocol uses an application level sequence numbering system which guarantees zero message loss and in-order message delivery. When two parties engage in a conversation using FIX, one party acts as the acceptor and the other party operates as the initiator. The acceptor opens up a port and waits till a valid initiator connects to the port. The initiator sends a LogOn message to the acceptor, which then validates the request and authorizes the session.

A FIX message consists of a header, a body and a trailer. Each section consists of one or more key-value pairs known as fields. The key of a field must be a positive integer and the value may consist of numeric data, strings, XML or even binary content. A key and a value are separated using the equal sign (=) character and individual fields are separated using the ASCII SOH (0001) character. A sample FIX message which illustrates these characteristics is shown below:

8=FIX.4.0<SOH>9=105<SOH>35=D<SOH>34=2<SOH>49=BANZAI<SOH>52=20080711-06:42:26<SOH>56=SYNAPSE<SOH>
11=1215758546278<SOH>21=1<SOH>38=1000<SOH>40=1<SOH>54=1<SOH>55=DELL<SOH>59=0<SOH>10=253

Most of the fields are defined in the FIX specification along with the type of information their values should contain. The protocol also allows room for defining custom fields with user defined keys.

The FIX protocol does not define a mechanism for securing FIX conversations. However, applications can use SSL or TLS to provide transport level security and various encryption schemes to provide message level security.

FIX Transport of WSO2 ESB

The FIX transport of WSO2 ESB is based on the Quickfix/J FIX engine. It is a prominent open source implementation of FIX which supports all six major versions of the protocol. Quickfix/J uses Apache MINA to handle transport layer concerns and takes advantage of the Java NIO API to provide high performance and scalability.

Like all other transport components of WSO2 ESB, FIX transport also consists of a receiver and a sender. These can be separately configured in the axis2.xml file of the ESB. The mediation engine of WSO2 ESB uses SOAP as the common means of message processing. Therefore the FIX transport receiver has to convert incoming FIX messages into a SOAP compatible format. The following sample SOAP message shows the general structure of a converted FIX message:

<soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <message>
            <header>
                <field id="8"><![CDATA[FIX.4.0]]></field>
                <field id="9"><![CDATA[124]]></field>
                <field id="34"><![CDATA[2]]></field>
                <field id="35"><![CDATA[8]]></field>
                <field id="49"><![CDATA[EXEC]]></field>
                <field id="52"><![CDATA[20080326-10:03:17]]></field>
                <field id="56"><![CDATA[SYNAPSE]]></field>
            </header>
            <body>
                <field id="6"><![CDATA[0]]></field>
                <field id="11"><![CDATA[1206525794862]]></field>
                <field id="14"><![CDATA[0]]></field>
                <field id="17"><![CDATA[1]]></field>
                <field id="20"><![CDATA[0]]></field>
                <field id="31"><![CDATA[0]]></field>
                <field id="32"><![CDATA[0]]></field>
                <field id="37"><![CDATA[1]]></field>
                <field id="38"><![CDATA[2]]></field>
                <field id="39"><![CDATA[0]]></field>
                <field id="54"><![CDATA[1]]></field>
                <field id="55"><![CDATA[DELL]]></field>
            </body>
            <trailer>
                <field id="10"><![CDATA[190]]></field>
            </trailer>
        </message>
    </soapenv:Body>
</soapenv:Envelope>

Note that all the sections of the FIX message along with their respective fields are well preserved in the above XML infoset. Once a converted FIX message is injected into the service bus it can be further processed by using the ESB mediators. For an example using the XSLT mediator we can transform the XML infoset of the FIX message to any desired format.

The FIX transport sender can be used to send a FIX message to an external endpoint. It can connect to an external party as a FIX initiator and then forward messages over the established session. It can even forward messages as an acceptor by using a session previously started by the FIX transport listener. FIX transport sender also takes care of converting the SOAP messages back to the actual FIX format, before forwarding them to an endpoint. In WSO2 ESB, a FIX endpoint can be defined using the following URL format:

fix://host:port?BeginString=FIX.4.0&SenderCompID=WSO2ESB&TargetCompID=INITIATOR

The transport sender can extract the required parameters from a given FIX URL and send the messages to the appropriate session.

Activating the FIX Transport

The FIX transport is disabled in WSO2 ESB by default. Therefore some steps should be taken to activate the FIX transport in WSO2 ESB.

First you need to download a Quickfix/J binary distribution. Quickfix/J 1.4 is recommended for WSO2 ESB 3.0. Extract the downloaded distribution archive and locate the following libraries in it:

  • quickfixj-all-1.4.0.jar
  • mina-core-1.1.0.jar
  • slf4j-jdk14-1.5.3.jar
  • slf4j-api-1.5.3.jar

Copy these jar files to the repository/components/lib directory of the WSO2 ESB installation. Note that these libraries are regular jar files. The ESB will convert them into OSGi bundles at the server startup. At this point it is also a good idea to get rid of the Quickfix/J 1.3 library that comes with WSO2 ESB by default, to avoid any conflicts. This library can be found in the repository/components/plugins directory. Simply delete the file from the file system.

Having deployed the necessary libraries, open up the axis2.xml file of WSO2 ESB. This file is located in the repository/conf directory. Locate the transport receiver and sender configurations for FIX, and uncomment them:

<transportReceiver name="fix" class="org.apache.synapse.transport.fix.FIXTransportListener">
         <parameter name="non-blocking">true</parameter>
</transportReceiver> 

<transportSender name="fix" class="org.apache.synapse.transport.fix.FIXTransportSender">
         <parameter name="non-blocking">true</parameter>
</transportSender>

Now the ESB is ready to send and receive messages using the FIX protocol. Actual acceptor configurations and initiator configurations should be specified at the proxy service level.

FIX Transport in Action

Scenario 1: Switching from FIX to HTTP

One of the most common use cases of WSO2 ESB is to receive FIX messages from a finance application and route them to a Web Service over HTTP. The source of the FIX messages could be an order blotter, an Order Management System (OMS), an Order Router (OR) or an Electronic Trading System (ETS). These sources may generate order submissions, order amend requests or order cancel requests. The target Web Service could be part of another OMS/OR/ETS or an order processing system. Depending on the format of the messages accepted by the Web Service, the incoming FIX messages should be transformed accordingly. Sometimes it may be even required to route the responses from the Web Service back to the FIX application.

This scenario can be easily implemented on WSO2 ESB, using a simple proxy service. The proxy service should be exposed over FIX by providing a suitable FIX acceptor configuration. Any transformations necessary can be performed in the in-sequence using transformation mediators. The following example proxy configuration shows how to implement this scenario:

<proxy name="FIXProxy" transports="fix">
    <target>
        <endpoint>
            <address uri="https://localhost:9000/services/SimpleStockQuoteService" />
        </endpoint>
        <inSequence>
            <log level="full" />
            <xslt key="xslt-key-req" />
        </inSequence>
        <outSequence>
            <send/>
        </outSequence>
    </target>
    <parameter name="transport.fix.AcceptorConfigURL">
        file:repository/samples/resources/fix/acceptor.cfg
    </parameter>
    <parameter name="transport.fix.AcceptorMessageStore">
        file
    </parameter>
</proxy>
<localEntry key="xslt-key-req">
    <xsl:stylesheet version="2.0" 
        xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
	xmlns:fn="https://www.w3.org/2005/02/xpath-functions">
	<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />
	<xsl:template match="/">
	    <m0:placeOrder xmlns:m0="https://services.samples">
	        <m0:order>
		    <m0:price><xsl:value-of select="//message/body/field[@id='44']"/></m0:price>
		    <m0:quantity><xsl:value-of select="//message/body/field[@id='38']"/></m0:quantity>
		    <m0:symbol><xsl:value-of select="//message/body/field[@id='55']"/></m0:symbol>
		</m0:order>
	    </m0:placeOrder>
	</xsl:template>
    </xsl:stylesheet>
</localEntry>

Note that the XSLT transformation is defined as a local entry. The acceptor configuration used by the proxy service is specified using the “transport.fix.AcceptorConfigURL” parameter. The value of this parameter could be a file URL or an HTTP URL. The resource pointed by the parameter should contain a valid Quickfix/J acceptor configuration. A sample acceptor configuration is given below:

[default]
FileStorePath=repository/logs/fix/acceptor
ConnectionType=acceptor
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ValidOrderTypes=1,2,F
SenderCompID=WSO2ESB
TargetCompID=BANZAI
UseDataDictionary=Y
DefaultMarketPrice=12.30

[session]
BeginString=FIX.4.0
SocketAcceptPort=9876

The transport.fix.AcceptorMessageStore is used to specify a message store implementation for the FIX acceptor. In the above example we have instructed the ESB to use a file system based message store. The parameters required to initialize the message store, such as the file store path, should be given in the acceptor configuration file. If transport.fix.AcceptorMessageStore was not specified explicitly, the ESB will use an in-memory message store for the acceptor session. (More information on various service level parameters available for the FIX transport is documented in the WSO2 Carbon Transports Catalog.)

The above proxy configuration will also handle mediating the responses back to the FIX application. If it is not necessary to process the responses, one just needs to omit the out-sequence of the proxy service and add the following property mediator configuration to the in-sequence:

<property name="OUT_ONLY" value="true"/>

Scenario 2: Switching from FIX to JMS

Receiving messages from a FIX application and forwarding them to a JMS queue is another common usage of the WSO2 ESB FIX transport. This scenario is functionally similar to scenario-1 but instead of sending messages to a Web Service over HTTP, we send messages to a JMS broker. We can assume that some OMS or an order processing application is polling messages out of the JMS queue.

To implement this scenario we need to first enable the JMS transport sender in WSO2 ESB. This will require starting up your JMS broker and deploying the required JMS client libraries to repository/components/lib directory of the ESB. If the broker being used is Apache ActiveMQ, you need to start the ActiveMQ broker and copy the following jars to the ESB installation:

  • activemq-core-5.3.2.jar
  • geronimo-j2ee-management_1.0_spec-1.0.jar

Once the jars are deployed, you also need to edit the axis2.xml file and uncomment the JMS transport sender configuration.

<transportSender name="jms" class="org.apache.axis2.transport.jms.JMSSender"/>

With the JMS transport sender enabled, we can implement this scenario using a proxy service configuration similar to the following:

<proxy name="FIXProxy" transports="fix">
    <target>
        <endpoint>
            <address uri="jms:/SimpleStockQuoteService?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616&transport.jms.DestinationType=queue"/>
        </endpoint>
        <inSequence>
            <log level="full" />
            <property name="OUT_ONLY" value="true"/>
        </inSequence>
    </target>
    <parameter name="transport.fix.AcceptorConfigURL">
        file:repository/samples/resources/fix/acceptor.cfg
    </parameter>
    <parameter name="transport.fix.AcceptorMessageStore">
        file
    </parameter>
</proxy>

The only significant difference between this configuration and the configuration we used in scenario-1 is the target endpoint declaration. Instead of an HTTP URL we have specified a JMS URL which points to a JMS queue in the broker.

Scenario 3: Switching from JMS to FIX

This is the exact opposite of scenario-2. Here we configure the ESB to receive messages from a JMS queue and forward them to a FIX acceptor. In order to run this scenario, we have to enable the JMS transport receiver in the service bus. For that you have to start your JMS broker and copy the JMS client libraries to repository/components/lib directory. Then the JMS transport receiver configuration should be enabled in the axis2.xml file:

<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">
    <parameter name="myTopicConnectionFactory" locked="false">
        <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
        <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
        <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">TopicConnectionFactory</parameter>
	<parameter name="transport.jms.ConnectionFactoryType" locked="false">topic</parameter>
    </parameter>

    <parameter name="myQueueConnectionFactory" locked="false">
        <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
        <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
        <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
	<parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
    </parameter>

    <parameter name="default" locked="false">
        <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
        <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
        <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
	<parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
    </parameter>
</transportReceiver>

Then all we have to do is deploying a simple proxy service on the ESB and expose it over JMS. The target endpoint of the service should point to the FIX acceptor.

<proxy name="JMSProxy" transports="jms">    
    <target>
        <endpoint>
	    <address uri="fix://localhost:19876?BeginString=FIX.4.0&SenderCompID=SYNAPSE&TargetCompID=EXEC"/>
	</endpoint>
	<inSequence>
	    <property name="transport.fix.ServiceName" value="FIXProxy" scope="axis2-client"/>
	    <log level="full"/>
	</inSequence>
	<outSequence>
            <send/>
	</outSequence>
    </target>
    <parameter name="transport.fix.InitiatorConfigURL">
        file:repository/samples/resources/fix/initiator.cfg
    </parameter>
    <parameter name="transport.fix.InitiatorMessageStore">file</parameter>
    <parameter name="transport.fix.SendAllToInSequence">false</parameter>
    <parameter name="transport.fix.DropExtraResponses">true</parameter>
    <parameter name="transport.jms.Destination">MyQueue</parameter>
</proxy>

The above example configuration assumes that the messages received from the JMS queue are in the XML format recognized by the FIX transport (the format to which the FIX transport listener converts messages). If not, we need to do some transformations in the in-sequence to convert the messages to the accepted format. As long as the messages are in the correct format, the FIX transport sender is capable of constructing FIX messages out of them and forwarding them to the specified FIX endpoint.

Another important thing to note in the above configuration is the usage of the transport.fix.InitiatorConfigURL parameter. The value of this parameter should point to a file which contains a valid Quickfix/J initiator configuration. This configuration can be used to specify any additional settings required to start a FIX initiator against the given endpoint. The transport.fix.InitiatorMessageStore is used to setup the message store implementation for the initiator session. The transport.jms.Destination parameter specifies the name of the source JMS queue.

Scenario 4: Switching FIX Versions

While integrating various finance applications, developers often run into situations where they have to connect applications that are based on different versions of the FIX protocol. For an example the FIX order blotter used by one of the partner organizations may be based on FIX 4.0 whereas the OMS is based on FIX 4.1. WSO2 ESB provides a convenient way for connecting such diverse applications, using proxy services. Let’s take a look at an example proxy configuration.

<proxy name="OrderProcesserProxy40" transports="fix">
    <target>
        <endpoint>
            <address uri="fix://localhost:19877?BeginString=FIX.4.1&SenderCompID=SYNAPSE&TargetCompID=EXEC"/>
        </endpoint>
        <inSequence><log level="full"/></inSequence>
        <outSequence><send/></outSequence>
    </target>
    <parameter name="transport.fix.AcceptorConfigURL">file:
        repository/samples/resources/fix/acceptor-m40.cfg
    </parameter>
    <parameter name="transport.fix.AcceptorMessageStore">file</parameter>
    <parameter name="transport.fix.InitiatorConfigURL">
        file:repository/samples/resources/fix/initiator-m.cfg
    </parameter>
    <parameter name="transport.fix.InitiatorMessageStore">file</parameter>
</proxy>

The Quickfix/J configurations referenced by the above proxy service are shown below.

acceptor-m40.cfg:

[default]
FileStorePath=repository/logs/fix/acceptor
ConnectionType=acceptor
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ValidOrderTypes=1,2,F
SenderCompID=WSO2ESB
TargetCompID=BANZAI
UseDataDictionary=Y
DefaultMarketPrice=12.30

[session]
BeginString=FIX.4.0
SocketAcceptPort=9876
DataDictionary=repository/samples/resources/fix/FIX40-acceptor.xml

initiator-m.cfg:

[default] 
FileStorePath=repository/logs/fix/initiator
HeartBtInt=30 
ReconnectInterval=5
SendResetSeqNumFlag=Y

You may have noticed that the proxy service configuration does not really do anything interesting. The key here is using the correct Quickfix/J configurations. Note that the acceptor configuration has a BeginString value of FIX.4.0 whereas the target endpoint has a BeginString value of FIX.4.1. This means the ESB will create a FIX 4.0 acceptor session and a FIX 4.1 initiator session. By pointing the Quickfix/J configurations to the appropriate data dictionary files, the ESB will be able to accept any message coming over the FIX 4.0 session and forward it over the FIX 4.1 session. One can even perform some transformations in the proxy service to add, remove or modify the fields of the message before forwarding it to the target endpoint.

Scenario 5: Content-Based Routing

WSO2 ESB can be used to analyze messages coming over a FIX session and forward them to different endpoints based on their content. This concept is known as Content-Based Routing (CBR) in general, and it is one of the most popular use cases of ESBs. Please note that in WSO2 ESB, CBR support is not limited to the FIX transport. This feature is available for all transports and message formats.

WSO2 ESB provides an array of mediators and extensions that can be used to inspect message content and make decisions based on the outcomes. These mediators are collectively referred to as filtering mediators. The following proxy service configuration uses a Switch mediator to process messages and make routing decisions.

<proxy name="FIXProxy" transports="fix">
    <target>
        <inSequence>
            <switch source="//message/body/field[@id='55']">
	        <case regex="IBM">
		    <send>
		        <endpoint>
			    <address uri="fix://localhost:19876?BeginString=FIX.4.0&SenderCompID=SYNAPSE&TargetCompID=EXEC" />
			</endpoint>
		    </send>
		</case>
		<case regex="MSFT">
		     <send>
		         <endpoint>
			     <address uri="fix://localhost:19877?BeginString=FIX.4.1&SenderCompID=SYNAPSE&TargetCompID=EXEC" />
			 </endpoint>
		     </send>
		</case>
		<default/>  
            </switch>
        </inSequence>
    </target>
    <parameter name="transport.fix.AcceptorConfigURL">
        file:repository/samples/resources/fix/acceptor.cfg
    </parameter>
    <parameter name="transport.fix.AcceptorMessageStore">file</parameter>
    <parameter name="transport.fix.InitiatorConfigURL">
	file:repository/samples/resources/fix/initiator.cfg
     </parameter>
     <parameter name="transport.fix.InitiatorMessageStore">file</parameter>
</proxy>

The source attribute of the switch mediator is used to specify an XPath expression which points to the section of the message which needs to be analyzed. In the above example we are pointing to the value of the FIX message field 55 (Symbol). If the value turns out to be “IBM” we are routing messages to one endpoint and if the value is “MSFT” we are forwarding them to a different endpoint. The initiator.cfg should contain configuration settings common to both initiator sessions. Session specific parameters like BeginString, SenderCompID and TargetCompID are given in the endpoint URLs.

QoS Features

Transport Level Security

It is possible to use FIX over SSL with WSO2 ESB. To enable this mode, we should first prepare a special Aapche MINA library which contains the MINA core classes and the MINA SSL filter implementation. This can be done by following these three steps:

  1. Extract the mina-core and mina-ssl-filter jars
  2. Merge the extracted content together
  3. Create a jar file from the aggregated content

The new jar file should be placed in the repository/components/lib directory of the ESB. If the mina-core is already deployed into the ESB it has to be removed. One must not attempt to deploy the mina-core and the mina-ssl-filter into the ESB as separate jar files. These two jars contain split packages and hence they can cause OSGi class loading issues. Therefore they must be merged into a single jar file.

Once the MINA library is deployed into the ESB, we can use FIX over SSL by specifying the following parameters in acceptor configuration files and initiator configuration files.

SocketUseSSL=Y
SocketKeyStore=resources/security/wso2carbon.jks
SocketKeyStorePassword=wso2carbon

The SocketKeyStore should point to the key store which contains the required certificates. Alternatively, you can import the necessary certificates into wso2carbon.jks that comes with WSO2 ESB. The ESB management console provides the necessary tools for importing certificates.

FIX Session Fail-over

Quickfix/J provides simple fail-over support for acceptors. We can use this feature in WSO2 ESB to create high available FIX acceptor sessions. To start a high available acceptor session in the ESB, we have to start multiple FIX proxy services that share the same mediation configuration and the same FIX message store. An example is given below:

<proxy name="proxy1" transports="fix">
    <target endpoint="sharedEndpoint" inSequence="sharedIn" outSequence="sharedOut"/>
    <parameter name="transport.fix.AcceptorConfigURL">
        file:repository/samples/resources/fix/acceptor1.cfg
    </parameter>
    <parameter name="transport.fix.AcceptorMessageStore">
        file
    </parameter>
</proxy>

<proxy name="proxy2" transports="fix">
    <target endpoint="sharedEndpoint" inSequence="sharedIn" outSequence="sharedOut"/>
    <parameter name="transport.fix.AcceptorConfigURL">
        file:repository/samples/resources/fix/acceptor2.cfg
    </parameter>
    <parameter name="transport.fix.AcceptorMessageStore">
        file
    </parameter>
</proxy>

Note that both proxy services refer to the same in-sequence, target endpoint and out-sequence. Therefore the mediation configuration is effectively shared between the two services. Also they both specify the acceptor message store type as “file”. The Quickfix/J acceptor configurations used by the two services should be as follows:

acceptor1.cfg:

[default]
FileStorePath=repository/logs/fix/acceptor
ConnectionType=acceptor
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ValidOrderTypes=1,2,F
SenderCompID=WSO2ESB
TargetCompID=BANZAI
UseDataDictionary=Y
DefaultMarketPrice=12.30
RefreshMessageStoreAtLogon=Y

[session]
BeginString=FIX.4.0
SocketAcceptPort=9876

acceptor2.cfg:

[default]
FileStorePath=repository/logs/fix/acceptor
ConnectionType=acceptor
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ValidOrderTypes=1,2,F
SenderCompID=WSO2ESB
TargetCompID=BANZAI
UseDataDictionary=Y
DefaultMarketPrice=12.30
RefreshMessageStoreAtLogon=Y

[session]
BeginString=FIX.4.0
SocketAcceptPort=19876

There are few important things to note here.

  1. Both configurations use the same persistent FIX message store
  2. The SocketAcceptPort values are different
  3. Configurations explicitly define the RefreshMessageStoreAtLogon parameter

In order to run two acceptors in the fail-over mode they must share the same persistent message store. In-memory message stores cannot be used to provide fail-over support. The SocketAcceptPort parameter is given two different values to avoid conflicts during service initialization. Specifying the same port number for two sessions will raise a Java BindException at server startup. The RefreshMessageStoreAtLogon is used to instruct the FIX engine that when a new initiator logs on to the session the message store must be refreshed. With these settings in place, now we can configure the initiator with fail-over support by providing the following Quickfix/J configuration.

[default]
FileStorePath=examples/store/initiator
SocketConnectHost=localhost
SocketConnectHost1=localhost
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ReconnectInterval=5
SenderCompID=BANZAI
TargetCompID=WSO2ESB
ConnectionType=initiator

[session]
BeginString=FIX.4.0
SocketConnectPort=9876
SocketConnectPort1=19876

Here we have configured the initiator to use proxy1 as the primary acceptor endpoint. If for some reason it goes down, the initiator will automatically switch to proxy2 and resume the session.

Persistent Message Stores

Maintaining a reliable message store is crucial when deploying the FIX protocol in the enterprise landscape. Message stores are required to handle certain error conditions and most importantly to handle retransmissions and sequence resets. With WSO2 ESB, it is possible to use a persistent FIX message store which saves all the messages in a database via JDBC. In almost all the examples we looked at earlier, a file system based message store was used. While this provides a satisfactory level of persistence, a file system based message store is not reliable enough. Also it is difficult to share the same file system based message store across multiple applications. JDBC message stores are more reliable and scalable. Also a database can be easily shared across multiple FIX applications.

To setup a JDBC-based message store we should first copy the corresponding JDBC drivers into the repository/components/lib directory of the ESB installation. The SQL scripts available in the Quickfix/J binary distribution can be used to setup the required tables in your database server. Then in the proxy service configurations, the transport.fix.AccceptorMessageStore parameter and transport.fix.InitiatorMessageStore parameter should be updated as follows:

<parameter name="transport.fix.AcceptorMessageStore">jdbc</parameter>
<parameter name="transport.fix.InitiatorMessageStore">jdbc</parameter>

Finally, the relevant Quickfix/J configurations referenced by the ESB should be updated, by adding the following JDBC message store parameters:

JdbcDriver=com.mysql.jdbc.Driver
JdbcURL=jdbc://my.db.server:3306/myDB
JdbcUser=wso2esb
JdbcPassword=password

Next Steps

To learn more about the FIX protocol support available in WSO2 ESB, please refer to WSO2 Carbon Transports Catalog and WSO2 ESB transport samples. WSO2 ESB ships with a number of sample configurations and resources that can be used to try out most of the scenarios we looked at earlier. The two sample FIX applications that come with Quickfix/J (named Banzai and Executor) can be used to try out these sample scenarios.

Conclusion

The FIX transport of WSO2 ESB allows the ESB to send and receive FIX messages. The transport is based on Quickfix/J and uses an XML infoset to represent FIX messages flowing through the service bus. Received FIX messages can be filtered, transformed and routed using the built-in mediators of the ESB. Also with WSO2 ESB, it is trivial to receive requests over FIX and forward them to remote endpoints over different protocols like HTTP and JMS. Additional quality of service requirements such as security and fail-over can be implemented if necessary with minimal effort. WSO2 ESB provides a robust and efficient framework for integrating finance applications and developing high performance finance data hubs.

References

[1] WSO2 ESB 3.0 Samples Guide - https://wso2.org/project/esb/java/3.0.0/docs/samples/transport_samples.html

[2] The FIX Protocol Organization - https://www.fixprotocol.org

[3] WSO2 Carbon Transports Catalog - https://wso2.org/project/esb/java/3.0.0/docs/transports/transports-catalog.html#FixTrp

 

About Author

  • Hiranya Jayathilaka
  • PhD student
  • Department of Computer Science at UC Santa Barbara