QuickFIX/J to FIX Antenna Java migration guide
Steps to migrate from QuickFIX/J to FIX Antenna Java
Typically in order to migrate you need to do the following steps:
- Install FIX Antenna Javaâ„¢
- Update your project to include FIX Antenna libraries
- Convert QuickFIX/J configuration files into FIX Antenna Javaâ„¢ format
- Update your project to replace QuickFIX/J API with FIX Antenna API
- Optional. Convert the dictionaries into FIXDIC format
- Compile and run
1. Install FIX Antenna Java™
- Download FIX Antenna package from b2bits.com
- Install it according to manual
- Ensure sample are build-able and run-able
2. Update your project to include FIX Antenna libraries
 Update your Ant, Maven or Gradle project to use fixaj-engine-full-2.15.16/lib/all-in-one-engine/fixaj-engine-all-2.15.16.jar (version may be different).
3. Convert QuickFIX/J configuration files into FIX Antenna Javaâ„¢ format
QuickFIX/J | FIX Antenna Java |
---|---|
[default] FileStorePath=target/data/app HeartBtInt=30 BeginString=FIX.4.4 StartTime=00:00:00 EndTime=00:00:00 [session] ConnectionType=initiator SocketConnectHost=localhost SocketConnectPort=9876 SenderCompID=BANZAI TargetCompID=EXEC ReconnectInterval=5 [session] ConnectionType=acceptor SenderCompID=EXEC TargetCompID=BANZAI SocketAcceptPort=9880 | sessionIDs=initiatorS, acceptorS #Default session parameters sessions.default.storageDirectory=target/data/app sessions.default.heartbeatInterval=30 sessions.default.fixVersion=FIX.4.4 ## Session initiatorS sessions.initiatorS.sessionType=initiator sessions.initiatorS.host=localhost sessions.initiatorS.port=9876 sessions.initiatorS.senderCompID=BANZAI sessions.initiatorS.targetCompID=EXEC //0 - infinitive autoreconnect sessions.initiatorS.autoreconnectAttempts=0 sessions.initiatorS.autoreconnectDelayInMs=5000 ## Session acceptorS sessions.acceptorS.sessionType=acceptor sessions.acceptorS.senderCompID=EXEC sessions.acceptorS.targetCompID=BANZAI |
4. Update your project to replace QuickFIX/J API with FIX Antenna API
4.1. Session configuration and start - Acceptor
The example below will start the server with acceptor session only defined in configuration file from section 3. To start the server with initiator session - please see section 4.2
QuickFIX/J | FIX Antenna Java |
---|---|
import quickfix.*; import java.io.FileInputStream; public class QFJApp { public static void main(String args[]) throws Exception { if (args.length != 1) { return; } // path to file with session's configuration String fileName = args[0]; // FooApplication is your class that implements the Application interface Application application = new FooApplication(); SessionSettings settings = new SessionSettings(new FileInputStream(fileName)); MessageStoreFactory storeFactory = new FileStoreFactory(settings); MessageFactory messageFactory = new DefaultMessageFactory(); // start acceptor Acceptor acceptor = new SocketAcceptor(application, storeFactory, settings, messageFactory); acceptor.start(); // preventing application from exiting System.out.println("Press enter to exit"); System.in.read(); acceptor.stop(); } } | import com.epam.fix.message.FIXFieldList; import com.epam.fixengine.*; import com.epam.fixengine.acceptor.DenyNonRegisteredAcceptorStrategyHandler; import com.epam.fixengine.configuration.Configuration; import java.io.IOException; import java.util.ArrayList; import java.util.List; // implements FIXServerListener to get notifications about new connections public class SimpleAcceptorServer implements FIXServerListener { // all active sessions should have references or will be GCed private List<FIXSession> activeSessions = new ArrayList<FIXSession>(); public static void main(String[] args) throws IOException { if (args.length != 1) { return; } String fileName = args[0]; // enable server strategy for accepting only registered sessions Configuration globalServerConfig = Configuration.getGlobalConfiguration(); globalServerConfig.setProperty(Configuration.SERVER_ACCEPTOR_STRATEGY, DenyNonRegisteredAcceptorStrategyHandler.class.getCanonicalName()); // create server that will listen for TCP/IP connections FIXServer server = new FIXServer(); server.setPort(9880); // setting listener for new connections server.setListener(new SimpleAcceptorServer()); // setting path to properties file with sessions server.setConfigPath(fileName); // starting new thread and listen for incoming connections server.start(); // preventing application from exiting System.out.println("Press enter to exit"); System.in.read(); // stop the thread that listens for new connections server.stop(); } // this method is called for every new connection public void newFIXSession(FIXSession session) { try { activeSessions.add(session); // setting listener for incoming messages; // MyFIXSessionListener is is your class that implements // the FIXSessionListener interface session.setFIXSessionListener(new MyFIXSessionListener(session)); // accept incoming session session.connect(); } catch (IOException e) { } } } |
4.2. Session configuration and start - Initiator
QuickFIX/J | FIX Antenna Java |
---|---|
import quickfix.*; import java.io.FileInputStream; public class QFJInitiator { public static void main(String args[]) throws Exception { if (args.length != 1) return; // path to file with session's configuration String fileName = args[0]; // FooApplication is your class that implements the Application interface Application application = new FooApplication(); SessionSettings settings = new SessionSettings(new FileInputStream(fileName)); MessageStoreFactory storeFactory = new FileStoreFactory(settings); MessageFactory messageFactory = new DefaultMessageFactory(); Initiator initiator = new SocketInitiator(application, storeFactory, settings, messageFactory); initiator.start(); // preventing application from exiting System.out.println("Press enter to exit"); System.in.read(); initiator.stop(); } } | import com.epam.fix.message.FIXFieldList; import com.epam.fix.message.constants.FIXT11; import com.epam.fixengine.*; import com.epam.fixengine.session.util.SessionParametersBuilder; import java.io.IOException; public class SimpleInitiator { public static void main(String[] args) throws IOException { if (args.length != 1) { return; } String fileName = args[0]; //load initiator configuration SessionParameters details = SessionParametersBuilder.buildSessionParameters(fileName, "initiatorS"); // create session we intend to work with final FIXSession session = details.createNewFIXSession(); // setting listener for incoming messages; // MyFIXSessionListener is is your class that implements // the FIXSessionListener interface session.setFIXSessionListener(new MyFIXSessionListener(session)); // initiate connection try { session.connect(); } catch (IOException e) { } // preventing application from exiting System.out.println("Press enter to exit"); System.in.read(); // stop the thread that listens for new connections session.disconnect("user request"); } } |
4.3. Compose message: flat model
QuickFIX/J | FIX Antenna Java |
---|---|
Message message = new Message(); // BeginString message.getHeader().setField(new StringField(8, "FIX.4.2")); // SenderCompID message.getHeader().setField(new StringField(49, "TW")); // TargetCompID message.getHeader().setField(new StringField(56, "TARGET")); // MsgType message.getHeader().setField(new CharField(35, 'F')); // ClOrdID message.setField(new StringField(11, "321")); // Side, with value enumeration message.setField(new CharField(54, Side.BUY))); // ... and other fields as necessary ... | FIXFieldList messageContent = new FIXFieldList(); // BeginString messageContent.addTag(8, "FIX.4.2"); // SenderCompID messageContent.addTag(49, "TW"); // TargetCompID messageContent.addTag(56, "TARGET"); // MsgType messageContent.addTag(35, "F"); // ClOrdID message.addTag(11, "321"); // Side message.addTag(54, Side.BUY.getValue()); // ... and other fields as necessary ... |
4.4. Compose message: object model (not recomened for FIXAJ due to low perfomance)
QuickFIX/J | FIX Antenna Java |
---|---|
quickfix.fix42.ExecutionReport message = new quickfix.fix42.ExecutionReport ( new ClOrdID("321"), new ExecType("1"), new OrdStatus("2"), new LeavesQty(0.0)); | // Create an "Execution Report" message for FIX 4.2 ExecutionReport exec = new ExecutionReport(); exec.setClOrdID("321"); exec.setExecType('1'); exec.setOrdStatus('2'); exec.setLeavesQty(0.0); |
4.5. Create message with repeating groups
QuickFIX/J | FIX Antenna Java |
---|---|
public void createRG(){ quickfix.fix42.MarketDataSnapshotFullRefresh message = new quickfix.fix42.MarketDataSnapshotFullRefresh(new Symbol("QF")); quickfix.fix42.MarketDataSnapshotFullRefresh.NoMDEntries group = new quickfix.fix42.MarketDataSnapshotFullRefresh.NoMDEntries(); group.set(new MDEntryType('0')); group.set(new MDEntryPx(12.32)); group.set(new MDEntrySize(100)); group.set(new OrderID("ORDERID")); message.addGroup(group); group.set(new MDEntryType('1')); group.set(new MDEntryPx(12.32)); group.set(new MDEntrySize(100)); group.set(new OrderID("ORDERID")); message.addGroup(group); } | public void createRG(){ FIXFieldList message = FIXFieldListFactory.newInstanceFromPool(); message.addTag(Symbol, "QF"); RepeatingGroup group = message.addRepeatingGroup(NoMDEntries); RepeatingGroup.Entry entry1 = group.addEntry(); entry1.addTag(MDEntryType, '0'); entry1.addTag(MDEntryPx, 12.32, 2); entry1.addTag(MDEntrySize, 100); entry1.addTag(OrderID, "ORDERID"); RepeatingGroup.Entry entry2 = group.addEntry(); entry2.addTag(MDEntryType, '1'); entry2.addTag(MDEntryPx, 12.32, 2); entry2.addTag(MDEntrySize, 100); entry2.addTag(OrderID, "ORDERID"); //return objects to pool entry1.release(); entry2.release(); group.release(); } |
4.6. Reading message with repeating group
QuickFIX/J | FIX Antenna Java |
---|---|
public void processRG(quickfix.fix42.MarketDataSnapshotFullRefresh message) throws FieldNotFound { NoMDEntries noMDEntries = new NoMDEntries(); message.get(noMDEntries); quickfix.fix42.MarketDataSnapshotFullRefresh.NoMDEntries group = new quickfix.fix42.MarketDataSnapshotFullRefresh.NoMDEntries(); MDEntryType MDEntryType = new MDEntryType(); MDEntryPx MDEntryPx = new MDEntryPx(); MDEntrySize MDEntrySize = new MDEntrySize(); OrderID orderID = new OrderID(); message.getGroup(1, group); group.get(MDEntryType); group.get(MDEntryPx); group.get(MDEntrySize); group.get(orderID); message.getGroup(2, group); group.get(MDEntryType); group.get(MDEntryPx); group.get(MDEntrySize); } | public void processRG(FIXFieldList message) { RepeatingGroup group = message.getRepeatingGroup(NoMDEntries); RepeatingGroup.Entry entry = group.getEntry(0); byte mdEntryType = entry.getTagValueAsByte(MDEntryType); double mdEntryPx = entry.getTagValueAsDouble(MDEntryPx); long mdEntrySize = entry.getTagValueAsLong(MDEntrySize); String orderId = entry.getTagValueAsString(OrderID); entry = group.getEntry(1); mdEntryType = entry.getTagValueAsByte(MDEntryType); mdEntryPx = entry.getTagValueAsDouble(MDEntryPx); mdEntrySize = entry.getTagValueAsLong(MDEntrySize); orderId = entry.getTagValueAsString(OrderID); } |
4.7. Sending message
QuickFIX/J | FIX Antenna Java |
---|---|
void sendOrderCancelRequest() throws SessionNotFound { quickfix.fix41.OrderCancelRequest message = new quickfix.fix41.OrderCancelRequest( new OrigClOrdID("123"), new ClOrdID("321"), new Symbol("LNUX"), new Side(Side.BUY)); message.set(new Text("Cancel My Order!")); Session.sendToTarget(message, "TW", "TARGET"); } | void sendOrderCancelRequest(FIXSession session) { FIXFieldList message = FIXFieldListFactory.newInstanceFromPool(); message.addTag(OrigClOrdID, "123"); message.addTag(ClOrdID, "321"); message.addTag(Symbol, "LNUX"); message.addTag(Side, BUY.getValue()); message.addTag(Text, "Cancel My Order!"); session.sendMessage("F", message); } |
4.8. Receiving and cracking message
QuickFIX/J | FIX Antenna Java |
---|---|
private static class FooApplication implements Application { //... other methods // here you can process incomming messages public void fromApp(Message message, SessionID sessionID) throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue { StringField field = new StringField(55); message.getField(field); } } | class MyFIXSessionListener implements FIXSessionListener { //... other methods // here you can process incoming messages public void onNewMessage(FIXFieldList message) { String symbol = message.getTagValueAsString(55); // or other getTagValueAsXXX() methods } } |
4.9. Minimal sample
QuickFIX/J | FIX Antenna Java |
---|---|
import quickfix.*; import java.io.FileInputStream; public class QFJApp { public static void main(String args[]) throws Exception { if (args.length != 1) { return; } // path to file with session's configuration String fileName = args[0]; // FooApplication is your class that implements the Application interface Application application = new FooApplication(); SessionSettings settings = new SessionSettings(new FileInputStream(fileName)); MessageStoreFactory storeFactory = new FileStoreFactory(settings); MessageFactory messageFactory = new DefaultMessageFactory(); // start acceptor Acceptor acceptor = new SocketAcceptor(application, storeFactory, settings, messageFactory); acceptor.start(); // preventing application from exiting System.out.println("Press enter to exit"); System.in.read(); acceptor.stop(); } private static class FooApplication implements Application { public void onCreate(SessionID sessionId) {} public void onLogon(SessionID sessionId) {} public void onLogout(SessionID sessionId) {} public void toAdmin(Message message, SessionID sessionId) {} public void toApp(Message message, SessionID sessionId) throws DoNotSend {} public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon {} public void fromApp(Message message, SessionID sessionId) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType { System.out.println("New message is accepted: " + message.toString()); } } } | import com.epam.fix.message.FIXFieldList; import com.epam.fixengine.*; import com.epam.fixengine.acceptor.DenyNonRegisteredAcceptorStrategyHandler; import com.epam.fixengine.configuration.Configuration; import java.io.IOException; import java.util.ArrayList; import java.util.List; // implements FIXServerListener to get notifications about new connections public class SimpleAcceptorServer implements FIXServerListener { // all active sessions should have references or will be GCed private List<FIXSession> activeSessions = new ArrayList<FIXSession>(); public static void main(String[] args) throws IOException { if (args.length != 1) { return; } String fileName = args[0]; // enable server strategy for accepting only registered sessions Configuration globalServerConfig = Configuration.getGlobalConfiguration(); globalServerConfig.setProperty(Configuration.SERVER_ACCEPTOR_STRATEGY, DenyNonRegisteredAcceptorStrategyHandler.class.getCanonicalName()); // create server that will listen for TCP/IP connections FIXServer server = new FIXServer(); server.setPort(9880); // setting listener for new connections server.setListener(new SimpleAcceptorServer()); // setting path to properties file with sessions server.setConfigPath(fileName); // starting new thread and listen for incoming connections server.start(); // preventing application from exiting System.out.println("Press enter to exit"); System.in.read(); // stop the thread that listens for new connections server.stop(); } // this method is called for every new connection public void newFIXSession(FIXSession session) { try { activeSessions.add(session); // setting listener for incoming messages; // MyFIXSessionListener is is your class that implements // the FIXSessionListener interface session.setFIXSessionListener(new MyFIXSessionListener(session)); // accept incoming session session.connect(); } catch (IOException e) { } } // listener for incoming messages and session state changes private class MyFIXSessionListener implements FIXSessionListener { private FIXSession session; public MyFIXSessionListener(FIXSession session) { this.session = session; } // this method will be called every time session state is changed public void onSessionStateChange(SessionState sessionState) { System.out.println("Session state: " + sessionState); // if disconnected, dispose it to let GC collect it if (SessionState.DISCONNECTED == sessionState) { session.dispose(); System.out.println("Your session has been disconnected." + " Press ENTER to exit the programm."); } } public void onNewMessage(FIXFieldList message) { System.out.println("New message is accepted: " + message.toString()); } } } |
5. Optional. Convert the dictionaries into FIXDIC format
If you'd like to use custom validation for FIX messages with FIX Antenna Java you have convert your custom QuickFIX XML FIX dictionaries into XML format suitable for further use with FIX Antenna. Â
- Use the XML Dictionary Convertion utility (packaged separately) to convert QuickFIX XML definition into XML format suitable for further use with FIX Antenna.
- Replace standard FIX Antenna dictionaries (fixprotocol-fix-X.Y.Z.jar) with generated
6. Compile and run
Compile and run you application with Java 7 or above.