Skip to content

Commit e72feb1

Browse files
committed
JAVA-2660: Improve error messages for MongoIncompatibleDriverException
1 parent 127887a commit e72feb1

File tree

5 files changed

+154
-57
lines changed

5 files changed

+154
-57
lines changed

driver-core/src/main/com/mongodb/connection/BaseCluster.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545

4646
import static com.mongodb.assertions.Assertions.isTrue;
4747
import static com.mongodb.assertions.Assertions.notNull;
48+
import static com.mongodb.connection.ServerDescription.MAX_DRIVER_WIRE_VERSION;
49+
import static com.mongodb.connection.ServerDescription.MIN_DRIVER_SERVER_VERSION;
50+
import static com.mongodb.connection.ServerDescription.MIN_DRIVER_WIRE_VERSION;
4851
import static com.mongodb.internal.event.EventListenerHelper.createServerListener;
4952
import static com.mongodb.internal.event.EventListenerHelper.getClusterListener;
5053
import static java.lang.String.format;
@@ -131,7 +134,7 @@ public void selectServerAsync(final ServerSelector serverSelector, final SingleR
131134
isTrue("open", !isClosed());
132135

133136
if (LOGGER.isTraceEnabled()) {
134-
LOGGER.trace(String.format("Asynchronously selecting server with selector %s", serverSelector));
137+
LOGGER.trace(format("Asynchronously selecting server with selector %s", serverSelector));
135138
}
136139
ServerSelectionRequest request = new ServerSelectionRequest(serverSelector, getCompositeServerSelector(serverSelector),
137140
getMaxWaitTimeNanos(), callback);
@@ -276,7 +279,7 @@ private boolean handleServerSelectionRequest(final ServerSelectionRequest reques
276279
Server server = selectRandomServer(request.compositeSelector, description);
277280
if (server != null) {
278281
if (LOGGER.isTraceEnabled()) {
279-
LOGGER.trace(String.format("Asynchronously selected server %s", server.getDescription().getAddress()));
282+
LOGGER.trace(format("Asynchronously selected server %s", server.getDescription().getAddress()));
280283
}
281284
request.onResult(server, null);
282285
return true;
@@ -367,9 +370,18 @@ private void throwIfIncompatible(final ClusterDescription curDescription) {
367370
}
368371

369372
private MongoIncompatibleDriverException createIncompatibleException(final ClusterDescription curDescription) {
370-
return new MongoIncompatibleDriverException(format("This version of the driver is not compatible with one or more of "
371-
+ "the servers to which it is connected: %s", curDescription),
372-
curDescription);
373+
String message;
374+
ServerDescription incompatibleServer = curDescription.findServerIncompatiblyOlderThanDriver();
375+
if (incompatibleServer != null) {
376+
message = format("Server at %s reports wire version %d, but this version of the driver requires at least %d (MongoDB %s).",
377+
incompatibleServer.getAddress(), incompatibleServer.getMaxWireVersion(),
378+
MIN_DRIVER_WIRE_VERSION, MIN_DRIVER_SERVER_VERSION);
379+
} else {
380+
incompatibleServer = curDescription.findServerIncompatiblyNewerThanDriver();
381+
message = format("Server at %s requires wire version %d, but this version of the driver only supports up to %d.",
382+
incompatibleServer.getAddress(), incompatibleServer.getMinWireVersion(), MAX_DRIVER_WIRE_VERSION);
383+
}
384+
throw new MongoIncompatibleDriverException(message, curDescription);
373385
}
374386

375387
private MongoTimeoutException createTimeoutException(final ServerSelector serverSelector, final ClusterDescription curDescription) {

driver-core/src/main/com/mongodb/connection/ClusterDescription.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,49 @@ public ServerSettings getServerSettings() {
101101
}
102102

103103
/**
104-
* Return whether the cluster is compatible with the driver.
104+
* Return whether all servers in the cluster are compatible with the driver.
105105
*
106-
* @return true if the cluster is compatible with the driver.
106+
* @return true if all servers in the cluster are compatible with the driver
107107
*/
108108
public boolean isCompatibleWithDriver() {
109-
for (final ServerDescription cur : serverDescriptions) {
109+
for (ServerDescription cur : serverDescriptions) {
110110
if (!cur.isCompatibleWithDriver()) {
111111
return false;
112112
}
113113
}
114114
return true;
115115
}
116116

117+
/**
118+
* Return a server in the cluster that is incompatibly older than the driver.
119+
*
120+
* @return a server in the cluster that is incompatibly older than the driver, or null if there are none
121+
* @since 3.6
122+
*/
123+
public ServerDescription findServerIncompatiblyOlderThanDriver() {
124+
for (ServerDescription cur : serverDescriptions) {
125+
if (cur.isIncompatiblyOlderThanDriver()) {
126+
return cur;
127+
}
128+
}
129+
return null;
130+
}
131+
132+
/**
133+
* Return a server in the cluster that is incompatibly newer than the driver.
134+
*
135+
* @return a server in the cluster that is incompatibly newer than the driver, or null if there are none
136+
* @since 3.6
137+
*/
138+
public ServerDescription findServerIncompatiblyNewerThanDriver() {
139+
for (ServerDescription cur : serverDescriptions) {
140+
if (cur.isIncompatiblyNewerThanDriver()) {
141+
return cur;
142+
}
143+
}
144+
return null;
145+
}
146+
117147
/**
118148
* Returns true if this cluster has at least one server that satisfies the given read preference.
119149
*

driver-core/src/main/com/mongodb/connection/ServerDescription.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
@Immutable
4747
public class ServerDescription {
4848

49+
static final String MIN_DRIVER_SERVER_VERSION = "2.6";
4950
static final int MIN_DRIVER_WIRE_VERSION = 1;
5051
static final int MAX_DRIVER_WIRE_VERSION = 6;
5152

@@ -429,21 +430,39 @@ public ServerDescription build() {
429430
* @return true if the server is compatible with the driver.
430431
*/
431432
public boolean isCompatibleWithDriver() {
432-
if (!ok) {
433-
return true;
434-
}
435-
436-
if (minWireVersion > MAX_DRIVER_WIRE_VERSION) {
433+
if (isIncompatiblyOlderThanDriver()) {
437434
return false;
438435
}
439436

440-
if (maxWireVersion < MIN_DRIVER_WIRE_VERSION) {
437+
if (isIncompatiblyNewerThanDriver()) {
441438
return false;
442439
}
443440

444441
return true;
445442
}
446443

444+
/**
445+
* Return whether the server is compatible with the driver. An incompatible server is one that has a min wire version greater that the
446+
* driver's max wire version or a max wire version less than the driver's min wire version.
447+
*
448+
* @return true if the server is compatible with the driver.
449+
* @since 3.6
450+
*/
451+
public boolean isIncompatiblyNewerThanDriver() {
452+
return ok && minWireVersion > MAX_DRIVER_WIRE_VERSION;
453+
}
454+
455+
/**
456+
* Return whether the server is compatible with the driver. An incompatible server is one that has a min wire version greater that the
457+
* driver's max wire version or a max wire version less than the driver's min wire version.
458+
*
459+
* @return true if the server is compatible with the driver.
460+
* @since 3.6
461+
*/
462+
public boolean isIncompatiblyOlderThanDriver() {
463+
return ok && maxWireVersion < MIN_DRIVER_WIRE_VERSION;
464+
}
465+
447466
/**
448467
* Get the default maximum document size.
449468
*

driver-core/src/test/unit/com/mongodb/connection/ClusterDescriptionTest.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import static com.mongodb.connection.ServerConnectionState.CONNECTED;
3737
import static com.mongodb.connection.ServerConnectionState.CONNECTING;
3838
import static com.mongodb.connection.ServerDescription.MAX_DRIVER_WIRE_VERSION;
39+
import static com.mongodb.connection.ServerDescription.MIN_DRIVER_WIRE_VERSION;
3940
import static com.mongodb.connection.ServerDescription.builder;
4041
import static com.mongodb.connection.ServerType.REPLICA_SET_OTHER;
4142
import static com.mongodb.connection.ServerType.REPLICA_SET_PRIMARY;
@@ -189,7 +190,7 @@ public void testSortingOfAll() throws UnknownHostException {
189190
}
190191

191192
@Test
192-
public void clusterDescriptionWithAnIncompatibleServerShouldBeIncompatible() throws UnknownHostException {
193+
public void clusterDescriptionWithAnIncompatiblyNewServerShouldBeIncompatible() throws UnknownHostException {
193194
ClusterDescription description =
194195
new ClusterDescription(MULTIPLE, UNKNOWN, asList(
195196
builder()
@@ -209,6 +210,33 @@ public void clusterDescriptionWithAnIncompatibleServerShouldBeIncompatible() thr
209210
.build())
210211
);
211212
assertFalse(description.isCompatibleWithDriver());
213+
assertEquals(new ServerAddress("loc:27018"), description.findServerIncompatiblyNewerThanDriver().getAddress());
214+
assertNull(description.findServerIncompatiblyOlderThanDriver());
215+
}
216+
217+
@Test
218+
public void clusterDescriptionWithAnIncompatiblyOlderServerShouldBeIncompatible() throws UnknownHostException {
219+
ClusterDescription description =
220+
new ClusterDescription(MULTIPLE, UNKNOWN, asList(
221+
builder()
222+
.state(CONNECTING)
223+
.address(new ServerAddress("loc:27019"))
224+
.build(),
225+
builder()
226+
.state(CONNECTED)
227+
.ok(true)
228+
.address(new ServerAddress("loc:27018"))
229+
.minWireVersion(0)
230+
.maxWireVersion(MIN_DRIVER_WIRE_VERSION - 1)
231+
.build(),
232+
builder()
233+
.state(CONNECTING)
234+
.address(new ServerAddress("loc:27017"))
235+
.build())
236+
);
237+
assertFalse(description.isCompatibleWithDriver());
238+
assertEquals(new ServerAddress("loc:27018"), description.findServerIncompatiblyOlderThanDriver().getAddress());
239+
assertNull(description.findServerIncompatiblyNewerThanDriver());
212240
}
213241

214242
@Test
@@ -229,6 +257,8 @@ public void clusterDescriptionWithCompatibleServerShouldBeCompatible() throws Un
229257
.build())
230258
);
231259
assertTrue(description.isCompatibleWithDriver());
260+
assertNull(description.findServerIncompatiblyNewerThanDriver());
261+
assertNull(description.findServerIncompatiblyOlderThanDriver());
232262
}
233263

234264
@Test

driver-core/src/test/unit/com/mongodb/connection/ServerDescriptionTest.java

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -437,63 +437,69 @@ public void testHasTags() throws UnknownHostException {
437437

438438
@Test
439439
public void notOkServerShouldBeCompatible() throws UnknownHostException {
440-
assertTrue(builder()
441-
.address(new ServerAddress())
442-
.state(CONNECTING)
443-
.ok(false)
444-
.build()
445-
.isCompatibleWithDriver());
440+
ServerDescription serverDescription = builder()
441+
.address(new ServerAddress())
442+
.state(CONNECTING)
443+
.ok(false)
444+
.build();
445+
assertTrue(serverDescription.isCompatibleWithDriver());
446+
assertFalse(serverDescription.isIncompatiblyNewerThanDriver());
447+
assertFalse(serverDescription.isIncompatiblyOlderThanDriver());
446448
}
447449

448450
@Test
449451
public void serverWithMinWireVersionEqualToDriverMaxWireVersionShouldBeCompatible() throws UnknownHostException {
450-
assertTrue(builder()
451-
.address(new ServerAddress())
452-
.state(CONNECTING)
453-
.ok(true)
454-
.minWireVersion(MAX_DRIVER_WIRE_VERSION)
455-
.maxWireVersion(MAX_DRIVER_WIRE_VERSION + 1)
456-
.build()
457-
.isCompatibleWithDriver());
458-
452+
ServerDescription serverDescription = builder()
453+
.address(new ServerAddress())
454+
.state(CONNECTING)
455+
.ok(true)
456+
.minWireVersion(MAX_DRIVER_WIRE_VERSION)
457+
.maxWireVersion(MAX_DRIVER_WIRE_VERSION + 1)
458+
.build();
459+
assertTrue(serverDescription.isCompatibleWithDriver());
460+
assertFalse(serverDescription.isIncompatiblyNewerThanDriver());
461+
assertFalse(serverDescription.isIncompatiblyOlderThanDriver());
459462
}
460463

461464
@Test
462465
public void serverWithMaxWireVersionEqualToDriverMinWireVersionShouldBeCompatible() throws UnknownHostException {
463-
assertTrue(builder()
464-
.address(new ServerAddress())
465-
.state(CONNECTING)
466-
.ok(true)
467-
.minWireVersion(MIN_DRIVER_WIRE_VERSION - 1)
468-
.maxWireVersion(MIN_DRIVER_WIRE_VERSION)
469-
.build()
470-
.isCompatibleWithDriver());
471-
466+
ServerDescription serverDescription = builder()
467+
.address(new ServerAddress())
468+
.state(CONNECTING)
469+
.ok(true)
470+
.minWireVersion(MIN_DRIVER_WIRE_VERSION - 1)
471+
.maxWireVersion(MIN_DRIVER_WIRE_VERSION)
472+
.build();
473+
assertTrue(serverDescription.isCompatibleWithDriver());
474+
assertFalse(serverDescription.isIncompatiblyNewerThanDriver());
475+
assertFalse(serverDescription.isIncompatiblyOlderThanDriver());
472476
}
473477

474478
@Test
475479
public void serverWithMinWireVersionGreaterThanDriverMaxWireVersionShouldBeIncompatible() throws UnknownHostException {
476-
assertFalse(builder()
477-
.address(new ServerAddress())
478-
.state(CONNECTING)
479-
.ok(true)
480-
.minWireVersion(MAX_DRIVER_WIRE_VERSION + 1)
481-
.maxWireVersion(MAX_DRIVER_WIRE_VERSION + 1)
482-
.build()
483-
.isCompatibleWithDriver());
484-
480+
ServerDescription serverDescription = builder()
481+
.address(new ServerAddress())
482+
.state(CONNECTING)
483+
.ok(true)
484+
.minWireVersion(MAX_DRIVER_WIRE_VERSION + 1)
485+
.maxWireVersion(MAX_DRIVER_WIRE_VERSION + 1)
486+
.build();
487+
assertFalse(serverDescription.isCompatibleWithDriver());
488+
assertTrue(serverDescription.isIncompatiblyNewerThanDriver());
489+
assertFalse(serverDescription.isIncompatiblyOlderThanDriver());
485490
}
486491

487492
@Test
488493
public void serverWithMaxWireVersionLessThanDriverMinWireVersionShouldBeIncompatible() throws UnknownHostException {
489-
assertFalse(builder()
490-
.address(new ServerAddress())
491-
.state(CONNECTING)
492-
.ok(true)
493-
.minWireVersion(MIN_DRIVER_WIRE_VERSION - 1)
494-
.maxWireVersion(MIN_DRIVER_WIRE_VERSION - 1)
495-
.build()
496-
.isCompatibleWithDriver());
497-
494+
ServerDescription serverDescription = builder()
495+
.address(new ServerAddress())
496+
.state(CONNECTING)
497+
.ok(true)
498+
.minWireVersion(MIN_DRIVER_WIRE_VERSION - 1)
499+
.maxWireVersion(MIN_DRIVER_WIRE_VERSION - 1)
500+
.build();
501+
assertFalse(serverDescription.isCompatibleWithDriver());
502+
assertFalse(serverDescription.isIncompatiblyNewerThanDriver());
503+
assertTrue(serverDescription.isIncompatiblyOlderThanDriver());
498504
}
499505
}

0 commit comments

Comments
 (0)