WSO2Con 2013 CFP Banner

Apache Synapse FIX'ed

Discuss this article on Stack Overflow
By Hiranya Jayathilaka
  • 2 Apr, 2008
  • Level:  Introductory
  • Reads: 7068

In this article by Hiranya Jayathilaka, he illustrates Apache Synapse support for the Financial Information eXchange protocol (FIX).

hiranya's picture
Hiranya Jayathilaka
PhD student
Department of Computer Science at UC Santa Barbara

Introduction

Apache Synapse is a lightweight mediation framework for Web services. It is based on Apache Axis2 and a number of other XML and Web services related projects. Apache Synapse is designed to be fast, easy to configure and provides a comprehensive solution for many integration and gatewaying problems. Apache Synapse supports a variety of protocols like HTTP/HTTPS, SMTP, JMS and VFS. Keeping alert for popular transports and protocols used in the industry and providing support for them in Synapse has been the habit of the Synapse development team. As a result of these efforts, Apache Synapse now supports the Financial Information eXchange (FIX) protocol.

In the first part of this article I touch the basics of the FIX protocol. Then I move on to describe, how the FIX protocol support is enabled in Synapse and how two FIX based applications can be setup to communicate through Apache Synapse.

 

Applies To

Apache Synapse Snapshot, 1.2
Environment Windows, Linux

 

Table of Contents

Introduction to FIX Protocol

The FIX protocol is a series of messaging specifications for the electronic exchange of trade-related messages. It is an industry-driven standard developed as an collaborative effort by banks, broker-dealers, exchanges, industry utilities and associations, institutional investors and IT providers around the world. FIX protocol was initiated in year 1992 as a bilateral communication framework for equity trading between Fidelity Investments and Salomon Brothers. The protocol specification is currently owned by the FIX Protocol Limited and the company is responsible for maintaining the specification while keeping it in the public domain. The FIX specification is open and free, but is not software. Rather, FIX is a communications protocol around which software developers can create commercial or open-source software. There are six major versions of the FIX protocol specification so far;

  • Version 4.0: (Released on Jan 13, 1996)
  • Version 4.1: (Released on Apr 1, 1998)
  • Version 4.2: (Released on Mar 1, 2000)
  • Version 4.3: (Released on Aug 24, 2001)
  • Version 4.4: (Released on Apr 30, 2003)
  • Version 5.0: (Released on Dec 30, 2006)

FIX is a protocol with a large user base. It is widely used by both the buy-side (institutions) and the sell-side (brokers/dealers) of financial markets. (See 'Who uses FIX?' on the FIX Protocol Limited website for a comprehensive list of major FIX users). Over the years FIX has been considered the defacto standard for securities transactions and the leading trade-communications protocol. It is becoming increasingly popular as the global language for the automated trading of financial instruments.

The FIX protocol supports a number of business functions. It was originally designed to be used in supporting US domestic equity trading, with message traffic flowing directly between principals. But as the protocol evolved, more features were added to facilitate cross-border trading and third party participation. FIX specification was written to be independent of any specific network protocol (X.25, TCP/IP etc) or any physical medium (copper, fiber, wireless etc) chosen for electronic data delivery. The protocol basically focuses on two level; i.e. session and application. The session level is concerned with the delivery of data while the application level defines business related data content.

 

FIX Message Format

A FIX message in its purest form is a collection of key-value pairs, where each pair is called a field. ASCII 0001 character (Start of Header) is used as the delimiter for fields. Any FIX message can be logically separated into three parts, namely the header, body and the trailer. The FIX specification clearly defines a set of fields messages should confirm with, for each message type.

In general, a FIX message appears to be something like the following:

8=FIX.4.0<SOH>9=102<SOH>35=D<SOH>34=16<SOH>49=BANZAI<SOH>52=20080314-05:01:47<SOH>56=SYNAPSE<SOH>11=1205470907396<SOH>21=1<SOH>38=5<SOH>40=1<SOH>54=1<SOH>55=IBM<SOH>59=0<SOH>10=078

Listing 1: A typical FIX message

Some of the important fields worth mentioning are briefly described below:

  • 8 (BeginString) - The FIX version
  • 9 (BodyLength) - The character length of the message
  • 35 (MsgType) - The type of the message (A=Logon, B=News, C=E-mail, D=Order-Single etc.)
  • 49 (SenderCompID) - The ID of the sending company
  • 56 (TargetCompID) - The ID of the receiving company
  • 10 (Checksum) - Calculated message checksum

The content of a FIX message can greatly vary depending on the type of the message.

 

FIX Sessions

An application could communicate using FIX in one of the two modes. It could be either in the initiator mode or in the acceptor mode. When in the initiator mode the application starts the transaction by sending out a request message. When in the acceptor mode the application simply waits till some other party (an initiator) tries to connect to it. A FIX transaction can only occur between an initiator and an acceptor.

