diff --git a/pom.xml b/pom.xml index 981f6b3ca0..e5f578a5e6 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.quickfixj quickfixj-parent - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT pom QuickFIX/J Parent diff --git a/quickfixj-all/pom.xml b/quickfixj-all/pom.xml index 6ac9115c1b..2347ca65a1 100644 --- a/quickfixj-all/pom.xml +++ b/quickfixj-all/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-parent - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-all diff --git a/quickfixj-codegenerator/pom.xml b/quickfixj-codegenerator/pom.xml index cec7dc9783..07938f2786 100644 --- a/quickfixj-codegenerator/pom.xml +++ b/quickfixj-codegenerator/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-parent - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-codegenerator diff --git a/quickfixj-core/pom.xml b/quickfixj-core/pom.xml index 23dc556da7..65a58df01f 100644 --- a/quickfixj-core/pom.xml +++ b/quickfixj-core/pom.xml @@ -3,7 +3,7 @@ org.quickfixj quickfixj-parent - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-core diff --git a/quickfixj-core/src/main/java/quickfix/FieldMap.java b/quickfixj-core/src/main/java/quickfix/FieldMap.java index f7edfe4081..5a80be2160 100644 --- a/quickfixj-core/src/main/java/quickfix/FieldMap.java +++ b/quickfixj-core/src/main/java/quickfix/FieldMap.java @@ -37,13 +37,8 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.TreeMap; /** * Field container used by messages, groups, and composites. @@ -232,6 +227,15 @@ public String getString(int field) throws FieldNotFound { return getField(field).getObject(); } + public Optional getOptionalString(int field) { + final StringField f = (StringField) fields.get(field); + if (f == null) { + return Optional.empty(); + } else { + return Optional.of(f.getValue()); + } + } + public boolean getBoolean(int field) throws FieldNotFound { try { return BooleanConverter.convert(getString(field)); diff --git a/quickfixj-core/src/main/java/quickfix/Message.java b/quickfixj-core/src/main/java/quickfix/Message.java index ae33a80dec..e3405f78b4 100644 --- a/quickfixj-core/src/main/java/quickfix/Message.java +++ b/quickfixj-core/src/main/java/quickfix/Message.java @@ -33,6 +33,8 @@ import org.w3c.dom.CDATASection; import org.w3c.dom.Document; import org.w3c.dom.Element; + +import quickfix.field.ApplExtID; import quickfix.field.ApplVerID; import quickfix.field.BeginString; import quickfix.field.BodyLength; @@ -720,6 +722,7 @@ static boolean isHeaderField(int field) { case OnBehalfOfSendingTime.FIELD: case ApplVerID.FIELD: case CstmApplVerID.FIELD: + case ApplExtID.FIELD: case NoHops.FIELD: return true; default: diff --git a/quickfixj-core/src/main/java/quickfix/Session.java b/quickfixj-core/src/main/java/quickfix/Session.java index dbfd9235bd..63392d6c4c 100644 --- a/quickfixj-core/src/main/java/quickfix/Session.java +++ b/quickfixj-core/src/main/java/quickfix/Session.java @@ -1073,7 +1073,10 @@ ignore the message and let the problem correct itself (optimistic approach). generateLogout(e.getMessage()); } } - state.incrNextTargetMsgSeqNum(); + // Only increment seqnum if we are at the expected seqnum + if (getExpectedTargetNum() == header.getInt(MsgSeqNum.FIELD)) { + state.incrNextTargetMsgSeqNum(); + } disconnect("Logon rejected: " + e, true); } catch (final UnsupportedMessageType e) { if (logErrorAndDisconnectIfRequired(e, message)) { diff --git a/quickfixj-core/src/test/java/quickfix/FieldMapTest.java b/quickfixj-core/src/test/java/quickfix/FieldMapTest.java index 8e40d5e493..c03f2cf7d3 100644 --- a/quickfixj-core/src/test/java/quickfix/FieldMapTest.java +++ b/quickfixj-core/src/test/java/quickfix/FieldMapTest.java @@ -11,6 +11,7 @@ import quickfix.field.converter.UtcTimeOnlyConverter; import java.util.Iterator; +import java.util.Optional; /** * Tests the {@link FieldMap} class. @@ -91,6 +92,16 @@ public void testOrdering() { testOrdering(new int[] { 3, 2, 1 }, new int[] { 3, 1 }, new int[] { 3, 1, 2 }); } + public void testOptionalString() { + FieldMap map = new Message(); + map.setField(new StringField(128, "bigbank")); + Optional optValue = map.getOptionalString(128); + assertTrue(optValue.isPresent()); + assertEquals("bigbank", optValue.get()); + assertFalse(map.getOptionalString(129).isPresent()); + } + + private long epochMilliOfLocalDate(LocalDateTime localDateTime) { return localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(); } diff --git a/quickfixj-core/src/test/java/quickfix/MessageTest.java b/quickfixj-core/src/test/java/quickfix/MessageTest.java index c8b22d45eb..ecbbbc90bd 100644 --- a/quickfixj-core/src/test/java/quickfix/MessageTest.java +++ b/quickfixj-core/src/test/java/quickfix/MessageTest.java @@ -24,6 +24,7 @@ import quickfix.field.Account; import quickfix.field.AllocAccount; import quickfix.field.AllocShares; +import quickfix.field.ApplExtID; import quickfix.field.ApplVerID; import quickfix.field.AvgPx; import quickfix.field.BeginString; @@ -588,6 +589,11 @@ public void testFix5HeaderFields() { assertTrue(Message.isHeaderField(CstmApplVerID.FIELD)); } + @Test + public void testApplExtIDIsHeaderField() { + assertTrue(Message.isHeaderField(ApplExtID.FIELD)); + } + @Test public void testCalculateStringWithNestedGroups() throws Exception { final NewOrderCross noc = new NewOrderCross(); diff --git a/quickfixj-core/src/test/java/quickfix/SessionTest.java b/quickfixj-core/src/test/java/quickfix/SessionTest.java index 56e3763437..a6e6fe5c6d 100644 --- a/quickfixj-core/src/test/java/quickfix/SessionTest.java +++ b/quickfixj-core/src/test/java/quickfix/SessionTest.java @@ -2336,6 +2336,68 @@ private void testLargeQueue(int N) throws Exception { */ } + @Test + public void testResendSeqWithReject() throws Exception { + final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); + final boolean resetOnLogon = false; + final boolean validateSequenceNumbers = true; + boolean enableNextExpectedMsgSeqNum = false; + boolean isInitiator = false; + + UnitTestApplication app = new UnitTestApplication() { + private int logonCount = 0; + + @Override + public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound, + IncorrectDataFormat, IncorrectTagValue, RejectLogon { + super.fromAdmin(message, sessionId); + if (message.getHeader().getString(MsgType.FIELD).equals(Logon.MSGTYPE)) { + logonCount += 1; + } + if (logonCount == 2) { + throw new RejectLogon("RejectLogon"); + } + } + }; + + Session session = new Session(app, new MemoryStoreFactory(), + sessionID, null, null, null, + new DefaultMessageFactory(), isInitiator ? 30 : 0, false, 30, UtcTimestampPrecision.MILLIS, resetOnLogon, + false, false, false, false, false, true, false, 1.5, null, validateSequenceNumbers, + new int[]{5}, false, false, false, true, false, true, false, null, true, 0, + enableNextExpectedMsgSeqNum, false); + UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + + logonTo(session, 1); + //Do Something + session.next(createAppMessage(2)); + session.next(createAppMessage(3)); + session.disconnect("Disconnecting", true); + session.next(); + session.logon(); + + //Logon + session.setResponder(responder); + logonTo(session, 105); + //Rejected + assertEquals(Logout.MSGTYPE, app.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); + assertEquals("RejectLogon", app.lastToAdminMessage().getString(Text.FIELD)); + + //Logon + session.setResponder(responder); + logonTo(session, 106); + //Accepted + assertEquals(Logon.MSGTYPE, app.lastFromAdminMessage().getHeader().getString(MsgType.FIELD)); + + session.next(); + session.next(); + //ResendRequest + assertEquals(ResendRequest.MSGTYPE, app.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); + assertEquals(4, app.lastToAdminMessage().getInt(BeginSeqNo.FIELD)); + assertEquals(0, app.lastToAdminMessage().getInt(EndSeqNo.FIELD)); + } + private News createPossDupAppMessage(int sequence) { // create a regular app message and and add the PossDup // and OrigSendingTime tags to it diff --git a/quickfixj-dictgenerator/pom.xml b/quickfixj-dictgenerator/pom.xml index 58a7fa22f0..42c980f7ba 100644 --- a/quickfixj-dictgenerator/pom.xml +++ b/quickfixj-dictgenerator/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-parent - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-dictgenerator diff --git a/quickfixj-distribution/pom.xml b/quickfixj-distribution/pom.xml index 51aeca5f68..2e9d3b001e 100644 --- a/quickfixj-distribution/pom.xml +++ b/quickfixj-distribution/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-parent - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-distribution diff --git a/quickfixj-examples/banzai/pom.xml b/quickfixj-examples/banzai/pom.xml index 3d92bf36bc..d435cb47fe 100644 --- a/quickfixj-examples/banzai/pom.xml +++ b/quickfixj-examples/banzai/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-examples - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-examples-banzai diff --git a/quickfixj-examples/executor/pom.xml b/quickfixj-examples/executor/pom.xml index ef76ed39aa..57f834a358 100644 --- a/quickfixj-examples/executor/pom.xml +++ b/quickfixj-examples/executor/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-examples - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-examples-executor diff --git a/quickfixj-examples/ordermatch/pom.xml b/quickfixj-examples/ordermatch/pom.xml index c6dd458e64..2397b3582b 100644 --- a/quickfixj-examples/ordermatch/pom.xml +++ b/quickfixj-examples/ordermatch/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-examples - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-examples-ordermatch diff --git a/quickfixj-examples/pom.xml b/quickfixj-examples/pom.xml index 6fd9c80993..e0b4f843cf 100644 --- a/quickfixj-examples/pom.xml +++ b/quickfixj-examples/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-parent - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-examples diff --git a/quickfixj-messages/pom.xml b/quickfixj-messages/pom.xml index 76b7b630fa..779579c908 100644 --- a/quickfixj-messages/pom.xml +++ b/quickfixj-messages/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-parent - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages diff --git a/quickfixj-messages/quickfixj-messages-all/pom.xml b/quickfixj-messages/quickfixj-messages-all/pom.xml index 7154da1351..574a1b8c69 100644 --- a/quickfixj-messages/quickfixj-messages-all/pom.xml +++ b/quickfixj-messages/quickfixj-messages-all/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-all diff --git a/quickfixj-messages/quickfixj-messages-fix40/pom.xml b/quickfixj-messages/quickfixj-messages-fix40/pom.xml index 8a6bdd354a..757c287177 100644 --- a/quickfixj-messages/quickfixj-messages-fix40/pom.xml +++ b/quickfixj-messages/quickfixj-messages-fix40/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-fix40 diff --git a/quickfixj-messages/quickfixj-messages-fix41/pom.xml b/quickfixj-messages/quickfixj-messages-fix41/pom.xml index 3ed73eeba3..e4e729e220 100644 --- a/quickfixj-messages/quickfixj-messages-fix41/pom.xml +++ b/quickfixj-messages/quickfixj-messages-fix41/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-fix41 diff --git a/quickfixj-messages/quickfixj-messages-fix42/pom.xml b/quickfixj-messages/quickfixj-messages-fix42/pom.xml index 909da5fe73..16ea74a562 100644 --- a/quickfixj-messages/quickfixj-messages-fix42/pom.xml +++ b/quickfixj-messages/quickfixj-messages-fix42/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-fix42 diff --git a/quickfixj-messages/quickfixj-messages-fix43/pom.xml b/quickfixj-messages/quickfixj-messages-fix43/pom.xml index a83d24a717..342fd0f673 100644 --- a/quickfixj-messages/quickfixj-messages-fix43/pom.xml +++ b/quickfixj-messages/quickfixj-messages-fix43/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-fix43 diff --git a/quickfixj-messages/quickfixj-messages-fix44/pom.xml b/quickfixj-messages/quickfixj-messages-fix44/pom.xml index 999cd62ea2..4f3d740ed8 100644 --- a/quickfixj-messages/quickfixj-messages-fix44/pom.xml +++ b/quickfixj-messages/quickfixj-messages-fix44/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-fix44 diff --git a/quickfixj-messages/quickfixj-messages-fix50/pom.xml b/quickfixj-messages/quickfixj-messages-fix50/pom.xml index 711a007e26..80e006b579 100644 --- a/quickfixj-messages/quickfixj-messages-fix50/pom.xml +++ b/quickfixj-messages/quickfixj-messages-fix50/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-fix50 diff --git a/quickfixj-messages/quickfixj-messages-fix50sp1/pom.xml b/quickfixj-messages/quickfixj-messages-fix50sp1/pom.xml index ff24ab88db..c94e97f794 100644 --- a/quickfixj-messages/quickfixj-messages-fix50sp1/pom.xml +++ b/quickfixj-messages/quickfixj-messages-fix50sp1/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-fix50sp1 diff --git a/quickfixj-messages/quickfixj-messages-fix50sp2/pom.xml b/quickfixj-messages/quickfixj-messages-fix50sp2/pom.xml index 29c113eb54..49bc2c9471 100644 --- a/quickfixj-messages/quickfixj-messages-fix50sp2/pom.xml +++ b/quickfixj-messages/quickfixj-messages-fix50sp2/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-fix50sp2 diff --git a/quickfixj-messages/quickfixj-messages-fixt11/pom.xml b/quickfixj-messages/quickfixj-messages-fixt11/pom.xml index 51f46292af..c959b475c7 100644 --- a/quickfixj-messages/quickfixj-messages-fixt11/pom.xml +++ b/quickfixj-messages/quickfixj-messages-fixt11/pom.xml @@ -4,7 +4,7 @@ org.quickfixj quickfixj-messages - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT quickfixj-messages-fixt11