ResendRequest

Imported from previous forum

Hi,

I am trying to create a Trade Auditor for my QuickFix/J Trading app. I started with using the OrderStatusRequest message but realized not all ECNs have that implemented. I had to resort to using the ResendRequest message instead. I am receiving all the resent messages with the PossDupFlag set (43=Y) in the FIX logs but my application is not picking up these messages. Is there a config that I have set unknowingly?

Kind Regards,
Umair.

Apparently, these duplicate messages are all discarded at the Session layer at Session.verify(). Does anyone know of a configuration to allow these messages in to the Application layer?

Rgds,
Umair.

Hi,

I am using 1.3.2 and Yes I can reproduce the problem quite easily. Every time I send out a resend request, all duplicate messages received from all ECNs are ignored. This is part of the FIX spec and in the code too, unfortunately, so it is highly unlikely your tests were centred around resend requests unless you found a way around it. My config file is as follows:

[default]
FileStorePath=*******
FileLogPath=*******
DataDictionary=Fix42.xml
BeginString=FIX.4.2
ConnectionType=initiator
Account=*******
Password=*******

[session]
SenderCompID=*******
TargetCompID=*******
SocketConnectPort=*******
SocketConnectHost=*******
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ResetToSender=Y
ResetOnLogout=Y
ResetOnDisconnect=Y
AggregatedBook=Y
SocketTcpNoDelay=Y
SocketReceiveBufferSize=32768
SocketSendBufferSize=32768

The following code is from the quickfix.Session class:

private boolean verify(Message msg, boolean checkTooHigh, boolean checkTooLow)
    throws RejectLogon, FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType, IOException
{
    String msgType;
    String senderCompID;
    String targetCompID;
    int msgSeqNum;
    try
    {
        Message.Header header = msg.getHeader();
        senderCompID = header.getString(49);
        targetCompID = header.getString(56);
        Date sendingTime = header.getUtcTimeStamp(52);
        msgType = header.getString(35);
        msgSeqNum = 0;
        if(checkTooHigh || checkTooLow)
            msgSeqNum = header.getInt(34);
        if(!validLogonState(msgType))
            throw new SessionException((new StringBuilder()).append("Logon state is not valid for message (MsgType=").append(msgType).append(")").toString());
        if(!isGoodTime(sendingTime))
        {
            doBadTime(msg);
            return false;
        }
    }
    catch(FieldNotFound e)
    {
        throw e;
    }
    catch(Exception e)
    {
        getLog().onEvent((new StringBuilder()).append(e.getClass().getName()).append(" ").append(e.getMessage()).toString());
        disconnect();
        return false;
    }
    if(!isCorrectCompID(senderCompID, targetCompID))
    {
        doBadCompID(msg);
        return false;
    }
    if(checkTooHigh && isTargetTooHigh(msgSeqNum))
    {
        doTargetTooHigh(msg);
        return false;
    }
    if(checkTooLow && isTargetTooLow(msgSeqNum))
    {
        doTargetTooLow(msg);
        return false;
    }
    if(isPossibleDuplicate(msg) && !validatePossDup(msg))
        return false;
    if((checkTooHigh || checkTooLow) && state.isResendRequested())
        synchronized(state.getLock())
        {
            int range[] = state.getResendRange();
            if(msgSeqNum >= range[1])
            {
                getLog().onEvent((new StringBuilder()).append("ResendRequest for messages FROM: ").append(range[0]).append(" TO: ").append(range[1]).append(" has been satisfied.").toString());
                state.setResendRange(0, 0);
            }
        }
    state.setLastReceivedTime(SystemTime.currentTimeMillis());
    state.clearTestRequestCounter();
    fromCallback(msgType, msg, sessionID);
    return true;
}

private boolean isPossibleDuplicate(Message message)
    throws FieldNotFound
{
    Message.Header header = message.getHeader();
    return header.isSetField(43) && header.getBoolean(43);
}

private boolean validatePossDup(Message msg)
    throws FieldNotFound, IOException
{
    Message.Header header = msg.getHeader();
    String msgType = header.getString(35);
    Date sendingTime = header.getUtcTimeStamp(52);
    if(!msgType.equals("4"))
    {
        if(!header.isSetField(122))
        {
            generateReject(msg, 1, 122);
            return false;
        }
        Date origSendingTime = header.getUtcTimeStamp(122);
        if(origSendingTime.compareTo(sendingTime) > 0)
        {
            generateReject(msg, 10, 0);
            generateLogout();
            return false;
        }
    }
    return true;
}

For my sanity, I hope you have found a way around it!

Thanks and Regards,
Umair RAHMAN