Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.mongodb.ClientBulkWriteException;
import org.bson.BsonInvalidOperationException;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
Expand Down Expand Up @@ -50,6 +51,7 @@
* @author Michal Vich
* @author Christoph Strobl
* @author Brice Vandeputte
* @author Seonwoo Jung
*/
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {

Expand Down Expand Up @@ -120,6 +122,10 @@ DataAccessException doTranslateException(RuntimeException ex) {
}
}

if (isTransientFailure(ex)) {
return new ConcurrencyFailureException(ex.getMessage(), ex);
}

return new DataIntegrityViolationException(ex.getMessage(), ex);
}

Expand All @@ -142,6 +148,9 @@ DataAccessException doTranslateException(RuntimeException ex) {
return new PermissionDeniedDataAccessException(ex.getMessage(), ex);
}
if (MongoDbErrorCodes.isDataIntegrityViolationError(mongoException)) {
if (isTransientFailure(mongoException)) {
return new ConcurrencyFailureException(mongoException.getMessage(), mongoException);
}
return new DataIntegrityViolationException(mongoException.getMessage(), mongoException);
}
if (MongoDbErrorCodes.isClientSessionFailure(mongoException)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.mockito.Mockito;

import org.springframework.core.NestedRuntimeException;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DuplicateKeyException;
Expand All @@ -39,7 +40,9 @@
import com.mongodb.MongoSocketException;
import com.mongodb.MongoSocketReadTimeoutException;
import com.mongodb.MongoSocketWriteException;
import com.mongodb.MongoWriteException;
import com.mongodb.ServerAddress;
import com.mongodb.WriteError;

/**
* Unit tests for {@link MongoExceptionTranslator}.
Expand All @@ -48,6 +51,7 @@
* @author Oliver Gierke
* @author Christoph Strobl
* @author Brice Vandeputte
* @author Seonwoo Jung
*/
class MongoExceptionTranslatorUnitTests {

Expand Down Expand Up @@ -193,6 +197,42 @@ public void translateMongoExceptionWithTransientLabel() {
expectExceptionWithCauseMessage(translatedException, UncategorizedMongoDbException.class);
}

@Test // GH-5150
void translateTransientWriteConflictMongoException() {

MongoException source = new MongoException(112, "WriteConflict");
source.addLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL);

DataAccessException translated = translator.translateExceptionIfPossible(source);

expectExceptionWithCauseMessage(translated, ConcurrencyFailureException.class, "WriteConflict");
assertThat(translator.isTransientFailure(translated)).isTrue();
}

@Test // GH-5150
void translateTransientMongoWriteException() {

WriteError writeError = new WriteError(112, "WriteConflict", new BsonDocument());
MongoWriteException source = new MongoWriteException(writeError, new ServerAddress());
source.addLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL);

DataAccessException translated = translator.translateExceptionIfPossible(source);

expectExceptionWithCauseMessage(translated, ConcurrencyFailureException.class, "WriteConflict");
assertThat(translator.isTransientFailure(translated)).isTrue();
}

@Test // GH-5150
void translateNonTransientWriteConflictMongoException() {

MongoException source = new MongoException(112, "WriteConflict");

DataAccessException translated = translator.translateExceptionIfPossible(source);

expectExceptionWithCauseMessage(translated,
org.springframework.dao.DataIntegrityViolationException.class, "WriteConflict");
}

private void checkTranslatedMongoException(Class<? extends Exception> clazz, int code) {

DataAccessException translated = translator.translateExceptionIfPossible(new MongoException(code, ""));
Expand Down
Loading