diff --git a/pom.xml b/pom.xml
index 1d9b760700..4b6a149317 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.9.0.BUILD-SNAPSHOT
+ 1.9.0.DATAMONGO-1373-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-cross-store/pom.xml b/spring-data-mongodb-cross-store/pom.xml
index fd36debedd..85c49dd5db 100644
--- a/spring-data-mongodb-cross-store/pom.xml
+++ b/spring-data-mongodb-cross-store/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.9.0.BUILD-SNAPSHOT
+ 1.9.0.DATAMONGO-1373-SNAPSHOT
../pom.xml
@@ -48,7 +48,7 @@
org.springframework.data
spring-data-mongodb
- 1.9.0.BUILD-SNAPSHOT
+ 1.9.0.DATAMONGO-1373-SNAPSHOT
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index 28c91bc332..4e8ae3941a 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -13,7 +13,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.9.0.BUILD-SNAPSHOT
+ 1.9.0.DATAMONGO-1373-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-log4j/pom.xml b/spring-data-mongodb-log4j/pom.xml
index dfe146ff96..424cb4e52b 100644
--- a/spring-data-mongodb-log4j/pom.xml
+++ b/spring-data-mongodb-log4j/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.9.0.BUILD-SNAPSHOT
+ 1.9.0.DATAMONGO-1373-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 0fcdb2f39f..7b008f84d7 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -11,7 +11,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.9.0.BUILD-SNAPSHOT
+ 1.9.0.DATAMONGO-1373-SNAPSHOT
../pom.xml
@@ -19,6 +19,7 @@
1.0.0.GA
1.3
1.5
+ 1.12.0.DATACMNS-825-SNAPSHOT
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java
index 119066877e..fd5c878787 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2015 the original author or authors.
+ * Copyright 2010-2016 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.
@@ -27,8 +27,9 @@
* @author Laurent Canet
* @author Thomas Darimont
* @author Christoph Strobl
+ * @author Mark Paluch
*/
-@Target(ElementType.FIELD)
+@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface GeoSpatialIndexed {
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java
index 9348aacd43..4f8fd83df1 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -26,10 +26,11 @@
* all fields marked with {@link TextIndexed} are combined into one single index.
*
* @author Christoph Strobl
+ * @author Mark Paluch
* @since 1.6
*/
@Documented
-@Target({ ElementType.FIELD })
+@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface TextIndexed {
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java
index d182a9460a..a1196fca46 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java
@@ -26,7 +26,6 @@
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
-import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
@@ -78,7 +77,7 @@ public BasicMongoPersistentEntity(TypeInformation typeInformation) {
Class> rawType = typeInformation.getType();
String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);
- Document document = AnnotationUtils.findAnnotation(rawType, Document.class);
+ Document document = this.findAnnotation(Document.class);
this.expression = detectExpression(document);
this.context = new StandardEvaluationContext();
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java
index 173aaa25b4..33d1eada88 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2011-2015 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
+ *
+ * http://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.mongodb.core.mapping;
import java.lang.annotation.Documented;
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java
index 9fe6c7cc7d..a24503b5ce 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -25,10 +25,11 @@
/**
* @author Christoph Strobl
+ * @author Mark Paluch
* @since 1.6
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Documented
@QueryAnnotation
public @interface Meta {
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java
index f79df312c6..8870ef3a61 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2014 the original author or authors.
+ * Copyright 2011-2016 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.
@@ -30,9 +30,10 @@
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
+ * @author Mark Paluch
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Documented
@QueryAnnotation
public @interface Query {
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java
index 85f0805f5c..afbecf83d3 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2015 the original author or authors.
+ * Copyright 2011-2016 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.
@@ -20,6 +20,7 @@
import java.util.Arrays;
import java.util.List;
+import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.geo.GeoPage;
import org.springframework.data.geo.GeoResult;
@@ -43,6 +44,7 @@
*
* @author Oliver Gierke
* @author Christoph Strobl
+ * @author Mark Paluch
*/
public class MongoQueryMethod extends QueryMethod {
@@ -191,7 +193,7 @@ private boolean isGeoNearQuery(Method method) {
* @return
*/
Query getQueryAnnotation() {
- return method.getAnnotation(Query.class);
+ return AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
}
TypeInformation> getReturnType() {
@@ -213,7 +215,7 @@ public boolean hasQueryMetaAttributes() {
* @since 1.6
*/
Meta getMetaAnnotation() {
- return method.getAnnotation(Meta.class);
+ return AnnotatedElementUtils.findMergedAnnotation(method, Meta.class);
}
/**
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java
index 4768db366f..ecfa60e042 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2015 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -18,6 +18,7 @@
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
+import static org.springframework.data.mongodb.test.util.IsBsonObject.isBsonObject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -30,6 +31,7 @@
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
+import org.springframework.core.annotation.AliasFor;
import org.springframework.data.annotation.Id;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.DBObjectTestUtils;
@@ -54,6 +56,7 @@
/**
* @author Christoph Strobl
+ * @author Mark Paluch
*/
@RunWith(Suite.class)
@SuiteClasses({ IndexResolutionTests.class, GeoSpatialIndexResolutionTests.class, CompoundIndexResolutionTests.class,
@@ -195,6 +198,42 @@ public void resolveIndexDefinitionInMetaAnnotatedFields() {
assertThat(indexDefinitions.get(0).getIndexOptions(),
equalTo(new BasicDBObjectBuilder().add("name", "_name").get()));
}
+
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void resolveIndexDefinitionInComposedAnnotatedFields() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(
+ IndexedDocumentWithComposedAnnotations.class);
+
+ assertThat(indexDefinitions, hasSize(2));
+
+ IndexDefinitionHolder indexDefinitionHolder = indexDefinitions.get(1);
+
+ assertThat(indexDefinitionHolder.getIndexKeys(), isBsonObject().containing("fieldWithMyIndexName", 1));
+ assertThat(indexDefinitionHolder.getIndexOptions(),
+ isBsonObject().containing("sparse", true).containing("unique", true).containing("name", "my_index_name"));
+ }
+
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void resolveIndexDefinitionInCustomComposedAnnotatedFields() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(
+ IndexedDocumentWithComposedAnnotations.class);
+
+ assertThat(indexDefinitions, hasSize(2));
+
+ IndexDefinitionHolder indexDefinitionHolder = indexDefinitions.get(0);
+
+ assertThat(indexDefinitionHolder.getIndexKeys(), isBsonObject().containing("fieldWithDifferentIndexName", 1));
+ assertThat(indexDefinitionHolder.getIndexOptions(),
+ isBsonObject().containing("sparse", true).containing("name", "different_name").notContaining("unique"));
+ }
@Document(collection = "Zero")
static class IndexOnLevelZero {
@@ -247,6 +286,44 @@ static class WithDbRef {
static class NoIndex {
@Id String id;
}
+
+ @Document
+ static class IndexedDocumentWithComposedAnnotations {
+
+ @Id String id;
+ @CustomIndexedAnnotation String fieldWithDifferentIndexName;
+ @ComposedIndexedAnnotation String fieldWithMyIndexName;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.FIELD })
+ @ComposedIndexedAnnotation(indexName = "different_name", beUnique = false)
+ static @interface CustomIndexedAnnotation {
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
+ @Indexed
+ static @interface ComposedIndexedAnnotation {
+
+ @AliasFor(annotation = Indexed.class, attribute = "unique")
+ boolean beUnique() default true;
+
+ @AliasFor(annotation = Indexed.class, attribute = "sparse")
+ boolean beSparse() default true;
+
+ @AliasFor(annotation = Indexed.class, attribute = "name")
+ String indexName() default "my_index_name";
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.FIELD)
+ @org.springframework.data.mongodb.core.mapping.Field
+ static @interface ComposedFieldAnnotation {
+
+ @AliasFor(annotation = org.springframework.data.mongodb.core.mapping.Field.class, attribute = "value")
+ String name() default "_id";
+ }
}
@@ -319,6 +396,24 @@ public void resolvesIndexDefinitionOptionsCorrectly() {
indexDefinition.getIndexOptions(),
equalTo(new BasicDBObjectBuilder().add("name", "location").add("min", 1).add("max", 100).add("bits", 2).get()));
}
+
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void resolvesComposedAnnotationIndexDefinitionOptionsCorrectly() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(GeoSpatialIndexedDocumentWithComposedAnnotation.class);
+
+ IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
+
+ assertThat(
+ indexDefinition.getIndexKeys(),
+ isBsonObject().containing("location", "geoHaystack").containing("What light?", 1));
+ assertThat(
+ indexDefinition.getIndexOptions(),
+ isBsonObject().containing("name", "my_geo_index_name").containing("bucketSize", 2.0));
+ }
@Document(collection = "Zero")
static class GeoSpatialIndexOnLevelZero {
@@ -342,6 +437,31 @@ static class WithOptionsOnGeoSpatialIndexProperty {
type = GeoSpatialIndexType.GEO_2D)//
Point location;
}
+
+ @Document(collection = "WithComposedAnnotation")
+ static class GeoSpatialIndexedDocumentWithComposedAnnotation {
+
+ @ComposedGeoSpatialIndexed//
+ Point location;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.FIELD })
+ @GeoSpatialIndexed
+ @interface ComposedGeoSpatialIndexed {
+
+ @AliasFor(annotation = GeoSpatialIndexed.class, attribute = "name")
+ String indexName() default "my_geo_index_name";
+
+ @AliasFor(annotation = GeoSpatialIndexed.class, attribute = "additionalField")
+ String theAdditionalFieldINeedToDefine() default "What light?";
+
+ @AliasFor(annotation = GeoSpatialIndexed.class, attribute = "bucketSize")
+ double size() default 2;
+
+ @AliasFor(annotation = GeoSpatialIndexed.class, attribute = "type")
+ GeoSpatialIndexType indexType() default GeoSpatialIndexType.GEO_HAYSTACK;
+ }
}
@@ -445,6 +565,20 @@ public void singleCompoundIndexPathOnLevelZeroIsResolvedCorrectly() {
assertThat(indexDefinitions, hasSize(1));
assertIndexPathAndCollection(new String[] { "foo", "bar" }, "CompoundIndexOnLevelZero", indexDefinitions.get(0));
}
+
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void singleCompoundIndexUsingComposedAnnotationsOnTypeResolvedCorrectly() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(CompoundIndexDocumentWithComposedAnnotation.class);
+
+ assertThat(indexDefinitions, hasSize(1));
+ assertThat(indexDefinitions.get(0).getIndexKeys(), isBsonObject().containing("foo", 1).containing("bar", -1));
+ assertThat(indexDefinitions.get(0).getIndexOptions(), isBsonObject().containing("name", "my_compound_index_name").
+ containing("unique", true).containing("background", true));
+ }
@Document(collection = "CompoundIndexOnLevelOne")
static class CompoundIndexOnLevelOne {
@@ -482,6 +616,34 @@ static class IndexDefinedOnSuperClass extends CompoundIndexOnLevelZero {
static class ComountIndexWithAutogeneratedName {
}
+
+ @Document(collection = "WithComposedAnnotation")
+ @ComposedCompoundIndex
+ static class CompoundIndexDocumentWithComposedAnnotation {
+
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.TYPE })
+ @CompoundIndex
+ @interface ComposedCompoundIndex {
+
+ @AliasFor(annotation = CompoundIndex.class, attribute = "def")
+ String fields() default "{'foo': 1, 'bar': -1}";
+
+ @AliasFor(annotation = CompoundIndex.class, attribute = "background")
+ boolean inBackground() default true;
+
+ @AliasFor(annotation = CompoundIndex.class, attribute = "name")
+ String indexName() default "my_compound_index_name";
+
+ @AliasFor(annotation = CompoundIndex.class, attribute = "useGeneratedName")
+ boolean useGeneratedName() default false;
+
+ @AliasFor(annotation = CompoundIndex.class, attribute = "unique")
+ boolean isUnique() default true;
+
+ }
}
@@ -611,6 +773,18 @@ public void shouldPreferExplicitlyAnnotatedLanguageProperty() {
List indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithOverlappingLanguageProps.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("language_override"), is((Object) "lang"));
}
+
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void shouldResolveComposedAnnotationCorrectly() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(TextIndexedDocumentWithComposedAnnotation.class);
+
+ DBObject weights = DBObjectTestUtils.getAsDBObject(indexDefinitions.get(0).getIndexOptions(), "weights");
+ assertThat(weights, isBsonObject().containing("foo", 99f));
+ }
@Document
static class TextIndexOnSinglePropertyInRoot {
@@ -696,6 +870,22 @@ static class DocumentWithOverlappingLanguageProps {
String language;
@Language String lang;
}
+
+ @Document
+ static class TextIndexedDocumentWithComposedAnnotation {
+
+ @ComposedTextIndexedAnnotation String foo;
+ String lang;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
+ @TextIndexed
+ static @interface ComposedTextIndexedAnnotation {
+
+ @AliasFor(annotation = TextIndexed.class, attribute = "weight")
+ float heavyweight() default 99f;
+ }
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java
index a420c24d85..458b0fd4b6 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2014 by the original author(s).
+ * Copyright 2011-2016 by the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.context.ApplicationContext;
+import org.springframework.core.annotation.AliasFor;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.util.ClassTypeInformation;
@@ -243,6 +244,18 @@ public void metaInformationShouldBeReadCorrectlyFromInheritedDocumentAnnotation(
assertThat(entity.getCollection(), is("collection-1"));
}
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void metaInformationShouldBeReadCorrectlyFromComposedDocumentAnnotation() {
+
+ BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity(
+ ClassTypeInformation.from(DocumentWithComposedAnnotation.class));
+
+ assertThat(entity.getCollection(), is("custom-collection"));
+ }
+
@Document(collection = "contacts")
class Contact {
@@ -284,9 +297,23 @@ static class DocumentWithCustomAnnotation {
}
+ @ComposedDocumentAnnotation
+ static class DocumentWithComposedAnnotation {
+
+ }
+
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
@Document(collection = "collection-1")
static @interface CustomDocumentAnnotation {
}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.TYPE })
+ @Document
+ static @interface ComposedDocumentAnnotation {
+
+ @AliasFor(annotation = Document.class, attribute = "collection")
+ String name() default "custom-collection";
+ }
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java
index 0dc781df1a..e2c64260c7 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2014 by the original author(s).
+ * Copyright 2011-2016 by the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,10 @@
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.Locale;
@@ -25,6 +29,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.springframework.core.annotation.AliasFor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.model.FieldNamingStrategy;
@@ -39,6 +44,7 @@
*
* @author Oliver Gierke
* @author Christoph Strobl
+ * @author Mark Paluch
*/
public class BasicMongoPersistentPropertyUnitTests {
@@ -184,6 +190,29 @@ public void shouldConsiderPropertyAsIdWhenExplicitlyAnnotatedWithIdEvenWhenExpli
"id");
assertThat(property.isIdProperty(), is(true));
}
+
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void shouldConsiderComposedAnnotationsForIdField() {
+
+ MongoPersistentProperty property = getPropertyFor(DocumentWithComposedAnnotations.class,
+ "myId");
+ assertThat(property.isIdProperty(), is(true));
+ assertThat(property.getFieldName(), is("_id"));
+ }
+
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void shouldConsiderComposedAnnotationsForFields() {
+
+ MongoPersistentProperty property = getPropertyFor(DocumentWithComposedAnnotations.class,
+ "myField");
+ assertThat(property.getFieldName(), is("myField"));
+ }
private MongoPersistentProperty getPropertyFor(Field field) {
return getPropertyFor(entity, field);
@@ -253,4 +282,25 @@ static class DocumentWithExplicitlyRenamedIdPropertyHavingIdAnnotation {
@Id @org.springframework.data.mongodb.core.mapping.Field("id") String id;
}
+
+ static class DocumentWithComposedAnnotations {
+
+ @ComposedIdAnnotation @ComposedFieldAnnotation String myId;
+ @ComposedFieldAnnotation(name = "myField") String myField;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.FIELD)
+ @org.springframework.data.mongodb.core.mapping.Field
+ static @interface ComposedFieldAnnotation {
+
+ @AliasFor(annotation = org.springframework.data.mongodb.core.mapping.Field.class, attribute = "value")
+ String name() default "_id";
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.FIELD)
+ @Id
+ static @interface ComposedIdAnnotation { }
+
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java
index 17ab38b47e..011333c24a 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java
@@ -18,6 +18,7 @@
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -129,4 +130,27 @@ public void findAllShouldWorkWhenUsingComplexId() {
assertThat(loaded, is(Matchers. iterableWithSize(1)));
assertThat(loaded, contains(userWithId));
}
+
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void composedAnnotationFindQueryShouldWorkWhenUsingComplexId() {
+
+ repo.save(userWithId);
+
+ assertThat(repo.getUserUsingComposedAnnotationByComplexId(id), is(userWithId));
+ }
+
+ /**
+ * @see DATAMONGO-1373
+ */
+ @Test
+ public void composedAnnotationFindMetaShouldWorkWhenUsingComplexId() {
+
+ repo.save(userWithId);
+
+ assertThat(repo.findUsersUsingComposedMetaAnnotationByUserIds(Arrays.asList(id)), hasSize(0));
+ }
+
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java
index 880edd7a11..dca1abab19 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java
@@ -15,9 +15,15 @@
*/
package org.springframework.data.mongodb.repository;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
import java.util.Collection;
import java.util.List;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.repository.CrudRepository;
/**
@@ -30,4 +36,31 @@ public interface UserWithComplexIdRepository extends CrudRepository findUsersUsingComposedMetaAnnotationByUserIds(Collection ids);
+
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.METHOD })
+ @Document
+ @Query
+ @interface ComposedQueryAnnotation {
+
+ @AliasFor(annotation = Query.class, attribute = "value")
+ String myQuery() default "{'_id': ?0}";
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.METHOD })
+ @Meta
+ @interface ComposedMetaAnnotation {
+
+ @AliasFor(annotation = Meta.class, attribute = "maxScanDocuments")
+ long scanDocuments() default 1;
+ }
}
diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc
index 0517b60d0e..e1d8c61dc5 100644
--- a/src/main/asciidoc/new-features.adoc
+++ b/src/main/asciidoc/new-features.adoc
@@ -1,6 +1,11 @@
[[new-features]]
= New & Noteworthy
+[[new-features.1-9-0]]
+== What's new in Spring Data MongoDB 1.9
+* The following annotations have been enabled to build own, composed annotations: `@Document`, `@Id`, `@Field`, `@Indexed`, `@CompoundIndex`, `@GeoSpatialIndexed`, `@TextIndexed`, `@Query`, `@Meta`.
+
+
[[new-features.1-8-0]]
== What's new in Spring Data MongoDB 1.8