Most of the messages you will be interested in looking at will be arriving in your overloaded fromApp function of your application. You can get fields out of messages with different degrees of type safety. The type in question here is the FIX message type. When the application passes you a Message class, the C++ type checker has no idea what specific FIX message it is, you must determine that dynamically. There is, however, a way we can make C++ aware of this type information. First we will cover how to dynamically retreive fields from a message, then we will show you the prefered type safe way. Keep in mind that all messages have a header and a trailer. If you want to see fields in them, you must first call getHeader() or getTrailer() to get access to them. Otherwise you use them just like the message.
This method of retreiving data from messages is strongly discouraged and is generally only useful for writing more low level interfaces for other languages and middleware.
Here is a sample code segment for this type of retrieval: See this code in C#, VB.NET, PYTHON, RUBYvoid fromApp( const FIX::Message& message, const FIX::SessionID& sessionID ) throw( FIX::FieldNotFound&, FIX::IncorrectDataFormat&, FIX::IncorrectTagValue&, FIX::UnsupportedMessageType& ) {// retreive value into string with integer field ID std::string value; value = message.getField(44); // retrieve value into a field base with integer field ID FIX::FieldBase field(44, ""); message.getField(field); // retreive value with an enumeration, a little better message.getField(FIX::FIELD::Price); }
A way to add some type safety to this is by using field classes that represent all the FIX defined fields. This is sometimes useful in an application, but is generally only used within code segments that need to be version independent (meaning versions of FIX). For example, our Session class is implemented using mostly these. It is generally not recomended for most applications. This will also get fields as their appropriate type, not just as strings.
See this code in C#, VB.NET, PYTHON, RUBYvoid fromApp( const FIX::Message& message, const FIX::SessionID& sessionID ) throw( FIX::FieldNotFound&, FIX::IncorrectDataFormat&, FIX::IncorrectTagValue&, FIX::UnsupportedMessageType& ) {// retreive value into field class FIX::Price price; message.getField(price); // another field... FIX::ClOrdID clOrdID; message.getField(clOrdID); }
Here is the most type safe and highly encouraged method for retreiving data from a message. QuickFIX has message classes that correlate to all the messages defined in the spec. They are, just like the field classes, generated directly off of the FIX specifications. To take advantage of this, you must break the messages out with the supplied MessageCracker. Also notice we are no longer using a generic Message class and we are now using get instead of getField. Keep in mind you can still use getField as all of these classes derive from Message
See this code in C#, VB.NET, PYTHON(not supported), RUBY(not supported)void fromApp( const FIX::Message& message, const FIX::SessionID& sessionID ) throw( FIX::FieldNotFound&, FIX::IncorrectDataFormat&, FIX::IncorrectTagValue&, FIX::UnsupportedMessageType& ) { crack(message, sessionID); } void onMessage( const FIX42::NewOrderSingle& message, const FIX::SessionID& ) { FIX::ClOrdID clOrdID; message.get(clOrdID); FIX::ClearingAccount clearingAccount; message.get(clearingAccount); } void onMessage( const FIX41::NewOrderSingle& message, const FIX::SessionID& ) { FIX::ClOrdID clOrdID; message.get(clOrdID);// compile time error!! field not defined in FIX41 FIX::ClearingAccount clearingAccount; message.get(clearingAccount); } void onMessage( const FIX42::OrderCancelRequest& message, const FIX::SessionID& ) { FIX::ClOrdID clOrdID; message.get(clOrdID); // compile time error!! field not defined for OrderCancelRequest FIX::Price price; message.get(price); }
In order to use this you must use the MessageCracker as a mixin to your application.
This will provide you with the crack function and allow you to overload specific message
functions. Any function you do not overload will by default throw an UnsupportedMessageType
exception
Define your application like this:
#include "quickfix/Application.h" #include "quickfix/MessageCracker.h" class MyApplication : public FIX::Application, public FIX::MessageCracker