diff --git a/src/main/asciidoc/entity.adoc b/src/main/asciidoc/entity.adoc index 057b9e2e..b713edfb 100644 --- a/src/main/asciidoc/entity.adoc +++ b/src/main/asciidoc/entity.adoc @@ -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. diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java index 264c8334..e4d22669 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java @@ -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); } diff --git a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java index ec405b74..2e9f14d1 100644 --- a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java @@ -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)) diff --git a/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java index 2bb669cb..8fd709ec 100644 --- a/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java @@ -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)) diff --git a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java index e3381b56..7143bb26 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java @@ -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 diff --git a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java index fd8ac10f..b24ff3aa 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java @@ -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); diff --git a/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryKeyValueIntegrationTests.java index 9192639d..46169ba5 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryKeyValueIntegrationTests.java @@ -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 diff --git a/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java index a6c7bfb1..725a93b6 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java @@ -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();