[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.
|