Before any message exchanging takes places the initiator and the acceptor should establish a FIX session. Then both parties should log on to the session. The initiator starts the log on procedure by sending out a logon request message. Then the acceptor validates the request and acknowledges it by sending out a logon response message. Once logged on the initiator and the acceptor are free to communicate. Once they are done the session will be logged off by exchanging log off messages. Each FIX session carries no more  than the traffic generated by the initiator and the acceptor that created the session. If some application wants to communicate with multiple parties over FIX it should establish multiple FIX sessions, one for  each target. FIX sessions do not support concurrent connections.

 

Introduction to Quickfix/J

Having discussed a fair deal on the FIX protocol, let's now focus on how it is implemented in practice. There are tons of FIX engines in the market that implement the FIX specification and allow applications to send and receive FIX messages. Quickfix/J, is a free open source FIX engine written in Java to give Apache Synapse the ability to communicate over FIX.

Quickfix/J is one of the most popular and widely used FIX engines in the world. It provides application developers a simple API to deal with and currently supports five out of the six major versions of the FIX specification. Quickfix/J is based on the Apache MINA project and hence uses Java NIO asynchronous network communications system. It has powerful techniques for message parsing, validation, storing and logging.

To develop a FIX based application with Quickfix/J, you simply need to implement the quickfix.Application interface illustrated below:

package quickfix;

public interface Application {
  void onCreate(SessionID sessionId);
  void onLogon(SessionID sessionId);
  void onLogout(SessionID sessionId);
  void toAdmin(Message message, SessionID sessionId);
  void toApp(Message message, SessionID sessionId)
    throws DoNotSend;
  void fromAdmin(Message message, SessionID sessionId)
    throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon;
  void fromApp(Message message, SessionID sessionId)
    throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType;
}

Listing 2: Quickfix/J Application Interface

It is also easy to configure FIX applications developed using Quickfix/J. Sessions are configured by creating a simple configuration file and pointing the application to it.

 

FIX Support in Apache Synapse

Apache Synapse is the first open source ESB in the world to support the FIX protocol. The FIX transport package for Apache Synapse was developed using Quickfix/J. During the process we have made sure that all the flexibility and simplicity found in Quickfix/J is still made available with Apache Synapse. It is easy to deploy FIX based services in Synapse, and most of the FIX related configuration settings are made as described in the Quickfix/J documentation. This allows a regular  Quickfix/J user to quickly get started with Synapse.

From here onwards I will be refering to the directory to which you have installed Synapse as SYNAPSE_HOME. To enable the FIX transport in Synapse, simply put the following few entires to the SYNAPSE_HOME/repository/conf/axis2.xml configuration file:

<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>

Listing 3: Sample Configuration for FIX Transport

 

Banzai and Executor

From here onwards, I describe how to integrate two FIX applications using Apache Synapse. The two applications I'm going to integrate are the sample FIX applications that comes with every Quickfix/J distribution. So please download the latest Quickfix/J binary distribution if you already have not done so.

The two sample applications are called Banzai and Executor and you can find them in quickfix.examples package. Banzai is a Swing based order entry application and Executor is a console based order processing application. You can send order requests from Banzai to Executor over five different FIX sessions and Executor will reply on the session on which you sent the request.

To begin with, let's try running the two sample applications and sending some order requests from Banzai to Executor directly. You will find the startup scripts for Banzai and Executor in the bin directory of the Quickfix/J distribution. First, fire up the Executor application by running executor.sh (or executor.bat if you are on Windows). You should see something similar to the following on your console:

