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:

  1. Install FIX Antenna Javaâ„¢
  2. Update your project to include FIX Antenna libraries
  3. Convert QuickFIX/J configuration files into FIX Antenna Javaâ„¢ format
  4. Update your project to replace QuickFIX/J API with FIX Antenna API
  5. Optional. Convert the dictionaries into FIXDIC format
  6. 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.  

  1. Use the XML Dictionary Convertion utility (packaged separately) to convert QuickFIX XML definition into XML format suitable for further use with FIX Antenna.
  2. 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.