diff --git a/src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java b/src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java index e8917f4f..e28920ea 100644 --- a/src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java +++ b/src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java @@ -23,6 +23,8 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import com.couchbase.client.java.repository.annotation.Field; + import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.CollectionFactory; @@ -61,6 +63,7 @@ import org.springframework.util.CollectionUtils; * * @author Michael Nitschinger * @author Oliver Gierke + * @author Geoffrey Mina */ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implements ApplicationContextAware { @@ -99,6 +102,11 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter */ private final SpELContext spELContext; + /** + * Enable strict @Field checking on mapper + */ + private boolean enableStrictFieldChecking = false; + /** * Create a new {@link MappingCouchbaseConverter}. * @@ -135,6 +143,20 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter return typeMapper.getTypeKey(); } + /** + * Toggles strict checking of the couchbase {@link Field} annotation. If enabled, + * strict checking will prevent non-annotated properties to be serialized. This only + * applies to the Couchbase datastore, allowing other Spring Data datastores to still + * deal with the property. + * + * @param enableStrictFieldChecking true to only consider Field-annotated properties for + * Couchbase serialization. + * @see DATACOUCH-226 + */ + public void setEnableStrictFieldChecking(boolean enableStrictFieldChecking){ + this.enableStrictFieldChecking = enableStrictFieldChecking; + } + @Override public R read(final Class clazz, final CouchbaseDocument source) { return read(ClassTypeInformation.from(clazz), source, null); @@ -434,6 +456,8 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter public void doWithPersistentProperty(final CouchbasePersistentProperty prop) { if (prop.equals(idProperty) || (versionProperty != null && prop.equals(versionProperty))) { return; + } else if(enableStrictFieldChecking && !prop.isAnnotationPresent(Field.class)){ + return; } Object propertyObj = accessor.getProperty(prop, prop.getType()); diff --git a/src/test/java/org/springframework/data/couchbase/core/mapping/MappingCouchbaseConverterTests.java b/src/test/java/org/springframework/data/couchbase/core/mapping/MappingCouchbaseConverterTests.java index 4912c3fd..c4c9d5cd 100644 --- a/src/test/java/org/springframework/data/couchbase/core/mapping/MappingCouchbaseConverterTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/mapping/MappingCouchbaseConverterTests.java @@ -33,6 +33,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import com.couchbase.client.java.repository.annotation.Field; import org.joda.time.LocalDateTime; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,6 +52,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Michael Nitschinger + * @author Geoffrey Mina */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = UnitTestApplicationConfig.class) @@ -501,6 +503,41 @@ public class MappingCouchbaseConverterTests { assertEquals("springId", converted.getId()); } + @Test + public void testStrictFieldCheckingIgnoresUnannotated() throws Exception{ + try { + CouchbaseDocument converted = new CouchbaseDocument(); + AnnotatedEntity entity = new AnnotatedEntity(); + + converter.setEnableStrictFieldChecking(true); + converter.write(entity,converted); + + assertTrue(converted.getId() != null); + assertTrue(converted.getPayload().containsKey("annotatedField")); + assertFalse(converted.getPayload().containsKey("nonAnnotatedField")); + } finally { + converter.setEnableStrictFieldChecking(false); + } + } + + @Test + public void testLenientFieldCheckingStoresUnannotated() throws Exception{ + try { + CouchbaseDocument converted = new CouchbaseDocument(); + AnnotatedEntity entity = new AnnotatedEntity(); + + converter.setEnableStrictFieldChecking(false); + converter.write(entity,converted); + + assertTrue(converted.getId() != null); + assertTrue(converted.getPayload().containsKey("annotatedField")); + assertTrue(converted.getPayload().containsKey("nonAnnotatedField")); + } finally { + converter.setEnableStrictFieldChecking(false); + } + } + + static class EntityWithoutID { private String attr0; @@ -648,6 +685,20 @@ public class MappingCouchbaseConverterTests { } } + static class AnnotatedEntity{ + @Id private String uuid; + @Field private String annotatedField; + private String nonAnnotatedField; + + public AnnotatedEntity(){ + this.uuid = java.util.UUID.randomUUID().toString(); + this.annotatedField = "Annotated Property"; + this.nonAnnotatedField = "Non Annotated Property"; + } + } + + + @WritingConverter public static enum BigDecimalToStringConverter implements Converter { INSTANCE;