From 1955cf45cd5d7c8b9edc64a695f42df347dd0fce Mon Sep 17 00:00:00 2001 From: Michael Reiche <48999328+mikereiche@users.noreply.github.com> Date: Wed, 14 Oct 2020 14:54:01 -0700 Subject: [PATCH] DATACOUCH-626 - Handle reading into entity with only all-args constructor; version primative type. The version arg - which is not in the document - will be passed into the constructor as a null which will fail if it is a primitive type. This change will pre-populated the converted object with the version/cas, so that it is not null. Co-authored-by: mikereiche --- .../core/CouchbaseTemplateSupport.java | 5 +- .../couchbase/repository/support/Util.java | 21 ++++++ .../couchbase/domain/SubscriptionToken.java | 75 +++++++++++++++++++ .../domain/SubscriptionTokenRepository.java | 29 +++++++ ...aseRepositoryKeyValueIntegrationTests.java | 17 +++++ 5 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/springframework/data/couchbase/domain/SubscriptionToken.java create mode 100644 src/test/java/org/springframework/data/couchbase/domain/SubscriptionTokenRepository.java diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplateSupport.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplateSupport.java index 89eb0028..dc4403f3 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplateSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplateSupport.java @@ -75,10 +75,13 @@ class CouchbaseTemplateSupport implements ApplicationContextAware { public T decodeEntity(String id, String source, long cas, Class entityClass) { final CouchbaseDocument converted = new CouchbaseDocument(id); converted.setId(id); + CouchbasePersistentEntity persistentEntity = mappingContext.getRequiredPersistentEntity(entityClass); + if (cas != 0 && persistentEntity.getVersionProperty() != null) { + converted.put(persistentEntity.getVersionProperty().getName(), cas); + } T readEntity = converter.read(entityClass, (CouchbaseDocument) translationService.decode(source, converted)); final ConvertingPropertyAccessor accessor = getPropertyAccessor(readEntity); - CouchbasePersistentEntity persistentEntity = mappingContext.getRequiredPersistentEntity(readEntity.getClass()); if (persistentEntity.getVersionProperty() != null) { accessor.setProperty(persistentEntity.getVersionProperty(), cas); diff --git a/src/main/java/org/springframework/data/couchbase/repository/support/Util.java b/src/main/java/org/springframework/data/couchbase/repository/support/Util.java index 6395eeab..ad8f3467 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/support/Util.java +++ b/src/main/java/org/springframework/data/couchbase/repository/support/Util.java @@ -1,9 +1,30 @@ +/* + * Copyright 2020 the original author or authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.data.couchbase.repository.support; import org.springframework.data.couchbase.core.convert.CouchbaseConverter; import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity; import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty; +/** + * Utility class for Couchbase Repository + * + * @author Michael Reiche + */ public class Util { public static boolean hasNonZeroVersionProperty(Object entity, CouchbaseConverter converter) { diff --git a/src/test/java/org/springframework/data/couchbase/domain/SubscriptionToken.java b/src/test/java/org/springframework/data/couchbase/domain/SubscriptionToken.java new file mode 100644 index 00000000..5230f8e4 --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/domain/SubscriptionToken.java @@ -0,0 +1,75 @@ +/* + * Copyright 2020 the original author or authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.couchbase.domain; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Version; +import org.springframework.data.couchbase.core.mapping.Document; +import org.springframework.data.couchbase.core.mapping.Field; +import org.springframework.data.couchbase.core.mapping.id.GeneratedValue; +import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy; + +/** + * SubscriptionTokenEntity for tests + * + * @author Michael Reiche + */ +@Getter +@ToString +@EqualsAndHashCode +@Document +public class SubscriptionToken { + private @Id + @GeneratedValue(strategy = GenerationStrategy.UNIQUE) + String id; + private @Version + long version; + private @Field + String subscriptionType; + private @Field + String userName; + private @Field + String appId; + private @Field + String deviceId; + private @Field + long subscriptionDate; + + public SubscriptionToken( + String id, + long version, + String subscriptionType, + String userName, + String appId, + String deviceId, + long subscriptionDate) { + this.id = id; + this.version = version; + this.subscriptionType = subscriptionType; + this.userName = userName; + this.appId = appId; + this.deviceId = deviceId; + this.subscriptionDate = subscriptionDate; + } + + public void setType(String type) { + type = type; + } +} diff --git a/src/test/java/org/springframework/data/couchbase/domain/SubscriptionTokenRepository.java b/src/test/java/org/springframework/data/couchbase/domain/SubscriptionTokenRepository.java new file mode 100644 index 00000000..b4ba58b4 --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/domain/SubscriptionTokenRepository.java @@ -0,0 +1,29 @@ +/* + * Copyright 2020 the original author or authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.couchbase.domain; + +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Repository; + +/** + * SubscriptionToken Repository for tests + * + * @author Michael Reiche + */ +@Repository +public interface SubscriptionTokenRepository extends PagingAndSortingRepository { +} 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 232f7aee..0d3db0f3 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java @@ -24,14 +24,18 @@ import java.util.List; import java.util.Optional; import java.util.UUID; +import com.couchbase.client.java.kv.GetResult; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; +import org.springframework.data.couchbase.core.CouchbaseTemplate; import org.springframework.data.couchbase.domain.Course; import org.springframework.data.couchbase.domain.Library; import org.springframework.data.couchbase.domain.LibraryRepository; import org.springframework.data.couchbase.domain.Submission; +import org.springframework.data.couchbase.domain.SubscriptionToken; +import org.springframework.data.couchbase.domain.SubscriptionTokenRepository; import org.springframework.data.couchbase.domain.User; import org.springframework.data.couchbase.domain.UserRepository; import org.springframework.data.couchbase.domain.UserSubmission; @@ -54,7 +58,20 @@ public class CouchbaseRepositoryKeyValueIntegrationTests extends ClusterAwareInt @Autowired UserRepository userRepository; @Autowired LibraryRepository libraryRepository; + @Autowired SubscriptionTokenRepository subscriptionTokenRepository; @Autowired UserSubmissionRepository userSubmissionRepository; + @Autowired CouchbaseTemplate couchbaseTemplate; + + @Test + void subscriptionToken() { + SubscriptionToken st = new SubscriptionToken("id", 0, "type", "Dave Smith", "app123", "dev123", 0); + st = subscriptionTokenRepository.save(st); + st = subscriptionTokenRepository.findById(st.getId()).get(); + + GetResult jdkResult = couchbaseTemplate.getCouchbaseClientFactory().getDefaultCollection().get(st.getId()); + assertNotEquals(0, st.getVersion()); + assertEquals(jdkResult.cas(), st.getVersion()); + } @Test @IgnoreWhen(clusterTypes = ClusterType.MOCKED)