In this article by Hiranya Jayathilaka, he illustrates Apache Synapse [1] support for the Financial Information eXchange protocol (FIX).
Apache Synapse [2] is a lightweight mediation framework for Web services. It is based on Apache Axis2 [3] 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 [3]
- Applies To [3]
- Table of Contents [3]
- Introduction to FIX Protocol [3]
- FIX Message Format [3]
- FIX Sessions [3]
- Introduction to Quickfix/J [3]
- FIX Support in Apache Synapse [3]
- Banzai and Executor [3]
- Connecting Banzai and Executor Using Synapse [3]
- Summary [3]
- Resources [3]
FIX protocol [4] 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? [5]' 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.
Quickfix/J [6], 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 [7] 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.
sample FIX applications [8] that comes with every Quickfix/J distribution. So please download [9] 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.
Quickfix/J configuration files [10]. 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&SenderCompID=SYNAPSE&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.
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 [11] 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 [12].
Apache Synapse [13] - Apache Synapse is an open source light weight mediation framework for Web services
Author
Hiranya Jayathilaka, Trainee Software Engineer at WSO2, hiranya at wso2 dot com