[QFJ-964] SessionSettings gets cleared intermittently Created: 21/Nov/18  Updated: 11/Jan/19  Resolved: 24/Nov/18

Status: Closed
Project: QuickFIX/J
Component/s: Engine
Affects Version/s: 2.0.0, 2.1.0
Fix Version/s: 2.1.1

Type: Bug Priority: Default
Reporter: Alex Wibowo Assignee: Alex Wibowo
Resolution: Fixed Votes: 0
Labels: None


 Description   

We have been using DynamicAcceptorSessionProvider in our project for quite sometime now, together with ThreadedSocketAcceptor.
After a recent upgrade to Quickfix 2.1.0 (from 1.5.3), we saw some errors that I believe is caused by Quickfix being unable to find the session settings.
The stack trace looks like below:


2018-11-19 00:01:13,236|| ERROR |||| org.quickfixj.QFJException: quickfix.ConfigError: Missing ConnectionType | NioProcessor-23 | q.m.a.AcceptorIoHandler
org.quickfixj.QFJException: quickfix.ConfigError: Missing ConnectionType
at quickfix.mina.acceptor.DynamicAcceptorSessionProvider.getSession(DynamicAcceptorSessionProvider.java:153) ~[quickfixj-core-2.1.0.jar:2.1.0]
at quickfix.mina.acceptor.AcceptorIoHandler.findQFSession(AcceptorIoHandler.java:118) ~[quickfixj-core-2.1.0.jar:2.1.0]
at quickfix.mina.AbstractIoHandler.messageReceived(AbstractIoHandler.java:129) ~[quickfixj-core-2.1.0.jar:2.1.0]
at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.messageReceived(DefaultIoFilterChain.java:997) ~[mina-core-2.0.19.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:641) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:48) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1114) [mina-core-2.0.19.jar:?]
at org.apache.mina.filter.codec.ProtocolCodecFilter$ProtocolDecoderOutputImpl.flush(ProtocolCodecFilter.java:437) [mina-core-2.0.19.jar:?]
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:256) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:641) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:48) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1114) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFilterAdapter.java:121) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:641) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageReceived(DefaultIoFilterChain.java:634) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:539) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$1200(AbstractPollingIoProcessor.java:68) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1242) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1231) [mina-core-2.0.19.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:683) [mina-core-2.0.19.jar:?]
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64) [mina-core-2.0.19.jar:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0-zing_18.06.0.0]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0-zing_18.06.0.0]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0-zing_18.06.0.0]
Caused by: quickfix.ConfigError: Missing ConnectionType
at quickfix.DefaultSessionFactory.create(DefaultSessionFactory.java:102) ~[quickfixj-core-2.1.0.jar:2.1.0]

I find this very strange, as we definitely have the session configuration, and the session configuration specifies the 'ConnectionType' (which is an 'acceptor').



 Comments   
Comment by Alex Wibowo [ 21/Nov/18 ]

Here is another variant of the failure. But I think the underlying cause is the same:

org.quickfixj.QFJException: quickfix.ConfigError: Session not found
          at quickfix.mina.acceptor.DynamicAcceptorSessionProvider.getSession(DynamicAcceptorSessionProvider.java:153) ~[quickfixj-core-2.1.0.jar:2.1.0]
          at quickfix.mina.acceptor.AcceptorIoHandler.findQFSession(AcceptorIoHandler.java:118) ~[quickfixj-core-2.1.0.jar:2.1.0]
          at quickfix.mina.AbstractIoHandler.messageReceived(AbstractIoHandler.java:129) ~[quickfixj-core-2.1.0.jar:2.1.0]
          at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.messageReceived(DefaultIoFilterChain.java:997) ~[mina-core-2.0.19.jar:?]
          at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:641) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:48) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1114) [mina-core-2.0.19.jar:?]
          at org.apache.mina.filter.codec.ProtocolCodecFilter$ProtocolDecoderOutputImpl.flush(ProtocolCodecFilter.java:437) [mina-core-2.0.19.jar:?]
          at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:256) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:641) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:48) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1114) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFilterAdapter.java:121) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:641) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageReceived(DefaultIoFilterChain.java:634) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:539) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$1200(AbstractPollingIoProcessor.java:68) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1242) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1231) [mina-core-2.0.19.jar:?]
          at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:683) [mina-core-2.0.19.jar:?]
          at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64) [mina-core-2.0.19.jar:?]
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_172]
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_172]
          at java.lang.Thread.run(Thread.java:748) [?:1.8.0_172]
Caused by: quickfix.ConfigError: Session not found
          at quickfix.SessionSettings.getSessionProperties(SessionSettings.java:165) ~[quickfixj-core-2.1.0.jar:2.1.0]
          at quickfix.SessionSettings.getSessionProperties(SessionSettings.java:186) ~[quickfixj-core-2.1.0.jar:2.1.0]
          at quickfix.mina.acceptor.DynamicAcceptorSessionProvider.getSession(DynamicAcceptorSessionProvider.java:140) ~[quickfixj-core-2.1.0.jar:2.1.0]
          ... 24 more
Comment by Alex Wibowo [ 21/Nov/18 ]

I probably should also mention how the session settings look like.
Roughly, it is like below (configured in Spring xml):

