diff --git a/driver-benchmarks/src/main/com/mongodb/benchmark/framework/MongoCryptBenchmarkRunner.java b/driver-benchmarks/src/main/com/mongodb/benchmark/framework/MongoCryptBenchmarkRunner.java
index a6c623364db..c5aec6517ce 100644
--- a/driver-benchmarks/src/main/com/mongodb/benchmark/framework/MongoCryptBenchmarkRunner.java
+++ b/driver-benchmarks/src/main/com/mongodb/benchmark/framework/MongoCryptBenchmarkRunner.java
@@ -67,8 +67,8 @@ private static String getFileAsString(final String fileName) {
throw new RuntimeException("Could not find file " + fileName);
}
return new String(Files.readAllBytes(Paths.get(resource.toURI())));
- } catch (Throwable t) {
- throw new RuntimeException("Could not parse file " + fileName, t);
+ } catch (Exception e) {
+ throw new RuntimeException("Could not parse file " + fileName, e);
}
}
diff --git a/driver-core/src/main/com/mongodb/internal/ExceptionUtils.java b/driver-core/src/main/com/mongodb/internal/ExceptionUtils.java
index 9ccb5ef0c8b..6a0d08ba123 100644
--- a/driver-core/src/main/com/mongodb/internal/ExceptionUtils.java
+++ b/driver-core/src/main/com/mongodb/internal/ExceptionUtils.java
@@ -26,6 +26,8 @@
import org.bson.BsonString;
import org.bson.BsonValue;
+import java.io.PrintStream;
+import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -46,6 +48,42 @@ public static boolean isOperationTimeoutFromSocketException(final Throwable e) {
return e instanceof MongoOperationTimeoutException && e.getCause() instanceof MongoSocketException;
}
+ /**
+ * We must always propagate {@link Error}s, instead of wrapping them in / replacing them with {@link Exception}s, or swallowing them.
+ *
+ * This enables an application to decide how to deal with {@link Error} via {@link UncaughtExceptionHandler}.
+ * An {@link Error} is more likely to cause an invariant violation than an {@link Exception},
+ * because it is less likely to be taken into account in code. An {@link AssertionError} outright informs about an invariant violation.
+ * Furthermore, a {@link VirtualMachineError} not only may happen in a peculiar situation,
+ * but also may be asynchronous.
+ * That is why it may be a good idea for an application to terminate on {@link Error}.
+ * We cannot make such a decision for an application, but we must do our best to give it an opportunity to react to an {@link Error}.
+ *
+ * If there is no {@link UncaughtExceptionHandler}, then the uncaught exception is
+ * {@linkplain Throwable#printStackTrace(PrintStream) printed}
+ * to {@link System#err}, see {@link ThreadGroup#uncaughtException(Thread, Throwable)}.
+ *
+ * @throws Error Iff {@code t} is {@link Error}.
+ * @see #mapUnlessError(Throwable, Function)
+ */
+ public static void rethrowIfError(final Throwable t) {
+ if (t instanceof Error) {
+ throw (Error) t;
+ }
+ }
+
+ /**
+ * See {@link #rethrowIfError(Throwable)}.
+ *
+ * @param mapper Is used iff {@code t} is not {@link Error}.
+ */
+ public static Throwable mapUnlessError(final Throwable t, final Function mapper) {
+ if (t instanceof Error) {
+ return t;
+ }
+ return mapper.apply(t);
+ }
+
public static final class MongoCommandExceptionUtils {
public static int extractErrorCode(final BsonDocument response) {
return extractErrorCodeAsBson(response).intValue();
diff --git a/driver-core/src/main/com/mongodb/internal/async/ErrorHandlingResultCallback.java b/driver-core/src/main/com/mongodb/internal/async/ErrorHandlingResultCallback.java
index da5a09a10b8..100a8b00b6d 100644
--- a/driver-core/src/main/com/mongodb/internal/async/ErrorHandlingResultCallback.java
+++ b/driver-core/src/main/com/mongodb/internal/async/ErrorHandlingResultCallback.java
@@ -20,6 +20,7 @@
import com.mongodb.lang.Nullable;
import static com.mongodb.assertions.Assertions.notNull;
+import static com.mongodb.internal.ExceptionUtils.rethrowIfError;
/**
* This class is not part of the public API and may be removed or changed at any time.
@@ -47,6 +48,7 @@ public void onResult(@Nullable final T result, @Nullable final Throwable t) {
wrapped.onResult(result, t);
} catch (Throwable e) {
logger.error("Callback onResult call produced an error", e);
+ rethrowIfError(e);
}
}
diff --git a/driver-core/src/main/com/mongodb/internal/capi/MongoCryptHelper.java b/driver-core/src/main/com/mongodb/internal/capi/MongoCryptHelper.java
index 240f5051c92..ed9aa52da26 100644
--- a/driver-core/src/main/com/mongodb/internal/capi/MongoCryptHelper.java
+++ b/driver-core/src/main/com/mongodb/internal/capi/MongoCryptHelper.java
@@ -199,8 +199,8 @@ public static void startProcess(final ProcessBuilder processBuilder) {
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(new File(System.getProperty("os.name").startsWith("Windows") ? "NUL" : "/dev/null"));
processBuilder.start();
- } catch (Throwable t) {
- throw new MongoClientException("Exception starting mongocryptd process. Is `mongocryptd` on the system path?", t);
+ } catch (Exception e) {
+ throw new MongoClientException("Exception starting mongocryptd process. Is `mongocryptd` on the system path?", e);
}
}
diff --git a/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java b/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java
index 4146d06c22e..6cedd8647e2 100644
--- a/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java
+++ b/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java
@@ -66,6 +66,7 @@
import static com.mongodb.connection.ServerDescription.MAX_DRIVER_WIRE_VERSION;
import static com.mongodb.connection.ServerDescription.MIN_DRIVER_SERVER_VERSION;
import static com.mongodb.connection.ServerDescription.MIN_DRIVER_WIRE_VERSION;
+import static com.mongodb.internal.ExceptionUtils.rethrowIfError;
import static com.mongodb.internal.Locks.withInterruptibleLock;
import static com.mongodb.internal.VisibleForTesting.AccessModifier.PRIVATE;
import static com.mongodb.internal.connection.EventHelper.wouldDescriptionsGenerateEquivalentEvents;
@@ -185,6 +186,7 @@ public void selectServerAsync(final ServerSelector serverSelector, final Operati
final SingleResultCallback callback) {
if (isClosed()) {
callback.onResult(null, new MongoClientException("Cluster was closed during server selection."));
+ return;
}
Timeout computedServerSelectionTimeout = operationContext.getTimeoutContext().computeServerSelectionTimeout();
@@ -280,7 +282,7 @@ private Timeout startMinWaitHeartbeatTimeout() {
private boolean handleServerSelectionRequest(
final ServerSelectionRequest request, final CountDownLatch currentPhase,
final ClusterDescription description) {
-
+ boolean requestOnResultCalled = false;
try {
OperationContext operationContext = request.getOperationContext();
if (currentPhase != request.phase) {
@@ -303,6 +305,7 @@ private boolean handleServerSelectionRequest(
ServerAddress serverAddress = serverTuple.getServerDescription().getAddress();
logServerSelectionSucceeded(operationContext, clusterId, serverAddress, request.originalSelector, description);
serverDeprioritization.updateCandidate(serverAddress);
+ requestOnResultCalled = true;
request.onResult(serverTuple, null);
return true;
}
@@ -315,7 +318,10 @@ private boolean handleServerSelectionRequest(
logAndThrowTimeoutException(operationContext, request.originalSelector, description);
});
return false;
- } catch (Exception e) {
+ } catch (Throwable e) {
+ if (requestOnResultCalled) {
+ throw e;
+ }
request.onResult(null, e);
return true;
}
@@ -455,8 +461,9 @@ private static final class ServerSelectionRequest {
void onResult(@Nullable final ServerTuple serverTuple, @Nullable final Throwable t) {
try {
callback.onResult(serverTuple, t);
- } catch (Throwable tr) {
- // ignore
+ } catch (Throwable e) {
+ LOGGER.error("Callback onResult call produced an error", e);
+ rethrowIfError(e);
}
}
diff --git a/driver-core/src/main/com/mongodb/internal/connection/InternalStreamConnection.java b/driver-core/src/main/com/mongodb/internal/connection/InternalStreamConnection.java
index 27de4840633..5227221947f 100644
--- a/driver-core/src/main/com/mongodb/internal/connection/InternalStreamConnection.java
+++ b/driver-core/src/main/com/mongodb/internal/connection/InternalStreamConnection.java
@@ -79,6 +79,8 @@
import static com.mongodb.assertions.Assertions.assertNull;
import static com.mongodb.assertions.Assertions.isTrue;
import static com.mongodb.assertions.Assertions.notNull;
+import static com.mongodb.internal.ExceptionUtils.mapUnlessError;
+import static com.mongodb.internal.ExceptionUtils.rethrowIfError;
import static com.mongodb.internal.TimeoutContext.createMongoTimeoutException;
import static com.mongodb.internal.async.AsyncRunnable.beginAsync;
import static com.mongodb.internal.async.ErrorHandlingResultCallback.errorHandlingCallback;
@@ -242,11 +244,8 @@ public void open(final OperationContext originalOperationContext) {
initAfterHandshakeFinish(initializationDescription);
} catch (Throwable t) {
close();
- if (t instanceof MongoException) {
- throw (MongoException) t;
- } else {
- throw new MongoException(t.toString(), t);
- }
+ rethrowIfError(t);
+ throw MongoException.fromThrowableNonNull(t);
}
}
@@ -961,12 +960,12 @@ public void completed(@Nullable final ByteBuf buffer) {
@Override
public void failed(final Throwable t) {
close();
- callback.onResult(null, translateReadFailure(t, operationContext));
+ callback.onResult(null, mapUnlessError(t, e -> translateReadException(e, operationContext)));
}
});
} catch (Throwable t) {
close();
- callback.onResult(null, translateReadFailure(t, operationContext));
+ callback.onResult(null, mapUnlessError(t, e -> translateReadException(e, operationContext)));
}
}
@@ -990,17 +989,6 @@ private void updateSessionContext(final SessionContext sessionContext, final Res
}
}
- /**
- * Rethrows a fatal JVM {@link Error} (e.g. {@link OutOfMemoryError}) unchanged, so it is never downgraded to a
- * catchable {@link MongoException}. Used by the paths that propagate a failure by throwing; the async read path
- * delivers the failure as a callback value instead and uses {@link #translateReadFailure} for the same purpose.
- */
- private static void rethrowIfError(final Throwable t) {
- if (t instanceof Error) {
- throw (Error) t;
- }
- }
-
private void throwTranslatedWriteException(final Throwable e, final OperationContext operationContext) {
rethrowIfError(e);
if (operationContext.getTimeoutContext().hasTimeoutMS()) {
@@ -1026,18 +1014,6 @@ private void throwTranslatedWriteException(final Throwable e, final OperationCon
}
}
- /**
- * Translates a read failure for delivery to an async callback. {@link Error}s are passed through unchanged
- * rather than wrapped in a {@link MongoException}, so a fatal JVM error (e.g. {@link OutOfMemoryError}) is not
- * downgraded to a catchable exception. The sync read path uses {@link #rethrowIfError} for the same purpose.
- */
- private Throwable translateReadFailure(final Throwable e, final OperationContext operationContext) {
- if (e instanceof Error) {
- return e;
- }
- return translateReadException(e, operationContext);
- }
-
private MongoSocketWriteTimeoutException createWriteTimeoutException(final SocketTimeoutException e) {
return new MongoSocketWriteTimeoutException("Timeout while sending message", getServerAddress(), e);
}
diff --git a/driver-core/src/main/com/mongodb/internal/connection/LoadBalancedCluster.java b/driver-core/src/main/com/mongodb/internal/connection/LoadBalancedCluster.java
index 2401a9e014a..a83048096f8 100644
--- a/driver-core/src/main/com/mongodb/internal/connection/LoadBalancedCluster.java
+++ b/driver-core/src/main/com/mongodb/internal/connection/LoadBalancedCluster.java
@@ -61,6 +61,7 @@
import static com.mongodb.assertions.Assertions.isTrue;
import static com.mongodb.assertions.Assertions.notNull;
import static com.mongodb.connection.ServerConnectionState.CONNECTING;
+import static com.mongodb.internal.ExceptionUtils.rethrowIfError;
import static com.mongodb.internal.connection.BaseCluster.logServerSelectionStarted;
import static com.mongodb.internal.connection.BaseCluster.logServerSelectionSucceeded;
import static com.mongodb.internal.connection.BaseCluster.logTopologyMonitoringStopping;
@@ -445,16 +446,18 @@ OperationContext getOperationContext() {
public void onSuccess(final ServerTuple serverTuple) {
try {
callback.onResult(serverTuple, null);
- } catch (Exception e) {
- LOGGER.warn("Unanticipated exception thrown from callback", e);
+ } catch (Throwable t) {
+ LOGGER.error("Callback onResult call produced an error", t);
+ rethrowIfError(t);
}
}
public void onError(final Throwable exception) {
try {
callback.onResult(null, exception);
- } catch (Exception e) {
- LOGGER.warn("Unanticipated exception thrown from callback", e);
+ } catch (Throwable t) {
+ LOGGER.error("Callback onResult call produced an error", t);
+ rethrowIfError(t);
}
}
}
diff --git a/driver-core/src/main/com/mongodb/internal/connection/tlschannel/async/AsynchronousTlsChannelGroup.java b/driver-core/src/main/com/mongodb/internal/connection/tlschannel/async/AsynchronousTlsChannelGroup.java
index 5150149fa6a..cdbd32cc625 100644
--- a/driver-core/src/main/com/mongodb/internal/connection/tlschannel/async/AsynchronousTlsChannelGroup.java
+++ b/driver-core/src/main/com/mongodb/internal/connection/tlschannel/async/AsynchronousTlsChannelGroup.java
@@ -58,6 +58,7 @@
import java.util.function.Consumer;
import java.util.function.LongConsumer;
+import static com.mongodb.internal.ExceptionUtils.rethrowIfError;
import static com.mongodb.internal.thread.InterruptionUtil.interruptAndCreateMongoInterruptedException;
import static java.lang.String.format;
@@ -233,6 +234,7 @@ public void execute(final Runnable r) {
r.run();
} catch (Throwable t) {
LOGGER.error(null, t);
+ rethrowIfError(t);
}
});
}
@@ -427,8 +429,9 @@ private void loop() {
processPendingInterests();
checkClosings();
}
- } catch (Throwable e) {
- LOGGER.error("error in selector loop", e);
+ } catch (Throwable t) {
+ LOGGER.error(this + " stopped working. You may want to recreate the MongoClient", t);
+ rethrowIfError(t);
} finally {
executor.shutdown();
// use shutdownNow to stop delayed tasks
@@ -467,6 +470,7 @@ private void processWrite(RegisteredSocket socket) {
doWrite(socket, op);
} catch (Throwable e) {
LOGGER.error("error in operation", e);
+ rethrowIfError(e);
}
});
}
@@ -486,6 +490,7 @@ private void processRead(RegisteredSocket socket) {
doRead(socket, op);
} catch (Throwable e) {
LOGGER.error("error in operation", e);
+ rethrowIfError(e);
}
});
}
diff --git a/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java b/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java
index cf9f1dcf6c4..ac83c5618ea 100644
--- a/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java
+++ b/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java
@@ -40,6 +40,7 @@
import java.util.function.Consumer;
import static com.mongodb.assertions.Assertions.assertNotNull;
+import static com.mongodb.internal.ExceptionUtils.rethrowIfError;
import static com.mongodb.internal.operation.ChangeStreamBatchCursorHelper.isResumableError;
import static com.mongodb.internal.operation.SyncOperationHelper.withReadConnectionSource;
@@ -239,6 +240,7 @@ private R execute(final BiFunction, OperationContext
try {
return function.apply(wrapped, operationContext);
} catch (Throwable t) {
+ rethrowIfError(t);
if (!isResumableError(t, maxWireVersion)) {
throw MongoException.fromThrowableNonNull(t);
}
diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java
index 511f9f62c6b..589084716f5 100644
--- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java
+++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java
@@ -230,7 +230,9 @@ public Publisher abortTransaction() {
return executor
.execute(new AbortTransactionOperation(writeConcern)
.recoveryToken(getRecoveryToken()), readConcern, this)
- .onErrorResume(Throwable.class, (e) -> Mono.empty())
+ .onErrorResume(Exception.class, e ->
+ // ignore exceptions from abort
+ Mono.empty())
.doOnTerminate(() -> {
clearTransactionContext();
cleanupTransaction(TransactionState.ABORTED);
diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/CommandMarker.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/CommandMarker.java
index 443ebbe14bd..826b662a70e 100644
--- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/CommandMarker.java
+++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/CommandMarker.java
@@ -87,13 +87,13 @@ class CommandMarker implements Closeable {
Mono mark(final String databaseName, final RawBsonDocument command, @Nullable final Timeout operationTimeout) {
if (client != null) {
return runCommand(databaseName, command, operationTimeout)
- .onErrorResume(Throwable.class, e -> {
+ .onErrorResume(Exception.class, e -> {
if (processBuilder == null || e instanceof MongoOperationTimeoutException) {
throw MongoException.fromThrowable(e);
}
return Mono.fromRunnable(() -> startProcess(processBuilder)).then(runCommand(databaseName, command, operationTimeout));
})
- .onErrorMap(t -> new MongoClientException("Exception in encryption library: " + t.getMessage(), t));
+ .onErrorMap(Exception.class, e -> new MongoClientException("Exception in encryption library: " + e.getMessage(), e));
} else {
return Mono.fromCallable(() -> command);
}
diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/Crypt.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/Crypt.java
index a9407799dc7..0138c5859e5 100644
--- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/Crypt.java
+++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/Crypt.java
@@ -46,6 +46,7 @@
import java.util.function.Supplier;
import static com.mongodb.assertions.Assertions.notNull;
+import static com.mongodb.internal.ExceptionUtils.mapUnlessError;
import static com.mongodb.internal.client.vault.EncryptOptionsHelper.asMongoExplicitEncryptOptions;
import static com.mongodb.internal.crypt.capi.MongoCryptContext.State;
@@ -146,7 +147,7 @@ public Mono encrypt(final String databaseName, final RawBsonDoc
public Mono decrypt(final RawBsonDocument commandResponse, @Nullable final Timeout timeout) {
notNull("commandResponse", commandResponse);
return executeStateMachine(() -> mongoCrypt.createDecryptionContext(commandResponse), timeout)
- .onErrorMap(this::wrapInClientException);
+ .onErrorMap(Exception.class, Crypt::wrapInClientException);
}
/**
@@ -247,7 +248,7 @@ private Mono executeStateMachine(final Suppliercreate(sink -> executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout))
- .onErrorMap(this::wrapInClientException)
+ .onErrorMap(Exception.class, Crypt::wrapInClientException)
.doFinally(s -> cryptContext.close());
} catch (MongoCryptException e) {
return Mono.error(wrapInClientException(e));
@@ -309,7 +310,7 @@ private void collInfo(final MongoCryptContext cryptContext,
cryptContext.completeMongoOperation();
executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout);
})
- .doOnError(t -> sink.error(MongoException.fromThrowableNonNull(t)))
+ .doOnError(t -> sink.error(mapUnlessError(t, MongoException::fromThrowableNonNull)))
.subscribe();
}
}
@@ -330,7 +331,7 @@ private void mark(final MongoCryptContext cryptContext,
cryptContext.completeMongoOperation();
executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout);
})
- .doOnError(e -> sink.error(wrapInClientException(e)))
+ .doOnError(t -> sink.error(mapUnlessError(t, Crypt::wrapInClientException)))
.subscribe();
}
}
@@ -348,7 +349,7 @@ private void fetchKeys(final MongoCryptContext cryptContext,
cryptContext.completeMongoOperation();
executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout);
})
- .doOnError(t -> sink.error(MongoException.fromThrowableNonNull(t)))
+ .doOnError(t -> sink.error(mapUnlessError(t, MongoException::fromThrowableNonNull)))
.subscribe();
}
@@ -361,22 +362,22 @@ private void decryptKeys(final MongoCryptContext cryptContext,
keyManagementService.decryptKey(keyDecryptor, operationTimeout)
.contextWrite(sink.contextView())
.doOnSuccess(r -> decryptKeys(cryptContext, databaseName, sink, operationTimeout))
- .doOnError(e -> sink.error(wrapInClientException(e)))
+ .doOnError(t -> sink.error(mapUnlessError(t, Crypt::wrapInClientException)))
.subscribe();
} else {
Mono.fromRunnable(cryptContext::completeKeyDecryptors)
.contextWrite(sink.contextView())
.doOnSuccess(r -> executeStateMachineWithSink(cryptContext, databaseName, sink, operationTimeout))
- .doOnError(e -> sink.error(wrapInClientException(e)))
+ .doOnError(t -> sink.error(mapUnlessError(t, Crypt::wrapInClientException)))
.subscribe();
}
}
- private Throwable wrapInClientException(final Throwable t) {
+ private static MongoClientException wrapInClientException(final Throwable t) {
if (t instanceof MongoClientException) {
- return t;
+ return (MongoClientException) t;
+ } else {
+ return new MongoClientException("Exception in encryption library: " + t.getMessage(), t);
}
- return new MongoClientException("Exception in encryption library: " + t.getMessage(), t);
}
-
}
diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/KeyManagementService.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/KeyManagementService.java
index 67ebf421c9c..b40ec164060 100644
--- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/KeyManagementService.java
+++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/KeyManagementService.java
@@ -100,7 +100,7 @@ public void failed(final Throwable t) {
handleError(t, operationContext, sink);
}
});
- }).onErrorMap(this::unWrapException);
+ }).onErrorMap(Exception.class, this::unWrapException);
}
private void streamWrite(final Stream stream, final MongoKeyDecryptor keyDecryptor,
diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/vault/ClientEncryptionImpl.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/vault/ClientEncryptionImpl.java
index 5ae7f4815e5..9942bae926c 100644
--- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/vault/ClientEncryptionImpl.java
+++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/vault/ClientEncryptionImpl.java
@@ -62,6 +62,7 @@
import java.util.stream.Collectors;
import static com.mongodb.assertions.Assertions.notNull;
+import static com.mongodb.internal.ExceptionUtils.mapUnlessError;
import static com.mongodb.internal.VisibleForTesting.AccessModifier.PRIVATE;
import static com.mongodb.internal.capi.MongoCryptHelper.validateRewrapManyDataKeyOptions;
import static com.mongodb.reactivestreams.client.internal.TimeoutHelper.collectionWithTimeout;
@@ -304,9 +305,9 @@ public Publisher createEncryptedCollection(final MongoDatabase dat
.createCollection(collectionName, new CreateCollectionOptions(createCollectionOptions)
.encryptedFields(maybeUpdatedEncryptedFields))))
)
- .onErrorMap(e -> dataKeyMightBeCreated.get(), e ->
+ .onErrorMap(t -> dataKeyMightBeCreated.get(), t -> mapUnlessError(t, e ->
new MongoUpdatedEncryptedFieldsException(maybeUpdatedEncryptedFields,
- format("Failed to create %s.", namespace), e)
+ format("Failed to create %s.", namespace), e))
)
.thenReturn(maybeUpdatedEncryptedFields);
});
diff --git a/driver-sync/src/main/com/mongodb/client/internal/CommandMarker.java b/driver-sync/src/main/com/mongodb/client/internal/CommandMarker.java
index d694cf682a3..365b1fc49e1 100644
--- a/driver-sync/src/main/com/mongodb/client/internal/CommandMarker.java
+++ b/driver-sync/src/main/com/mongodb/client/internal/CommandMarker.java
@@ -99,7 +99,7 @@ RawBsonDocument mark(final String databaseName, final RawBsonDocument command, @
return executeCommand(databaseName, command, timeout);
}
} catch (MongoException e) {
- throw wrapInClientException(e);
+ throw new MongoClientException("Exception in encryption library: " + e.getMessage(), e);
}
} else {
return command;
@@ -126,8 +126,4 @@ private RawBsonDocument executeCommand(
return databaseWithTimeout(mongoDatabase, TIMEOUT_ERROR_MESSAGE, timeout)
.runCommand(markableCommand, RawBsonDocument.class);
}
-
- private MongoClientException wrapInClientException(final MongoException e) {
- return new MongoClientException("Exception in encryption library: " + e.getMessage(), e);
- }
}
diff --git a/driver-sync/src/main/com/mongodb/client/internal/Crypt.java b/driver-sync/src/main/com/mongodb/client/internal/Crypt.java
index 67fac13770c..a6fe46eecc3 100644
--- a/driver-sync/src/main/com/mongodb/client/internal/Crypt.java
+++ b/driver-sync/src/main/com/mongodb/client/internal/Crypt.java
@@ -146,7 +146,7 @@ RawBsonDocument encrypt(
try (MongoCryptContext encryptionContext = mongoCrypt.createEncryptionContext(databaseName, command)) {
return executeStateMachine(encryptionContext, databaseName, timeout);
} catch (MongoCryptException e) {
- throw wrapInMongoException(e);
+ throw wrapInClientException(e);
}
}
@@ -161,7 +161,7 @@ RawBsonDocument decrypt(final RawBsonDocument commandResponse, @Nullable final
try (MongoCryptContext decryptionContext = mongoCrypt.createDecryptionContext(commandResponse)) {
return executeStateMachine(decryptionContext, null, timeoutOperation);
} catch (MongoCryptException e) {
- throw wrapInMongoException(e);
+ throw wrapInClientException(e);
}
}
@@ -184,7 +184,7 @@ BsonDocument createDataKey(final String kmsProvider, final DataKeyOptions option
.build())) {
return executeStateMachine(dataKeyCreationContext, null, operationTimeout);
} catch (MongoCryptException e) {
- throw wrapInMongoException(e);
+ throw wrapInClientException(e);
}
}
@@ -203,7 +203,7 @@ BsonBinary encryptExplicitly(final BsonValue value, final EncryptOptions options
new BsonDocument("v", value), asMongoExplicitEncryptOptions(options))) {
return executeStateMachine(encryptionContext, null, timeoutOperation).getBinary("v");
} catch (MongoCryptException e) {
- throw wrapInMongoException(e);
+ throw wrapInClientException(e);
}
}
@@ -222,7 +222,7 @@ BsonDocument encryptExpression(final BsonDocument expression, final EncryptOptio
new BsonDocument("v", expression), asMongoExplicitEncryptOptions(options))) {
return executeStateMachine(encryptionContext, null, timeoutOperation).getDocument("v");
} catch (MongoCryptException e) {
- throw wrapInMongoException(e);
+ throw wrapInClientException(e);
}
}
@@ -237,7 +237,7 @@ BsonValue decryptExplicitly(final BsonBinary value, @Nullable final Timeout time
try (MongoCryptContext decryptionContext = mongoCrypt.createExplicitDecryptionContext(new BsonDocument("v", value))) {
return assertNotNull(executeStateMachine(decryptionContext, null, timeoutOperation).get("v"));
} catch (MongoCryptException e) {
- throw wrapInMongoException(e);
+ throw wrapInClientException(e);
}
}
@@ -260,7 +260,7 @@ BsonDocument rewrapManyDataKey(final BsonDocument filter, final RewrapManyDataKe
return executeStateMachine(rewrapManyDatakeyContext, null, operationTimeout);
}
} catch (MongoCryptException e) {
- throw wrapInMongoException(e);
+ throw wrapInClientException(e);
}
}
@@ -321,8 +321,8 @@ private void collInfo(final MongoCryptContext cryptContext, final String databas
cryptContext.addMongoOperationResult(result);
}
cryptContext.completeMongoOperation();
- } catch (Throwable t) {
- throw MongoException.fromThrowableNonNull(t);
+ } catch (Exception e) {
+ throw MongoException.fromThrowableNonNull(e);
}
}
@@ -331,8 +331,8 @@ private void mark(final MongoCryptContext cryptContext, final String databaseNam
RawBsonDocument markedCommand = assertNotNull(commandMarker).mark(databaseName, cryptContext.getMongoOperation(), timeout);
cryptContext.addMongoOperationResult(markedCommand);
cryptContext.completeMongoOperation();
- } catch (Throwable t) {
- throw wrapInMongoException(t);
+ } catch (Exception e) {
+ throw wrapInClientException(e);
}
}
@@ -342,8 +342,8 @@ private void fetchKeys(final MongoCryptContext keyBroker, @Nullable final Timeou
keyBroker.addMongoOperationResult(bsonDocument);
}
keyBroker.completeMongoOperation();
- } catch (Throwable t) {
- throw MongoException.fromThrowableNonNull(t);
+ } catch (Exception e) {
+ throw MongoException.fromThrowableNonNull(e);
}
}
@@ -355,9 +355,9 @@ private void decryptKeys(final MongoCryptContext cryptContext, @Nullable final T
keyDecryptor = cryptContext.nextKeyDecryptor();
}
cryptContext.completeKeyDecryptors();
- } catch (Throwable t) {
- throw translateInterruptedException(t, "Interrupted while doing IO")
- .orElseThrow(() -> wrapInMongoException(t));
+ } catch (Exception e) {
+ throw translateInterruptedException(e, "Interrupted while doing IO")
+ .orElseThrow(() -> wrapInClientException(e));
}
}
@@ -378,11 +378,11 @@ private void decryptKey(final MongoKeyDecryptor keyDecryptor, @Nullable final Ti
}
}
- private MongoException wrapInMongoException(final Throwable t) {
- if (t instanceof MongoClientException) {
- return (MongoException) t;
+ private static MongoClientException wrapInClientException(final Exception e) {
+ if (e instanceof MongoClientException) {
+ return (MongoClientException) e;
} else {
- return new MongoClientException("Exception in encryption library: " + t.getMessage(), t);
+ return new MongoClientException("Exception in encryption library: " + e.getMessage(), e);
}
}
}
diff --git a/gradle.properties b/gradle.properties
index 733e8118433..9f2453d567e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -14,7 +14,7 @@
# limitations under the License.
#
-version=5.10.0-SNAPSHOT
+version=5.11.0-SNAPSHOT
org.gradle.daemon=true
org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en