Translate CasMismatchException to OptimisticLockingFailureException. (#1341)

Translate CasMismatchException to OptimisticLockingFailureException
instead of DataIntegrityViolationException.  CasMismatchException is
a ConcurrencyFailureException which is a TransientDataAccessException.
Versus DataIntegrityViolation, which is a NonTransientDataAccessException.

Closed #1339.
This commit is contained in:
Michael Reiche
2022-02-15 11:38:25 -08:00
committed by GitHub
parent fc075ccdeb
commit 1fcd252b68
8 changed files with 21 additions and 16 deletions

View File

@@ -375,7 +375,7 @@ public class User {
If you load a document through the template or repository, the version field will be automatically populated with the current CAS value.
It is important to note that you shouldn't access the field or even change it on your own.
Once you save the document back, it will either succeed or fail with a `DataIntegrityViolationException`.
Once you save the document back, it will either succeed or fail with a `OptimisticLockingFailureException`.
If you get such an exception, the further approach depends on what you want to achieve application wise.
You should either retry the complete load-update-write cycle or propagate the error to the upper layers for proper handling.

View File

@@ -25,6 +25,7 @@ import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.dao.OptimisticLockingFailureException;;
import org.springframework.dao.QueryTimeoutException;
import org.springframework.dao.TransientDataAccessResourceException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
@@ -66,8 +67,11 @@ public class CouchbaseExceptionTranslator implements PersistenceExceptionTransla
return new DataRetrievalFailureException(ex.getMessage(), ex);
}
if (ex instanceof CasMismatchException || ex instanceof ConcurrentModificationException
|| ex instanceof ReplicaNotConfiguredException || ex instanceof DurabilityLevelNotAvailableException
if (ex instanceof CasMismatchException || ex instanceof ConcurrentModificationException) {
return new OptimisticLockingFailureException(ex.getMessage(), ex);
}
if ( ex instanceof ReplicaNotConfiguredException || ex instanceof DurabilityLevelNotAvailableException
|| ex instanceof DurabilityImpossibleException || ex instanceof DurabilityAmbiguousException) {
return new DataIntegrityViolationException(ex.getMessage(), ex);
}

View File

@@ -39,6 +39,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.couchbase.core.ExecutableFindByIdOperation.ExecutableFindById;
import org.springframework.data.couchbase.core.ExecutableRemoveByIdOperation.ExecutableRemoveById;
import org.springframework.data.couchbase.core.ExecutableReplaceByIdOperation.ExecutableReplaceById;
@@ -137,7 +138,7 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
User badUser = new User(user.getId(), user.getFirstname(), user.getLastname());
badUser.setVersion(12345678);
assertThrows(DataIntegrityViolationException.class, () -> couchbaseTemplate.replaceById(User.class).one(badUser));
assertThrows(OptimisticLockingFailureException.class, () -> couchbaseTemplate.replaceById(User.class).one(badUser));
User found = couchbaseTemplate.findById(User.class).one(user.getId());
assertEquals(modified, found);
@@ -347,7 +348,7 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
// careful now - user and modified are the same object. The object has the new cas (@Version version)
Long savedCas = modified.getVersion();
modified.setVersion(123);
assertThrows(DataIntegrityViolationException.class, () -> couchbaseTemplate.removeById()
assertThrows(OptimisticLockingFailureException.class, () -> couchbaseTemplate.removeById()
.withCas(reactiveCouchbaseTemplate.support().getCas(modified)).one(modified.getId()));
modified.setVersion(savedCas);
couchbaseTemplate.removeById().withCas(reactiveCouchbaseTemplate.support().getCas(modified))

View File

@@ -37,8 +37,8 @@ import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.couchbase.core.ReactiveFindByIdOperation.ReactiveFindById;
import org.springframework.data.couchbase.core.ReactiveRemoveByIdOperation.ReactiveRemoveById;
import org.springframework.data.couchbase.core.ReactiveReplaceByIdOperation.ReactiveReplaceById;
@@ -130,7 +130,7 @@ class ReactiveCouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationT
User badUser = new User(user.getId(), user.getFirstname(), user.getLastname());
badUser.setVersion(12345678);
assertThrows(DataIntegrityViolationException.class,
assertThrows(OptimisticLockingFailureException.class,
() -> reactiveCouchbaseTemplate.replaceById(User.class).one(badUser).block());
User found = reactiveCouchbaseTemplate.findById(User.class).one(user.getId()).block();
@@ -285,7 +285,7 @@ class ReactiveCouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationT
// careful now - user and modified are the same object. The object has the new cas (@Version version)
Long savedCas = modified.getVersion();
modified.setVersion(123);
assertThrows(DataIntegrityViolationException.class, () -> reactiveCouchbaseTemplate.removeById()
assertThrows(OptimisticLockingFailureException.class, () -> reactiveCouchbaseTemplate.removeById()
.withCas(reactiveCouchbaseTemplate.support().getCas(modified)).one(modified.getId()).block());
modified.setVersion(savedCas);
reactiveCouchbaseTemplate.removeById().withCas(reactiveCouchbaseTemplate.support().getCas(modified))

View File

@@ -36,8 +36,8 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.data.couchbase.domain.Airline;
@@ -111,7 +111,7 @@ public class CouchbaseRepositoryKeyValueIntegrationTests extends ClusterAwareInt
user.setVersion(0);
assertThrows(DuplicateKeyException.class, () -> userRepository.save(user));
user.setVersion(saveVersion + 1);
assertThrows(DataIntegrityViolationException.class, () -> userRepository.save(user));
assertThrows(OptimisticLockingFailureException.class, () -> userRepository.save(user));
userRepository.delete(user);
// Airline does not have a version

View File

@@ -55,8 +55,8 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.auditing.DateTimeProvider;
import org.springframework.data.couchbase.CouchbaseClientFactory;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
@@ -566,7 +566,7 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
userRepository.save(user);
long saveVersion = user.getVersion();
user.setVersion(user.getVersion() - 1);
assertThrows(DataIntegrityViolationException.class, () -> userRepository.save(user));
assertThrows(OptimisticLockingFailureException.class, () -> userRepository.save(user));
user.setVersion(saveVersion);
userRepository.save(user);
userRepository.delete(user);

View File

@@ -28,8 +28,8 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.auditing.DateTimeProvider;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import org.springframework.data.couchbase.domain.Airline;
@@ -72,7 +72,7 @@ public class ReactiveCouchbaseRepositoryKeyValueIntegrationTests extends Cluster
user.setVersion(0);
assertThrows(DuplicateKeyException.class, () -> userRepository.save(user).block());
user.setVersion(saveVersion + 1);
assertThrows(DataIntegrityViolationException.class, () -> userRepository.save(user).block());
assertThrows(OptimisticLockingFailureException.class, () -> userRepository.save(user).block());
userRepository.delete(user);
// Airline does not have a version

View File

@@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.springframework.dao.OptimisticLockingFailureException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@@ -40,7 +41,6 @@ import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.couchbase.CouchbaseClientFactory;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
@@ -120,7 +120,7 @@ public class ReactiveCouchbaseRepositoryQueryIntegrationTests extends JavaIntegr
userRepository.save(user).block();
long saveVersion = user.getVersion();
user.setVersion(user.getVersion() - 1);
assertThrows(DataIntegrityViolationException.class, () -> userRepository.save(user).block());
assertThrows(OptimisticLockingFailureException.class, () -> userRepository.save(user).block());
user.setVersion(saveVersion);
userRepository.save(user).block();
userRepository.delete(user).block();