diff --git a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java index eb646be21..a09ba5be7 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java @@ -16,6 +16,7 @@ package org.springframework.data.elasticsearch.core; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.springframework.data.annotation.Transient; import org.springframework.data.elasticsearch.annotations.*; import org.springframework.data.elasticsearch.core.facet.FacetRequest; import org.springframework.data.elasticsearch.core.geo.GeoPoint; @@ -72,6 +73,11 @@ class MappingBuilder { } for (java.lang.reflect.Field field : fields) { + + if (field.isAnnotationPresent(Transient.class)) { + continue; + } + if (isEntity(field) && !isInIgnoreFields(field)) { mapEntity(xContentBuilder, field.getType(), false, EMPTY, field.getName()); } diff --git a/src/test/java/org/springframework/data/elasticsearch/SampleTransientEntity.java b/src/test/java/org/springframework/data/elasticsearch/SampleTransientEntity.java new file mode 100644 index 000000000..994eefcfd --- /dev/null +++ b/src/test/java/org/springframework/data/elasticsearch/SampleTransientEntity.java @@ -0,0 +1,76 @@ +/* + * Copyright 2013 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.elasticsearch; + +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Transient; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; + +import static org.springframework.data.elasticsearch.annotations.FieldIndex.not_analyzed; +import static org.springframework.data.elasticsearch.annotations.FieldType.String; + +/** + * @author Jakub Vavrik + */ +@Document(indexName = "test-recursive-mapping", type = "mapping", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1") +public class SampleTransientEntity { + + @Id + private String id; + + @Field(type = String, index = not_analyzed, store = true, searchAnalyzer = "standard", indexAnalyzer = "standard") + private String message; + + @Transient + private NestedEntity nested; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + static class NestedEntity { + @Field + private static NestedEntity someField = new NestedEntity(); + @Field + private Boolean something; + + public NestedEntity getSomeField() { + return someField; + } + + public void setSomeField(NestedEntity someField) { + this.someField = someField; + } + + public Boolean getSomething() { return something; } + + public void setSomething(Boolean something) { this.something = something; } + } + +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/CircularObject.java b/src/test/java/org/springframework/data/elasticsearch/SimpleRecursiveEntity.java similarity index 79% rename from src/test/java/org/springframework/data/elasticsearch/core/CircularObject.java rename to src/test/java/org/springframework/data/elasticsearch/SimpleRecursiveEntity.java index 0438edbcd..8166d14a9 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/CircularObject.java +++ b/src/test/java/org/springframework/data/elasticsearch/SimpleRecursiveEntity.java @@ -1,4 +1,4 @@ -package org.springframework.data.elasticsearch.core; +package org.springframework.data.elasticsearch; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; @@ -9,10 +9,10 @@ import org.springframework.data.elasticsearch.annotations.FieldType; * @author Stuart Stevenson */ @Document(indexName = "circular-objects", type = "circular-object" , indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1") -public class CircularObject { +public class SimpleRecursiveEntity { @Id private String id; @Field(type = FieldType.Object, ignoreFields = {"circularObject"}) - private CircularObject circularObject; + private SimpleRecursiveEntity circularObject; } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java b/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java index b8bb1a1d0..9727969b6 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java @@ -1,13 +1,22 @@ package org.springframework.data.elasticsearch.core; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.SampleTransientEntity; +import org.springframework.data.elasticsearch.SimpleRecursiveEntity; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import java.io.IOException; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + /** * @author Stuart Stevenson + * @author Jakub Vavrik */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:elasticsearch-template-test.xml") @@ -18,8 +27,18 @@ public class MappingBuilderTests { @Test public void shouldNotFailOnCircularReference() { - elasticsearchTemplate.createIndex(CircularObject.class); - elasticsearchTemplate.putMapping(CircularObject.class); + elasticsearchTemplate.createIndex(SimpleRecursiveEntity.class); + elasticsearchTemplate.putMapping(SimpleRecursiveEntity.class); + } + + @Test + public void testInfiniteLoopAvoidance() throws IOException { + final String expected = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true,\"" + + "type\":\"string\",\"index\":\"not_analyzed\",\"search_analyzer\":\"standard\"," + + "\"index_analyzer\":\"standard\"}}}}"; + + XContentBuilder xContentBuilder = MappingBuilder.buildMapping(SampleTransientEntity.class, "mapping", "id"); + assertThat(xContentBuilder.string(), is(expected)); } }