<20080314-09:14:31, FIX.4.3:EXEC->BANZAI, event> (Session FIX.4.3:EXEC->BANZAI schedule is daily, 00:00:00 UTC - 00:00:00 UTC (daily, 00:00:00 UTC - 00:00:00 UTC)) 
<20080314-09:14:31, FIX.4.3:EXEC->BANZAI, event> (Created session: FIX.4.3:EXEC->BANZAI) 
<20080314-09:14:31, FIX.4.3:EXEC->BANZAI, event> (Valid order types: [F, 2, 1]) 
<20080314-09:14:31, FIX.4.2:EXEC->BANZAI, event> (Session FIX.4.2:EXEC->BANZAI schedule is daily, 00:00:00 UTC - 00:00:00 UTC (daily, 00:00:00 UTC - 00:00:00 UTC)) 
<20080314-09:14:31, FIX.4.2:EXEC->BANZAI, event> (Created session: FIX.4.2:EXEC->BANZAI) 
<20080314-09:14:31, FIX.4.2:EXEC->BANZAI, event> (Valid order types: [F, 2, 1]) 
<20080314-09:14:31, FIX.4.0:EXEC->BANZAI, event> (Session FIX.4.0:EXEC->BANZAI schedule is daily, 00:00:00 UTC - 00:00:00 UTC (daily, 00:00:00 UTC - 00:00:00 UTC)) 
<20080314-09:14:31, FIX.4.0:EXEC->BANZAI, event> (Created session: FIX.4.0:EXEC->BANZAI) 
<20080314-09:14:31, FIX.4.0:EXEC->BANZAI, event> (Valid order types: [F, 2, 1]) 
<20080314-09:14:32, FIX.4.4:EXEC->BANZAI, event> (Session FIX.4.4:EXEC->BANZAI schedule is daily, 00:00:00 UTC - 00:00:00 UTC (daily, 00:00:00 UTC - 00:00:00 UTC)) 
<20080314-09:14:32, FIX.4.4:EXEC->BANZAI, event> (Created session: FIX.4.4:EXEC->BANZAI) 
<20080314-09:14:32, FIX.4.4:EXEC->BANZAI, event> (Valid order types: [F, 2, 1]) 
<20080314-09:14:32, FIX.4.1:EXEC->BANZAI, event> (Session FIX.4.1:EXEC->BANZAI schedule is daily, 00:00:00 UTC - 00:00:00 UTC (daily, 00:00:00 UTC - 00:00:00 UTC)) 
<20080314-09:14:32, FIX.4.1:EXEC->BANZAI, event> (Created session: FIX.4.1:EXEC->BANZAI) 
<20080314-09:14:32, FIX.4.1:EXEC->BANZAI, event> (Valid order types: [F, 2, 1]) 
Mar 14, 2008 2:44:32 PM quickfix.mina.acceptor.AbstractSocketAcceptor startAcceptingConnections 
INFO: Listening for connections at 0.0.0.0/0.0.0.0:9880 
Mar 14, 2008 2:44:32 PM quickfix.mina.acceptor.AbstractSocketAcceptor startAcceptingConnections 
INFO: Listening for connections at 0.0.0.0/0.0.0.0:9878 
Mar 14, 2008 2:44:32 PM quickfix.mina.acceptor.AbstractSocketAcceptor startAcceptingConnections 
INFO: Listening for connections at 0.0.0.0/0.0.0.0:9876 
Mar 14, 2008 2:44:32 PM quickfix.mina.acceptor.AbstractSocketAcceptor startAcceptingConnections 
INFO: Listening for connections at 0.0.0.0/0.0.0.0:9879 
Mar 14, 2008 2:44:32 PM quickfix.mina.acceptor.AbstractSocketAcceptor startAcceptingConnections 
INFO: Listening for connections at 0.0.0.0/0.0.0.0:9877 
press <enter> to quit 

Listing 4: Executor Console Output

As you can see, the Executor creates five FIX sessions and waits till some initiator attempts to connect to them. Now, start Banzai on another console by running the banzai.sh (or banzai.bat if you are on Windows). You should get an output similar to the following on the console and a Swing frame should pop up.

