This chapters explains how to create a simple application step-by step with samples. The usual scenario to get it to work is:
Session-acceptor is created in the following way:
// implements FIXServerListener to get notifications about new connections public class SimpleServer 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 { FIXServer server = new FIXServer(); // create server that will listen for TCP/IP connections server.setPort(777); // setting port it will listen to server.setListener(new SimpleServer()); // setting listener for new connections server.start(); // this will start new thread and listen for incoming connections System.out.println("Press enter to exit"); System.in.read(); // preventing application from exiting server.stop(); // this will stop the thread that listens for new connections } // this method is called for every new connection public void newFIXSession(FIXSession session) { try { activeSessions.add(session); // Once user lost all references to his session - it will be disposed and gc'ed eventually! session.setFIXSessionListener(new MyFIXSessionListener(session)); // setting listener for incoming messages session.connect(); // accepting connection } 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) { // if disconnected, remove it from the list to let GC collect it if (SessionState.DISCONNECTED == sessionState) { activeSessions.remove(session); } } // here you can process incoming messages public void onNewMessage(FIXFieldList message) { } } }
Session-initiator is created in three steps:
// creating connection parameters SessionParameters details = new SessionParameters(); details.setFixVersion(FIXVersion.FIX42); details.setHost("localhost"); details.setHeartbeatInterval(30); details.setPort(777); details.setSenderCompId("senderId"); details.setTargetCompId("targetId"); // listener for incoming messages and session state changes FIXSessionListener application = new FIXSessionListener() { // this method will be called every time session state is changed public void onSessionStateChange(SessionState sessionState) { System.out.println("Session state changed:" + sessionState); // this callback is called upon session state change } // processing incoming messages public void onNewMessage(FIXFieldList message) { System.out.println("New application level message type: " + message.getTagValueAsString(FIXT11.Header.MsgType) + "received"); // this callback is called upon new message arrival } }; // create session we intend to work with final FIXSession session = details.createNewFIXSession(); // setting listener for incoming messages session.setFIXSessionListener(application); // initiate connection session.connect();
FIX Antenna provides two interfaces for manipulations with FIX messages:
The flat model is based on a single FIXFieldList class and exports high performance.
// create FIX 4.4 New Order Single FIXFieldList messageContent = new FIXFieldList(); messageContent.addTag(11, "USR20000101"); messageContent.addTag(54, 1); messageContent.addTag(60, "20000101-01:12:55");
The object model is a typified interface less efficient than the flat model, but more user-friendly.
// create FIX 4.4 New Order Single NewOrderSingle order = new NewOrderSingle(); order.getHeader().setBeginString(FIXVersion.FIX44.getMessageVersion()); order.getHeader().setMsgType("D"); // set ClOrdID order.setClOrdID( "USR20000101" ); // get ClOrdID String clOrdID = order.getClOrdID();
Message is sent asynchronously by calling the session.sendMessage method. Consequently the message is scheduled for sending in the internal queue and sent in a separate thread. This means that if the method returns control, the message is not necessarily already sent. The fastest standard way of sending a message out is to use the sendMessage(String messageType, FIXFieldList content) method. This message adds proper footer and header.
// Send news to session initiator or acceptor session.sendMessage("B", messageContent); // news
Alternatively, if a user has entire FIXMessage in FIXFieldList including header and footer, it is possible to use the sendMessage(FIXFieldList message) method. Header and footer fields will be updated but it will take more time then just to wrap message content, so the first option is preferred.
// Send news to session initiator or acceptor session.sendMessage(message); // news
Implement the FIXSessionListener interface to process incoming messages and session changes:
private class MyFIXSessionListener implements FIXSessionListener { private FIXSession session; public MyFIXSessionListener(FIXSession session) { this.session = session; } public void onSessionStateChange(SessionState sessionState) { if (SessionState.DISCONNECTED == sessionState) { activeSessions.remove(session); } } public void onNewMessage(FIXFieldList message) { log.debug("New app message type " + new String(message.getMsgType()) + "received for session" + session.toString()); } }
The FIXSessionListener.onNewMessage() method is called only in case of the delivery of an incoming application-level message, if all checks are passed. Possible errors and all session-level messages are handled inside the FIXEngine. The FIXEngine guarantees sequential message delivery in the order of receiving.
Note: It is possible to provide custom session level handlers if desired, but it may affect FIXEngine workflow and the FIX protocol support so it is not recommended unless absolutely necessary.
Note: the FIXSessionListener.onNewMessage method must not be dead-locked or perform time-demanding operations, because it will lock entire message processing for this session. A user should execute time consuming handling operations in separate threads and return control as soon as possible..
Use the following methods to close the session:
session.disconnect("User request");
session.dispose();
Combining all above:
package com.epam.example; import com.epam.fix.message.FIXFieldList; import com.epam.fixengine.*; import java.io.IOException; import java.util.ArrayList; import java.util.List; //implements FIXServerListener to get notified about new connections public class SimpleServer implements FIXServerListener { // all active sessions should have references or will be GCed public static void main(String[] args) throws IOException { // create a server that will listen for TCP/IP connections FIXServer server = new FIXServer(); // setting the port it will listen to server.setPort(777); // setting the listener for new connections server.setListener(new SimpleServer()); // this will start a new thread and listen for incoming connections server.start(); System.out.println("Server started..."); // preventing the application from exiting System.in.read(); // this will stop the thread that listens for new connections server.stop(); } // this method is called for every new connection public void newFIXSession(FIXSession session) { try { // setting listener for incoming messages session.setFIXSessionListener(new MyFIXSessionListener(session)); // accepting a connection session.connect(); System.out.println("New connection accepted"); } 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."); } } // here you can process incoming messages public void onNewMessage(FIXFieldList message) { System.out.println("New message is accepted: " + message.toString()); } } }
package com.epam.example; import com.epam.common.FIXVersion; import com.epam.fix.message.FIXFieldList; import com.epam.fix.message.constants.FIXT11; import com.epam.fixengine.*; import java.io.IOException; public class SimpleNewsBroadcaster { public static void main(String[] args) throws IOException { // creating connection parameters SessionParameters details = new SessionParameters(); details.setFixVersion(FIXVersion.FIX42); details.setHost("localhost"); details.setHeartbeatInterval(30); details.setPort(777); details.setSenderCompId("senderId"); details.setTargetCompId("targetId"); // create a session we intend to work with final FIXSession session = details.createNewSession(); // listener for incoming messages and session state changes FIXSessionListener application = new FIXSessionListener() { // this method will be called every time session state is changed public void onSessionStateChange(SessionState sessionState) { System.out.println("Session state changed:" + sessionState); // this callback is called upon session state change if (sessionState == SessionState.DISCONNECTED) { // end this session session.dispose(); } } // processing incoming messages public void onNewMessage(FIXFieldList message) { System.out.println("New application level message type: " + message.getTagValueAsString(FIXT11.Header.MsgType) + "received"); // this callback is called upon new message arrival } }; // setting listener for incoming messages session.setFIXSessionListener(application); // initiate a connection session.connect(); // create FIX 4.2 News FIXFieldList messageContent = new FIXFieldList(); messageContent.addTag(148, "Hello there"); // Add Subject messageContent.addTag(33, 3); // Add Repeating group messageContent.addTag(58, "line1"); messageContent.addTag(58, "line2"); messageContent.addTag(58, "line3"); // sending a message session.sendMessage("B", messageContent); try { Thread.sleep(100); // sleep for some time to ensure message delivery. Other flow control procedures should // be used in real applications. } catch (Exception e) { } // disconnecting session.disconnect("User request"); } }