3

When I logon, I'm sending a application message request (BW) and server responding with multiple type of messages, but for the Security Status one, it returns Halt Reason Exception. I have 2 onMessage function, these for Security Definition Report and Security Definition Update Report. Security Status does not have onMessage function because I am not using this message so I do not expect to handle other type of messages. When a security status message received, we are getting HaltReason exception. And after all this, our client can't receive any heartbeat from server, so our client is disconnecting and sending another login request. It causes a loop which we get messages, disconnect with Halt reason exception and request again. We are using FIX50SP2 with FIXT1.1 but MessageCracker maps these messages to FIX50. Also We use quickfix 2.3.1 version and DefaultMessageFactory for receiving FIX messages.

Example:

event> (Received logon)

incoming> (8=FIXT.1.1 9=00000 35=f 49=foo 56=foo 34=0000 57=0000 52=20220302-10:11:09.908 1180=R 1181=0000 1350=0000 55=foo 48=0000 22=M 336=135 325=N 60=20220302-10:11:09.908 10=119)

error> (java.lang.VerifyError: Bad type on operand stack Exception Details: Location: quickfix/fix50/SecurityStatus.get(Lquickfix/field/HaltReason;)Lquickfix/field/HaltReason; @2: invokevirtual Reason: Type 'quickfix/field/HaltReason' (current frame, stack[1]) is not assignable to 'quickfix/IntField' Current Frame: bci: @2 flags: { } locals: { 'quickfix/fix50/SecurityStatus', 'quickfix/field/HaltReason' } stack: { 'quickfix/fix50/SecurityStatus', 'quickfix/field/HaltReason' } Bytecode: 0x0000000: 2a2b b600 2457 2bb0

java.lang.VerifyError: Bad type on operand stack Exception Details: Location: quickfix/fix50/SecurityStatus.get(Lquickfix/field/HaltReason;)Lquickfix/field/HaltReason; @2: invokevirtual Reason: Type 'quickfix/field/HaltReason' (current frame, stack[1]) is not assignable to 'quickfix/IntField' Current Frame: bci: @2 flags: { } locals: { 'quickfix/fix50/SecurityStatus', 'quickfix/field/HaltReason' } stack: { 'quickfix/fix50/SecurityStatus', 'quickfix/field/HaltReason' } Bytecode: 0x0000000: 2a2b b600 2457 2bb0

at quickfix.fix50.MessageFactory.create(MessageFactory.java:120)
at quickfix.DefaultMessageFactory.create(DefaultMessageFactory.java:141)
at quickfix.MessageUtils.parse(MessageUtils.java:145)
at quickfix.mina.AbstractIoHandler.messageReceived(AbstractIoHandler.java:131)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.messageReceived(DefaultIoFilterChain.java:858)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:542)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:48)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:947)
at org.apache.mina.filter.codec.ProtocolCodecFilter$ProtocolDecoderOutputImpl.flush(ProtocolCodecFilter.java:398)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:234)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:542)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:48)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:947)
at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFilterAdapter.java:109)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:542)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageReceived(DefaultIoFilterChain.java:535)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:703)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:659)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:648)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$600(AbstractPollingIoProcessor.java:68)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:1120)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

)

pom.xml :

<dependency>
            <groupId>org.quickfixj</groupId>
            <artifactId>quickfixj-core</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.quickfixj</groupId>
            <artifactId>quickfixj-messages-fix40</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.quickfixj</groupId>
            <artifactId>quickfixj-messages-fix41</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.quickfixj</groupId>
            <artifactId>quickfixj-messages-fix42</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.quickfixj</groupId>
            <artifactId>quickfixj-messages-fix43</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.quickfixj</groupId>
            <artifactId>quickfixj-messages-fix44</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.quickfixj</groupId>
            <artifactId>quickfixj-messages-fix50</artifactId>
            <version>2.3.1</version>
        </dependency>

FIXApplication50.java:

