[Quickfix-users] Modifying toAdmin/toApp messages
Brought to you by:
orenmnero
From: Brian E. <azz...@ya...> - 2004-12-31 05:13:36
|
As I am relatively new to QuickFIX, this may have already been covered in the past (I did a search across the mailing list archive and didn't see much on it though). It seems to me that the use of toApp and toAdmin needs to be better documented and that there might be a need for a message cracker specific to these messages. None of the examples, for instance, make use of either of these methods (except for a token check of the PossDupFlag in TradeClient). The FIX server I was connecting to required the use of the Username and Password fields in a Logon message. It took a long time perusing the mailing list and reading the source code to figure out that I'd need to use the toApp method to trap the automatically generated Logon message and modify that message. After that, I bumped into a slight problem with message cracking. The MessageCracker class can crack any message, but will only dispatch those messages as "const", which requires a cast in order to add the appropriate fields (I created a non-const pointer to the Logon message and set the fields). Is there/should there be an "inbound" message cracker and an "outbound" message cracker? "Inbound" messages would have a "const" modifier to prevent changes to the message, while "outbound" messages would be non-const so the message could be modified (or "decorated") prior to being sent. For backward compatibility, the "inbound" message cracker could continue to be MessageCracker, while a new class could handle the "outbound" message cracking/decorating. I'd foresee something like: class MessageDecorator { public: virtual ~MessageDecorator() {} virtual void decorateMessage(Message&, const FIX::SessionID&) {throw FIX::UnsupportedMessageType();} virtual void decorateMessage(Heartbeat&, const FIX::SessionID&) {} virtual void decorateMessage(Logon &, const FIX::SessionID&) {} ... public: void decorate(Message & message, const FIX::SessionID & sessionID) { FIX::MsgType msgType; message.getHeader().getField(msgType); std::string msgTypeValue = msgType.getValue(); if (msgTypeValue == "0") decorateMessage((Heartbeat&)message, sessionID); else if (msgTypeValue == "A") decorateMessage((Logon&)message, sessionID); ... } } and Application could inherit from both MessageCracker and MessageDecorator. Then, when an Application-derived class needs to add fields to outbound messages, they simply override the toApp() or toAdmin() methods and override the appropriate decorator. Maybe this is overkill to avoid casting, but it also helps to separate the message flow - otherwise, a single "onMessage" method might be called by both inbound messages AND outbound messages (when systems are closer to being peers, you can often see the same messages going both ways) and you have to add additional checks (who does the SenderCompID point to in this message). Just an idea. I'm willing to put my money where my mouth is an write a C++ MessageDecorator class - it's a pretty simple modification of the existing MessageCracker class(es). I'll also look into updating the Wiki to document how things work now - assuming I accurately understand the process. - Brian Erst p.s. QuickFIX is a very impressive piece of work - none of the above should be construed as anything other than a wishlist item. |