Mar 14, 2008 2:45:49 PM quickfix.mina.initiator.InitiatorIoHandler sessionCreated 
INFO: MINA session created: /127.0.0.1:49403 
Mar 14, 2008 2:45:49 PM quickfix.mina.initiator.InitiatorIoHandler sessionCreated 
INFO: MINA session created: /127.0.0.1:59159 
Mar 14, 2008 2:45:49 PM quickfix.mina.initiator.InitiatorIoHandler sessionCreated 
INFO: MINA session created: /127.0.0.1:40188 
Mar 14, 2008 2:45:49 PM quickfix.mina.initiator.InitiatorIoHandler sessionCreated 
INFO: MINA session created: /127.0.0.1:37287 
Mar 14, 2008 2:45:49 PM quickfix.mina.initiator.InitiatorIoHandler sessionCreated 
INFO: MINA session created: /127.0.0.1:58275 
<20080314-09:15:50, FIX.4.1:BANZAI->EXEC, outgoing> (8=FIX.4.1#9=62#35=A#34=25#49=BANZAI#52=20080314-09:15:50#56=EXEC#98=0#108=30#10=067#) 
<20080314-09:15:51, FIX.4.1:BANZAI->EXEC, event> (Initiated logon request) 
<20080314-09:15:51, FIX.4.4:BANZAI->EXEC, outgoing> (8=FIX.4.4#9=65#35=A#34=3#49=BANZAI#52=20080314-09:15:51.093#56=EXEC#98=0#108=30#10=224#) 
<20080314-09:15:51, FIX.4.4:BANZAI->EXEC, event> (Initiated logon request) 
<20080314-09:15:51, FIX.4.2:BANZAI->EXEC, outgoing> (8=FIX.4.2#9=65#35=A#34=3#49=BANZAI#52=20080314-09:15:51.105#56=EXEC#98=0#108=30#10=216#) 
<20080314-09:15:51, FIX.4.2:BANZAI->EXEC, event> (Initiated logon request) 
<20080314-09:15:51, FIX.4.0:BANZAI->EXEC, outgoing> (8=FIX.4.0#9=61#35=A#34=3#49=BANZAI#52=20080314-09:15:51#56=EXEC#98=0#108=30#10=014#) 
<20080314-09:15:51, FIX.4.0:BANZAI->EXEC, event> (Initiated logon request) 
<20080314-09:15:51, FIX.4.3:BANZAI->EXEC, outgoing> (8=FIX.4.3#9=65#35=A#34=3#49=BANZAI#52=20080314-09:15:51.126#56=EXEC#98=0#108=30#10=220#) 
<20080314-09:15:51, FIX.4.3:BANZAI->EXEC, event> (Initiated logon request) 
<20080314-09:15:51, FIX.4.1:BANZAI->EXEC, incoming> (8=FIX.4.1#9=62#35=A#34=48#49=EXEC#52=20080314-09:15:51#56=BANZAI#98=0#108=30#10=073#) 
<20080314-09:15:51, FIX.4.2:BANZAI->EXEC, incoming> (8=FIX.4.2#9=65#35=A#34=3#49=EXEC#52=20080314-09:15:51.329#56=BANZAI#98=0#108=30#10=224#) 
<20080314-09:15:51, FIX.4.3:BANZAI->EXEC, incoming> (8=FIX.4.3#9=65#35=A#34=3#49=EXEC#52=20080314-09:15:51.316#56=BANZAI#98=0#108=30#10=221#) 
<20080314-09:15:51, FIX.4.4:BANZAI->EXEC, incoming> (8=FIX.4.4#9=65#35=A#34=3#49=EXEC#52=20080314-09:15:51.309#56=BANZAI#98=0#108=30#10=224#) 
<20080314-09:15:51, FIX.4.0:BANZAI->EXEC, incoming> (8=FIX.4.0#9=61#35=A#34=3#49=EXEC#52=20080314-09:15:51#56=BANZAI#98=0#108=30#10=014#) 

Listing 5: Banzai Console Output

When Banzai comes on-line it sees that Executor is already up and running, and therefore sending log on requests. Five requests will be sent for each session. Then Executor will acknowledge the log on requests. When all five sessions are properly established you should see something like this on the console where you started Banzai:

<20080314-09:15:51, FIX.4.1:BANZAI->EXEC, event> (Received logon response) 
<20080314-09:15:51, FIX.4.3:BANZAI->EXEC, event> (Received logon response) 
<20080314-09:15:51, FIX.4.4:BANZAI->EXEC, event> (Received logon response) 
<20080314-09:15:51, FIX.4.2:BANZAI->EXEC, event> (Received logon response) 
<20080314-09:15:51, FIX.4.0:BANZAI->EXEC, event> (Received logon response) 

Listing 6: Banzai Console Output

Now you can send order requests from Banzai to Executor. Try sending some orders and see what happens. Each order executed by the Executor will add an entry under the Executions tab in the Banzai UI. Also you can have a look at the console outputs to get an idea about what's going on. Both applications will log the messages they exchange on the screen in a self explanatory manner.

 

Connecting Banzai and Executor Using Synapse

Now let's try to do the same thing done above using Synapse. We will deploy a Proxy service in Synapse which forwards all the FIX traffic it receives to a given endpoint (in this case the endpoint would be the Executor). Then we will get Banzai to send messages to Synapse. For simplicity we will use only one FIX session for the moment. I'm going to use a FIX 4.0 session to start with.

When deploying a proxy service in Synapse you need to give an EPR to forward the traffic to. In Synapse a FIX EPR identifies a FIX session. The general format of a FIX EPR is as follows.

fix://<host>:<port>?BeginString=<A valid BeginString>&SenderCompID=<A valid SenderCompID>&TargetCompID=<A valid TargetCompID>

Listing 7: General FIX EPR

In addition to the three mandatory parameters (BeginString, SenderCompID and TargetCompID) mentioned in the above EPR you could put as much as valid FIX properties in the EPR as key-value pairs separated by ampersands. Here are some example FIX EPRs.

fix://localhost:9786?BeginString=FIX.4.0&SenderCompID=BANZAI&TargetCompID=SYNAPSE
fix://localhost:9877?BeginString=FIX.4.1&SenderCompID=BANZAI&TargetCompID=SYNAPSE&SenderSubID=desk&SenderLocationID=lk
fix://localhost:9878?BeginString=FIX.4.1&SenderCompID=BANZAI&TargetCompID=SYNAPSE&DeliverToCompID=EXEC&StartTime=00:00:00&EndTime=00:00:00

Listing 8: Sample FIX EPRs

So what is the EPR we should put in the Synapse configuration for our example? Let's assume Synapse is identified as 'SYNAPSE' by the remote FIX engines. Then the SenderCompID parameter of the EPR becomes 'SYNAPSE'. TargetCompID is where we want our FIX message to be delivered. So it should be the SenderCompID of the Executor which is 'EXEC'. The BeginString is the FIX version we intend to use. So it is FIX.4.0. Now our target endpoint for the proxy service effectively becomes something like the following.

fix://localhost:19876?BeginString=FIX.4.0&SenderCompID=SYNAPSE&TargetCompID=EXEC

Listing 9: Sample FIX EPRs

If we are using this EPR we have to make sure that Executor will listen on the port 19876 for FIX 4.0 messages.

Now we have to specify the FIX session configuration settings for Synapse. As you may have already figured out by now Synapse will need two FIX sessions for this scenario. It will listen for messages coming from Banzai on one session and forward them to Executor on another session. The session with Banzai should be in acceptor mode whereas the session with Executor should be in the initiator mode. So we need two configuration files. These configuration files should be valid Quickfix/J configuration files. For the acceptor session we can use something like this.

[default] 
FileStorePath=/home/hiranya/Desktop/fix-tests/fix-sessions/synapse 
ConnectionType=acceptor 
StartTime=00:00:00 
EndTime=00:00:00 
HeartBtInt=30 
ValidOrderTypes=1,2,F 
SenderCompID=SYNAPSE 
TargetCompID=BANZAI 
UseDataDictionary=Y 
DefaultMarketPrice=12.30 

[session] 
BeginString=FIX.4.0 
SocketAcceptPort=9876

Listing 10: Acceptor Configuration for Synapse

Simply put the above in a simple text file and save it somewhere in your local file system. You may name it something like 'fix-synapse.cfg'. The extension or the name does not really matter here.

Do not forget to change the FileStorePath property to point to a location on your hard disk. We will be using a file based message store and hence it is required to define a valid FileStorePath property.

For the initiator session we can use the following configuration.

[default] 
FileStorePath=/home/hiranya/Desktop/fix-tests/fix-sessions/synapse-sender 
StartTime=00:00:00 
EndTime=00:00:00 

HeartBtInt=30 
ReconnectInterval=5

Listing 11: Initiator Configuration for Synapse

Put the above in a simple text file and save it somewhere in your local file system. You may name it something like 'synapse-sender.cfg'. The FileStorePath property should point to a directory in your local file system.

There is no need to define a session section in the configuration file for the initiator session. Specifying only the default section is sufficient since we have defined a few parameters on the target EPR itself. Parameters defined in the EPR will be used to create a session anyway. The properties defined above under the default section will be simply applied to that session.
Alternatively you could choose not to use a configuration file at all to setup the initiator. You could simply put all the parameters in the EPR.

Perfect! Now we can write the proxy service configuration.

<proxy name="OrderProcesserProxy40" transports="fix"> 
     <target> 
         <endpoint> 
              <address uri="fix://localhost:19876?BeginString=FIX.4.0&amp;SenderCompID=SYNAPSE&amp;TargetCompID=EXEC"/> 
         </endpoint> 

         <inSequence><log level="full"/></inSequence> 
         <outSequence><log level="full"/><send/></outSequence> 
      </target> 
            
      <parameter name="transport.fix.AcceptorConfigURL">file:/home/hiranya/Desktop/fix-tests/fix-config/fix-synapse.cfg</parameter> 
      <parameter name="transport.fix.AcceptorMessageStore">file</parameter>               
      <parameter name="transport.fix.InitiatorConfigURL">file:/home/hiranya/Desktop/fix-tests/fix-config/synapse-sender.cfg</parameter> 
      <parameter name="transport.fix.InitiatorMessageStore">file</parameter>           
</proxy>

Listing 12: Synapse Proxy Service Configuration

As you can see  there are four parameters defined in the Synapse configuration. Let's see what they are all about.

transport.fix.AcceptorConfigURL A URL pointing to the acceptor configuration file we created earlier
transport.fix.InitiatorConfigURL A URL pointing to the initiator configuration file we created earlier
transport.fix.AcceptorMessageStore

This parameter defines the type of message store implementation Quickfix/J should use for the acceptor. This is an optional parameter and if not specified Synapse will tell Quickfix/J to use a memory based message store. When specified it should have one of the following values.

  • file
  • jdbc
  • memory
  • sleepycat

Other parameters required by each of these message store implementations should be specified in the session configuration file. (For an example a file based message store requires the user to define the property FileStorePath in the session configuration file. See here for more information.)

transport.fix.InitiatorMessageStore This defines the type of message store implementation to be used with the initiator. This is similar to the above parameter.

Table 1: Synapse Service Parameters for FIX Services

OK. Simply put the above proxy service configuration in the SYNAPSE_HOME/repository/conf/synapse.xml. Change the parameters accordingly. The InitiatorConfigURL and AcceptorConfigURL must point to the files you created earlier. Now Synapse is armed and ready to mediate some FIX messages. Go to SYNAPSE_HOME/bin directory and  execute the synapse.sh script to fire up Synapse and see what happens. You should see something like the following on your console.

2008-03-26 15:21:24,183 [127.0.1.1-hiranya-desktop] [main]  INFO SynapseInitializationModule Loading mediator extensions...
2008-03-26 15:21:24,183 [127.0.1.1-hiranya-desktop] [main]  INFO SynapseInitializationModule Initializing the Synapse configuration ...
2008-03-26 15:21:24,189 [127.0.1.1-hiranya-desktop] [main]  INFO XMLConfigurationBuilder Generating the Synapse configuration model by parsing the XML configuration
2008-03-26 15:21:24,343 [127.0.1.1-hiranya-desktop] [main]  INFO SynapseConfigurationBuilder Loaded Synapse configuration from : /home/hiranya/java/synapse-1.1.1/repository/conf/synapse.xml
2008-03-26 15:21:24,353 [127.0.1.1-hiranya-desktop] [main]  INFO SynapseInitializationModule Deploying the Synapse service..
2008-03-26 15:21:24,381 [127.0.1.1-hiranya-desktop] [main]  INFO SynapseInitializationModule Synapse server name : hiranya-desktop
2008-03-26 15:21:24,381 [127.0.1.1-hiranya-desktop] [main]  INFO SynapseInitializationModule Deploying Proxy services...
2008-03-26 15:21:24,381 [127.0.1.1-hiranya-desktop] [main]  INFO ProxyService Building Axis service for Proxy service : OrderProcesserProxy40
2008-03-26 15:21:24,384 [127.0.1.1-hiranya-desktop] [main]  INFO ProxyService Adding service OrderProcesserProxy40 to the Axis2 configuration
2008-03-26 15:21:24,384 [127.0.1.1-hiranya-desktop] [main]  INFO ProxyService Successfully created the Axis2 service for Proxy service : OrderProcesserProxy40
2008-03-26 15:21:24,384 [127.0.1.1-hiranya-desktop] [main]  INFO SynapseInitializationModule Deployed Proxy service : OrderProcesserProxy40
2008-03-26 15:21:24,384 [127.0.1.1-hiranya-desktop] [main]  INFO SynapseInitializationModule Synapse initialized successfully...!
2008-03-26 15:21:24,406 [127.0.1.1-hiranya-desktop] [main]  INFO HttpCoreNIOSender HTTPS Sender starting
2008-03-26 15:21:24,472 [127.0.1.1-hiranya-desktop] [main]  INFO HttpCoreNIOSender HTTP Sender starting
2008-03-26 15:21:24,479 [127.0.1.1-hiranya-desktop] [main]  INFO FIXTransportSender FIX transport sender initialized...
2008-03-26 15:21:24,710 [127.0.1.1-hiranya-desktop] [main]  INFO HttpCoreNIOListener HTTPS Listener starting on port : 8443
2008-03-26 15:21:24,710 [127.0.1.1-hiranya-desktop] [main]  INFO ServerManager Starting transport https on port 8443
2008-03-26 15:21:24,711 [127.0.1.1-hiranya-desktop] [main]  INFO HttpCoreNIOListener HTTP Listener starting on port : 8080
2008-03-26 15:21:24,712 [127.0.1.1-hiranya-desktop] [main]  INFO ServerManager Starting transport http on port 8080
2008-03-26 15:21:24,739 [127.0.1.1-hiranya-desktop] [main]  INFO FIXTransportListener FIX transport listener initialized...
2008-03-26 15:21:24,789 [127.0.1.1-hiranya-desktop] [main]  INFO FIXSessionFactory FIX message logging method = file
2008-03-26 15:21:27,306 [127.0.1.1-hiranya-desktop] [main]  INFO FIXIncomingMessageHandler New FIX session created: FIX.4.0:SYNAPSE->BANZAI
2008-03-26 15:21:27,382 [127.0.1.1-hiranya-desktop] [main]  INFO ServerManager Starting transport fix
Mar 26, 2008 3:21:27 PM quickfix.mina.acceptor.AbstractSocketAcceptor startAcceptingConnections
INFO: Listening for connections at 0.0.0.0/0.0.0.0:9876
2008-03-26 15:21:27,398 [127.0.1.1-hiranya-desktop] [main]  INFO ServerManager Starting transport vfs
2008-03-26 15:21:27,398 [127.0.1.1-hiranya-desktop] [main]  INFO ServerManager Starting transport mailto
2008-03-26 15:21:27,398 [127.0.1.1-hiranya-desktop] [main]  INFO ServerManager Ready for processing

Listing 13: Synapse Console Output

What happens here is that Synapse creates a new FIX session in the acceptor mode and starts listening for FIX messages coming from Banzai.

Now you should tell Banzai and Executor to establish sessions with Synapse. For that we need to find and modify the FIX configuration files for Banzai and Executor. These applications are packed to a jar file called quickfixj-examples.jar along with their configuration files in the Quickfix/J binary distribution and they are by default configured to directly send messages to each other. The easiest wat to modify Banzai and Executor configurations would be to extract the quickfixj-examples.jar file, edit the relevant configuration files and create the jar file back. Once you have extracted the quickfixj-examples.jar file you will get a directory called 'quickfix'. I will refer to this directory as QFJ_SAMPLES_HOME. The configuration file for Banzai is at QFJ_SAMPLES_HOME/examples/banzai/banzai.cfg and the configuration file for Executor can be found at QFJ_SAMPLES_HOME/examples/executor/executor.cfg. You can edit these two files and create the jar file back.

Edit the Banzai configuration file so it looks as follows.

[default]
FileStorePath=examples/target/data/banzai
ConnectionType=initiator
SenderCompID=BANZAI
TargetCompID=SYNAPSE
SocketConnectHost=localhost
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ReconnectInterval=5

[session]
BeginString=FIX.4.0
SocketConnectPort=9876

Listing 14: Modified Banzai Configuration

What we have done here is simply changing the TargetCompID property value from EXEC to SYNAPSE and removing settings for some of the sessions. This file usually has settings for five FIX sessions. But we will be only using one FIX session for this scenario. So we remove the settings for last four sessions in the file.

Now edit the Executor configuration so it looks as follows.

[default]
FileStorePath=examples/target/data/executor
ConnectionType=acceptor
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ValidOrderTypes=1,2,F
SenderCompID=EXEC
TargetCompID=SYNAPSE
UseDataDictionary=Y
DefaultMarketPrice=12.30

[session]
BeginString=FIX.4.0
SocketAcceptPort=19876

Listing 15: Modified Executor Configuration

Here also we have changed the TargetCompID property value from BANZAI to SYNAPSE. Also we have removed settings for the last four sessions and changed the SocketAcceptPort value from 9876 to 19876. Note that this is the port we specified in our FIX EPR when writing the Synapse configuration.

Once completed, start Executor and Banzai. Since Synapse is already on-line and ready to accept the traffic from Banzai, a FIX session will be established in that end. You should see something like the following on the console where you started Synapse.


INFO: MINA session created: /127.0.0.1:42476
2008-03-26 15:32:20,126 [127.0.1.1-hiranya-desktop] [QFJ Message Processor]  INFO FIXIncomingMessageHandler FIX session logged on: FIX.4.0:SYNAPSE->BANZAI

Listing 16: Synapse Console Output

Now send an order from Banzai and see.

2008-03-26 15:33:15,024 [127.0.1.1-hiranya-desktop] [fix-Worker-1]  INFO LogMediator To: , WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:678F043771C4B9BB5F1206525794944, Direction: request, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><message inSession="FIX.4.0:SYNAPSE->BANZAI" counter="1"><header><field id="8"><![CDATA[FIX.4.0]]></field><field id="9"><![CDATA[102]]></field><field id="34"><![CDATA[3]]></field><field id="35"><![CDATA[D]]></field><field id="49"><![CDATA[BANZAI]]></field><field id="52"><![CDATA[20080326-10:03:14]]></field><field id="56"><![CDATA[SYNAPSE]]></field></header><body><field id="11"><![CDATA[1206525794862]]></field><field id="21"><![CDATA[1]]></field><field id="38"><![CDATA[2]]></field><field id="40"><![CDATA[1]]></field><field id="54"><![CDATA[1]]></field><field id="55"><![CDATA[DELL]]></field><field id="59"><![CDATA[0]]></field></body><trailer><field id="10"><![CDATA[095]]></field></trailer></message></soapenv:Body></soapenv:Envelope>
2008-03-26 15:33:15,051 [127.0.1.1-hiranya-desktop] [fix-Worker-1]  INFO TimeoutHandler This engine will expire all callbacks after : 86400 seconds, irrespective of the timeout action, after the specified or optional timeout
2008-03-26 15:33:15,064 [127.0.1.1-hiranya-desktop] [fix-Worker-1]  INFO FIXSessionFactory FIX message logging method = file
2008-03-26 15:33:15,074 [127.0.1.1-hiranya-desktop] [fix-Worker-1]  INFO FIXIncomingMessageHandler New FIX session created: FIX.4.0:SYNAPSE->EXEC
Mar 26, 2008 3:33:16 PM quickfix.mina.initiator.InitiatorIoHandler sessionCreated
INFO: MINA session created: /127.0.0.1:39010
2008-03-26 15:33:17,351 [127.0.1.1-hiranya-desktop] [QFJ Message Processor]  INFO FIXIncomingMessageHandler FIX session logged on: FIX.4.0:SYNAPSE->EXEC
2008-03-26 15:33:17,534 [127.0.1.1-hiranya-desktop] [fix-Worker-2]  INFO LogMediator To: , WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:678F043771C4B9BB5F1206525797553, Direction: response, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><message inSession="FIX.4.0:SYNAPSE->EXEC" counter="1"><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>
2008-03-26 15:33:17,573 [127.0.1.1-hiranya-desktop] [fix-Worker-3]  INFO LogMediator To: , WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:678F043771C4B9BB5F1206525797592, Direction: response, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><message inSession="FIX.4.0:SYNAPSE->EXEC" counter="2"><header><field id="8"><![CDATA[FIX.4.0]]></field><field id="9"><![CDATA[130]]></field><field id="34"><![CDATA[3]]></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[12.3]]></field><field id="11"><![CDATA[1206525794862]]></field><field id="14"><![CDATA[2]]></field><field id="17"><![CDATA[2]]></field><field id="20"><![CDATA[0]]></field><field id="31"><![CDATA[12.3]]></field><field id="32"><![CDATA[2]]></field><field id="37"><![CDATA[2]]></field><field id="38"><![CDATA[2]]></field><field id="39"><![CDATA[2]]></field><field id="54"><![CDATA[1]]></field><field id="55"><![CDATA[DELL]]></field></body><trailer><field id="10"><![CDATA[236]]></field></trailer></message></soapenv:Body></soapenv:Envelope>

Listing 17: Synapse Console Output

It will take some time for the replies to arrive for the first order request since Synapse has to establish a session with the Executor. But all the subsequent orders will pass through almost instantaneously. So that is basically it. You have successfully integrated two FIX applications using Apache Synapse. The basic steps you had to go through can be summarized as follows:

  • Create a FIX configuration file for the acceptor
  • Create a FIX configuration file for the initiator
  • Write the Synapse configuration (proxy service) and point it to the two configuration files using transport.fix.AcceptorConfigURL and transport.fix.InitiatorConfigURL parameters

Now, how convenient is that?

If you take a close look at the message logs created by Synapse you will notice that Synapse has converted FIX messages into XML and embedded them in SOAP envelopes. The order requests sent from Banzai looks like the following when converted into SOAP.

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <message inSession="FIX.4.0:SYNAPSE->EXEC" counter="1">
            <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>

Listing 18: FIX Message Embedded in SOAP

The advantage of converting the entire FIX message into XML is that XML messages can be easily manipulated within the Synapse core using technologies like Xpath. So you have more control over the content of the FIX messages at Synapse level.

While performing the mediation, Synapse guarantees that messages are sent out in the exact order they were received. This is done in order to facilitate the in-order message delivery property of FIX protocol. Also, the two parties that communicate via Synapse can use, DeliverTo and OnBehalf fields in the FIX message headers, to indicate that a third party routing takes place in the middle. Synapse will handle those fields as specified in the FIX protocol specification.

You can add more flavor to the mediation process defined in the above Synapse configuration by defining a few more parameters. For an example you can tell Synapse to log the messages at the transport level before converting them into SOAP. Simply add the following two lines to the configuration and try for yourself.

<parameter name=”transport.fix.AcceptorLogFactory”>console</parameter>
<parameter name=”transport.fix.InitiatorLogFactory”>console</parameter>

Listing 19: Optional Service Parameters

Inserting the above two parameters in the Synapse configuration will command Synapse to log FIX messages at transport level for both the acceptor and the initiator. The value 'console' indicates that messages should be logged on to the console. You can also pass in values like 'file' or 'jdbc' for these parameters. All other parameters related to these log factories should be specified in the corresponding FIX configuration files as specified in the Quickfix/J user manual.

 

Summary

The FIX protocol is a messaging standard developed specifically for the real-time electronic exchange of securities transactions. It has a large user base and is increasingly becoming the global language of choice for finance related information exchanges. Apache Synapse is the first open source ESB to provide support for the FIX protocol. Integrating FIX applications using Synapse is a simple 3-step task.

 

Resources

 

Author

Hiranya Jayathilaka, Trainee Software Engineer at WSO2, hiranya at wso2 dot com

WSO2Con 2014 USA