import org.apache.log4j.Logger;
import quickfix.Message;
import quickfix.MessageCracker;
import quickfix.*;
import quickfix.field.*;
import quickfix.fix50.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class FIXApplication50 extends MessageCracker implements Application {

    public FIXApplication50() throws ConfigError {
    }

    public void onMessage(SecurityDefinition refData, SessionID sessionID) {
        
    }

    public void onMessage(SecurityDefinitionUpdateReport refData, SessionID sessionID) {

    }

    public void onCreate(SessionID sessionID) {

    }

    public void sendApplicationMessageRequest(Message message, SessionID sessionID) {

    }

    public void onLogon(SessionID sessionID) {
        Message message = new Message();

        sendApplicationMessageRequest(message, sessionID);
    }

    public void onLogout(SessionID sessionID) {

    }


    public void toAdmin(Message message, SessionID sessionID) {
      
    }


    public void fromAdmin(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon {

    }


    public void toApp(Message message, SessionID sessionID) throws DoNotSend {

    }

    public void fromApp(Message message, SessionID sessionId)
            throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
        crack(message, sessionId);
    }
}

session.properties :

[DEFAULT]
ConnectionType=initiator
ReconnectInterval=60
ResetOnLogon=Y
FileLogPath=logs/plugins/foo/Client_Logs
SenderCompID=foo
SenderSubID=foo
ValidateIncomingMessage=N

[SESSION]
BeginString=FIXT.1.1
TargetCompID=foo
StartDay=sunday
EndDay=friday
StartTime=21:35:00
EndTime=21:30:00
HeartBtInt=30
CheckLatency=N
SocketConnectPort=0000
SocketConnectHost=00.00.00
DefaultApplVerID=FIX.5.0SP2
TransportDataDictionary=config/plugins/foo/FIXT11.xml
AppDataDictionary=config/plugins/foo/RefDataFIX50sp2.xml
  • There was a similar question some days ago. Why do you use different versions on your QuickFIX/J dependencies? Probably HaltReason changed its type between FIX5.0 and FIX5.0SP2. – Christoph John Mar 03 '22 at 22:15
  • Does it related with other fix versions?(FIX42, FIX44...) When i use dependency for FIX50SP2 all messages are rejected, it doesn't even pass to the on message function. @ChristophJohn – Başak Gören Mar 04 '22 at 07:26
  • You probably need to use fix50sp2 classes in your message cracker. – Christoph John Mar 04 '22 at 13:01
  • I extend quickfixj core's message cracker in my FIXApplication50. If you mean onMessage classes on the same class, fix engine rejects all messages when i changed onMessage to FIX50SP2. Could you give a further explanation? @ChristophJohn – Başak Gören Mar 04 '22 at 13:33
  • What is `HaltReason`'s value (tag 327) in the message that you are receiving? – Grant Birchmeier Mar 04 '22 at 15:35
  • @OP Maybe your message factory still produces fix50 message objects instead of fix50sp2 objects? – Christoph John Mar 05 '22 at 22:31
  • Yes, but I don't know what could be the reason or how to solve it. @ChristophJohn – Başak Gören Mar 07 '22 at 07:30
  • The weird thing is there is no HaltReason (tag 327) field in the message we are receiving @GrantBirchmeier – Başak Gören Mar 07 '22 at 11:33
  • @Başakgören what do you mean? You should have implemented (or used or overriden) a `MessageFactory` somewhere in your code. Make sure that the factory produces fix50sp2 messages. – Christoph John Mar 07 '22 at 16:49
  • @ChristophJohn I am using DefaultMessageFactory that implements MessageFactory. – Başak Gören Mar 08 '22 at 10:09
  • You can see in your stack trace that `quickfix.fix50.MessageFactory` is used. This is probably caused by your mix of quickfixj versions in your dependencies. Because since QFJ 2.1.0 it should use `fix50sp2.MessageFactory` by default. See here: https://github.com/quickfix-j/quickfixj/blob/2f4fda1f0dbcfd1185cf01533b0a614e00808478/quickfixj-core/src/main/java/quickfix/DefaultMessageFactory.java#L58 – Christoph John Mar 09 '22 at 09:14
  • @ChristophJohn I deleted other fix dependencies and keep just quickfixj-messages-fix50sp2 v2.3.1 & quickfixj-core v2.3.1. I just use two onMessage functions for SecurityDefinition and SecurityDefinitionUpdateReport. However all messages rejected by our client with an Unsupported Message request With quickfixJ v2.3.1 and DefaultMessageFactory. Sample fix message : 8=FIXT.1.19=00035=j34=0000=foo50=foo52=20220311-12:40:40.16856=fooT45=580658=Unsupported Message Type372=d380=310=084 – Başak Gören Mar 11 '22 at 12:56
  • Is your `FIXApplication50.java` still implemented as in your original question? If yes, try to use full qualified class names as first parameter in the `onMessage` methods. Example: https://github.com/quickfix-j/quickfixj/blob/master/quickfixj-core/src/test/java/quickfix/test/acceptance/ATMessageCracker.java Basically the reason for the message rejection is that a handler method for a given message could not be found. – Christoph John Mar 11 '22 at 15:58
  • Yes, implemented. I changed onMessage's first parameters as full qualified class names. "public void onMessage(quickfix.fix50sp2.SecurityDefinition refData, SessionID sessionID)". But still taking unsupported message type for all messages. @ChristophJohn – Başak Gören Mar 14 '22 at 09:09
  • As said the problem is most likely the message factory. What happens if you add an onMessage method with a general quickfix.Message as parameter? – Christoph John Mar 14 '22 at 13:10
  • All messages were dropped to onMessage when I was using like this; public void onMessage(Message message, SessionID) @ChristophJohn – Başak Gören Mar 16 '22 at 10:46
  • So does this mean it is solved or what do you mean by "dropped"? – Christoph John Mar 16 '22 at 19:16
  • No, it's not solved, that way I'll have to handle all my messages myself, which is the message cracker's job. @ChristophJohn – Başak Gören Mar 17 '22 at 09:04
  • Well that only proves what I stated in my last comments. The factory does not seem to produce fix50sp2 messages. I think I cannot help you any further than that – Christoph John Mar 17 '22 at 11:25

