[QFJ-930] FIXSettings not set for new DataDictionary objects created by DefaultDataDictionaryProvider Created: 18/Jul/17 Updated: 29/Jan/18 |
|
Status: | Open |
Project: | QuickFIX/J |
Component/s: | Engine |
Affects Version/s: | 1.6.3 |
Fix Version/s: | None |
Type: | Bug | Priority: | Default |
Reporter: | Sachin Agrawal | Assignee: | Unassigned |
Resolution: | Unresolved | Votes: | 0 |
Labels: | None |
Attachments: | quickfix_930.rar |
Description |
While DefaultSessionsFactory.processFixtDataDictionaries adds ApplicationDictionary to dataDictionaryProvider it uses beginStringQualifier only. While method of MessageUtils method used session,messageString both to get the ApplVerId. this results in mismatched key inside DefaultDataDictionaryProvider and DefaultDataDictionaryPovider need to create a new DataDictionary but FIX sesion settings are not set here at all, which are set by DefaultSessionsFactory while executing processFixtDataDictionaries inside createDataDictionary. Please let me know in case this is intentional. |
Comments |
Comment by Christoph John [ 18/Jul/17 ] |
I am sorry, but I cannot follow your description. Could you maybe describe the problem with some code examples or a unit test? |
Comment by Sachin Agrawal [ 19/Jul/17 ] |
Thanks Chris for looking into,i now try to be more specific. Please look into DeafultSessionFactory.processFixtDataDictionaries, we find following piece of code, please note here that toApplVerID is used to create the instance of ApplVerID before the applicationDictionary is added to the datadictionaryProvider.
final DataDictionary dd = createDataDictionary(sessionID, settings, key,
beginStringQualifier);
dataDictionaryProvider.addApplicationDictionary(MessageUtils.toApplVerID(beginStringQualifier), dd);
and createDataDictionary method reads the settings private DataDictionary createDataDictionary(SessionID sessionID, SessionSettings settings, String settingsKey, String beginString) throws ConfigError, FieldConvertError { final String path = getDictionaryPath(sessionID, settings, settingsKey, beginString); final DataDictionary dataDictionary = getDataDictionary(path); if (settings.isSetting(sessionID, Session.SETTING_VALIDATE_FIELDS_OUT_OF_ORDER)) { dataDictionary.setCheckFieldsOutOfOrder(settings.getBool(sessionID, Session.SETTING_VALIDATE_FIELDS_OUT_OF_ORDER)); } if (settings.isSetting(sessionID, Session.SETTING_VALIDATE_FIELDS_HAVE_VALUES)) { dataDictionary.setCheckFieldsHaveValues(settings.getBool(sessionID, Session.SETTING_VALIDATE_FIELDS_HAVE_VALUES)); } if (settings.isSetting(sessionID, Session.SETTING_VALIDATE_UNORDERED_GROUP_FIELDS)) { boolean chkUnorderedGrpFields = settings.getBool(sessionID, Session.SETTING_VALIDATE_UNORDERED_GROUP_FIELDS); settings.getLogger().error("Msg SttString "+Session.SETTING_VALIDATE_UNORDERED_GROUP_FIELDS +" value "+ chkUnorderedGrpFields +" dataDictionary " +dataDictionary.toString() +" beginString "+beginString); dataDictionary.setCheckUnorderedGroupFields(chkUnorderedGrpFields); } if (settings.isSetting(sessionID, Session.SETTING_VALIDATE_USER_DEFINED_FIELDS)) { dataDictionary.setCheckUserDefinedFields(settings.getBool(sessionID, Session.SETTING_VALIDATE_USER_DEFINED_FIELDS)); } if (settings.isSetting(sessionID, Session.SETTING_ALLOW_UNKNOWN_MSG_FIELDS)) { dataDictionary.setAllowUnknownMessageFields(settings.getBool(sessionID, Session.SETTING_ALLOW_UNKNOWN_MSG_FIELDS)); } return dataDictionary; } Please note that DefaultDataDictionaryProvider uses ApplVerID as the key of the map. While there is a method called MessageUtils.parse(Session session, String messageString), which uses getApplVerID(session, messageString) to create the ApplVerId and uses the same to fetch the applicationDictionary from dataDictionaryProvider. MessageUtils.parse(Session session, String messageString) ..... final String beginString = getStringField(messageString, BeginString.FIELD); final String msgType = getMessageType(messageString); ApplVerID applVerID; if (FixVersions.BEGINSTRING_FIXT11.equals(beginString)) { applVerID = getApplVerID(session, messageString); } else { applVerID = toApplVerID(beginString); } final MessageFactory messageFactory = session.getMessageFactory(); final DataDictionaryProvider ddProvider = session.getDataDictionaryProvider(); final DataDictionary sessionDataDictionary = ddProvider == null ? null : ddProvider.getSessionDataDictionary(beginString); final DataDictionary applicationDataDictionary = ddProvider == null ? null : ddProvider.getApplicationDataDictionary(applVerID); .... So when an application message is received a new DataDictionary is created by DefaultDataDictionaryProvider, look at method public DataDictionary getApplicationDataDictionary(ApplVerID applVerID)
so the problem is that this new DataDictionary created by DefaultdataDictionaryProvider does not copy the FIX configurations i.e. settings. Hence even though the application dev has set the settings they are not picked while parsing messages. Please ask further clarifications. Thanks, |
Comment by Christoph John [ 19/Jul/17 ] |
Hi, I have changed https://github.com/quickfix-j/quickfixj/blob/master/quickfixj-core/src/test/java/quickfix/DefaultSessionFactoryTest.java (method testFixtDataDictionaryConfiguration) slightly to set "AllowUnknownMessageFields" to true. @Test public void testFixtDataDictionaryConfiguration() throws Exception { SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIXT11, "SENDER", "TARGET"); setUpDefaultSettings(sessionID); settings.setBool(sessionID, Session.SETTING_USE_DATA_DICTIONARY, true); settings.setString(sessionID, Session.SETTING_TRANSPORT_DATA_DICTIONARY, "FIXT11.xml"); settings.setString(sessionID, Session.SETTING_DEFAULT_APPL_VER_ID, "FIX.4.2"); settings.setString(sessionID, Session.SETTING_APP_DATA_DICTIONARY, "FIX42.xml"); settings.setString(sessionID, Session.SETTING_APP_DATA_DICTIONARY + "." + FixVersions.BEGINSTRING_FIX40, "FIX40.xml"); settings.setString(sessionID, Session.SETTING_ALLOW_UNKNOWN_MSG_FIELDS, "Y"); // added Session session = factory.create(sessionID, settings); DataDictionaryProvider provider = session.getDataDictionaryProvider(); assertThat(provider.getSessionDataDictionary(sessionID.getBeginString()), is(notNullValue())); final DataDictionary applicationDataDictionary = provider.getApplicationDataDictionary(new ApplVerID(ApplVerID.FIX42)); assertThat(applicationDataDictionary, is(notNullValue())); assertThat(provider.getApplicationDataDictionary(new ApplVerID(ApplVerID.FIX40)), is(notNullValue())); System.err.println("XXXX " + provider.getSessionDataDictionary(sessionID.getBeginString()).isAllowUnknownMessageFields() ); System.err.println("XXXX " + applicationDataDictionary.isAllowUnknownMessageFields() ); quickfix.fixt11.Logon logon = new quickfix.fixt11.Logon(new EncryptMethod(EncryptMethod.NONE_OTHER), new HeartBtInt(30), new DefaultApplVerID(ApplVerID.FIX42)); MessageUtils.parse(session, logon.toString()); This gives the following as output: XXXX true XXXX true So the setting is picked up by both dictionaries. Then I stepped into MessageUtils.parse(session, logon.toString()) with the debugger and could also see that the setting is true on the applicationDataDictionary. So maybe I am taking a different code path than you? BTW I tested it on master, i.e. with version 1.7.0-SNAPSHOT. Cheers, |
Comment by Sachin Agrawal [ 20/Jul/17 ] |
Hi Chris, I understand in your use case a new dictionary is never created, but there are some configurations in which a scenario occurs which creates a new dictionary by DefaultDataDictionaryProvider, then the settings will not be copied. 1) I correct the Fix configurations so that a new dictionary is never created. I see you are suggesting option 1. --Regards, |
Comment by Christoph John [ 20/Jul/17 ] |
Hi, when there are such configurations then please give an example configuration. Otherwise I don't know how to reproduce the problem. Thanks, |
Comment by Sachin Agrawal [ 29/Jan/18 ] |
Attached is the zip src files with change Add fix for correctly reading the settings in all the cases, i.e. whenever DataDictionary object is created from SessionFactory or MessageUtils.parse |
Comment by Sachin Agrawal [ 29/Jan/18 ] |
only improvement the changes i uploaded have is that whereever the DataDictionary object is created, the existing settings of current session are always applied on DataDictionary created. |
Comment by Christoph John [ 29/Jan/18 ] |
Thanks for the file. Are you maybe able to generate a patch or even better open a pull request on github? |