<bean id="quickfixConfiguration" class="com.foobar.quickfix.QuickfixjConfiguration">
    <property name="defaultSettings">
        <util:map>
            <!-- Custom Properties -->
            <entry key="ResourceName" value="dapi"/>
            <entry key="AsynchronousLogging" value="N"/>
            <entry key="AsynchronousLoggerMaxPoolSize" value="1"/>
            <entry key="AsynchronousLoggerQueueCapacity" value="100"/>
            <entry key="AsynchronousLoggerThreadNamePrefix" value="QuickfixAsynchronousFileLogger-"/>
            <!-- End of custom properties -->

            <entry key="TimeZone" value="UTC"/>
            <entry key="StartDay" value="Sunday"/>
            <entry key="StartTime" value="7:00:00"/>
            <entry key="EndDay" value="Friday"/>
            <entry key="EndTime" value="17:00:00"/>
            <entry key="NonStopSession" value="N"/>
            <entry key="ConnectionType" value="acceptor"/>
            <entry key="HeartBtInt" value="30"/>
            <entry key="UseDataDictionary" value="Y"/>
            <entry key="ThreadModel" value="ThreadPerSession"/>
            <entry key="UseJmx" value="Y"/>
            <entry key="FileStorePath" value="/home/wibowoa/var/lib/myApp"/>
            <entry key="FileLogPath" value="logs/fixlog"/>
            <entry key="FileIncludeTimeStampForMessages" value="Y"/>
            <entry key="FileIncludeMilliseconds" value="Y"/>
            <entry key="CheckLatency" value="Y"/>
            <entry key="BeginString" value="FIX.4.2"/>
            <entry key="AcceptorTemplate" value="Y"/>
            <entry key="TargetCompID" value="*"/>
        </util:map>
    </property>
    <property name="sessionSettings">
        <util:map>
            <entry key="FIX.4.2:FOOBAR_PRICING->*">
                <util:map>
                    <entry key="PersistMessages" value="N"/>
                    <entry key="SocketAcceptPort" value="7565"/>
                    <entry key="DataDictionary" value="fix/FIX42-PRICING-2.4.xml"/>
                    <entry key="ResetOnLogon" value="Y"/>
                    <entry key="MaxLatency" value="120"/>
                </util:map>
            </entry>
            <entry key="FIX.4.2:FOOBAR_TRADING->*">
                <util:map>
                    <entry key="PersistMessages" value="Y"/>
                    <entry key="SocketAcceptPort" value="7566"/>
                    <entry key="DataDictionary" value="fix/FIX42-TRADING-2.4.xml"/>
                    <entry key="ResetOnLogon" value="N"/>
                    <entry key="MaxLatency" value="1"/>
                </util:map>
            </entry>
        </util:map>
    </property>
</bean>

then this gets loaded into SessionSettings:

public final class QuickfixjConfiguration {
    private Map<Object, Object> defaultSettings;
    private Map<SessionID, Map<Object, Object>> sessionSettings;


    public void setDefaultSettings(final Map<Object, Object> defaultSettings) {
        this.defaultSettings = defaultSettings;
    }

    public Map<SessionID, Map<Object, Object>> getSessionSettings() {
        return sessionSettings;
    }

    public void setSessionSettings(final Map<SessionID, Map<Object, Object>> sessionSettings) {
        this.sessionSettings = sessionSettings;
    }

    public SessionSettings createSessionSettings() throws ConfigError {
        final SessionSettings settings = new SessionSettings();
        if(defaultSettings != null && !defaultSettings.isEmpty()) {
            settings.set(new Dictionary(null, defaultSettings));
        }
        if(sessionSettings != null && !sessionSettings.isEmpty()) {
            for (Map.Entry<SessionID, Map<Object, Object>> sessionSetting : sessionSettings.entrySet()) {
                settings.set(sessionSetting.getKey(), new Dictionary("session", sessionSetting.getValue()));
            }
        }
        return settings;
    }

}
...
QuickfixJConfiguration foobar =... (injected as spring)
SessionSettings settings = foobar.createSessionSettings();

  final MessageFactory messageFactory = new DefaultMessageFactory();
        final LogFactory logFactory = ...
        final MessageStoreFactory messageStoreFactory = new CustomFileStoreFactory(settings);
final Acceptor acceptor =  new ThreadedSocketAcceptor(application, messageStoreFactory, settings, logFactory, messageFactory);

  for (final SessionID sessionID : (Iterable<SessionID>)(settings::sectionIterator)) {
                 final int acceptPort = (int) settings.getLong(sessionID, Acceptor.SETTING_SOCKET_ACCEPT_PORT);
                 if (settings.getBool(sessionID, Acceptor.SETTING_ACCEPTOR_TEMPLATE)) {
                                            final AcceptorSessionProvider dynamicAcceptorSessionProvider = new DynamicAcceptorSessionProvider(settings, sessionID, application, messageStoreFactory, logFactory, messageFactory);
                                            acceptor.setSessionProvider(new InetSocketAddress(acceptPort), dynamicAcceptorSessionProvider);
                   }
}

Comment by Alex Wibowo [ 21/Nov/18 ]

PR for this issue is here: https://github.com/quickfix-j/quickfixj/pull/216

Generated at Wed May 08 17:46:05 UTC 2024 using JIRA 7.5.2#75007-sha1:9f5725bb824792b3230a5d8716f0c13e296a3cae.