2 Answers2

1

I'm not sure precisely what is causing your exception, but I do see some issues that you should address:

  1. Config issues:

    Looks like you are using FIX50SP2, so you need:

    • UseDataDictionary=Y
    • AppDataDictionary=<path/to/your/FIX50SP2.xml>
    • TransportDataDictionary=<path/to/your/FIXT11.xml>

    (In asker's initial edit, these fields were not present)

    And I don't think you want ValidateIncomingMessage=N. This setting always tells me that someone doesn't know what they're doing! If your connection is using repeating groups (and I've never seen one that doesn't), you must have a correct DD. If your DD is correct, then validation is nothing to worry about.

    Also, do you really need CheckLatency=N?

  2. You probably do need a SecurityStatus handler

    Security Status does not have onMessage function because I am not using this message so I do not expect to handle other type of messages.

    If you do not provide an onMessage(SecurityStatus) handler, then your app will respond to those messages with 35=j rejections. If you truly want to ignore this message, then you should add this handler with an empty implementation.

Grant Birchmeier
  • 17,809
  • 11
  • 63
  • 98
  • UseDataDictionary=Y ,AppDataDictionary=,TransportDataDictionary= already exists in session.prop. I did not put this field in the example session.properties. My DD is correct. And Even if I put onMessage function, Halt reason exception is occuring in crack(message, sessionId) line inside fromApp function before onMessage. Moreover, how are these ValidateIncomingMessage=N and CheckLatency=N config related with the issue? – Başak Gören Mar 04 '22 at 07:45
  • While these suggestions are valid issues that I see in what you posted, I guess they were not related to your issue. – Grant Birchmeier Mar 04 '22 at 15:36
0

You need to read it as a custom tag as follows - (tested):

          try {
              
                    response.setHaltReason(report.getString(327));
            
            } catch (Exception e) {
                log.error...
            }

where report is quickfix.fix44.SecurityStatus

user666
  • 1,750
  • 3
  • 18
  • 34