Skip to content

Commit 0ac1b4a

Browse files
authored
Allow CustomConversions for entities.
Original PullRequest #1672 Closes #1667
1 parent e8edd60 commit 0ac1b4a

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed

src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchMappingContext.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public void setFieldNamingStrategy(@Nullable FieldNamingStrategy fieldNamingStra
5050
this.fieldNamingStrategy = fieldNamingStrategy == null ? DEFAULT_NAMING_STRATEGY : fieldNamingStrategy;
5151
}
5252

53+
@Override
54+
protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
55+
return !ElasticsearchSimpleTypes.HOLDER.isSimpleType(type.getType());
56+
}
57+
5358
@Override
5459
protected <T> SimpleElasticsearchPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
5560
return new SimpleElasticsearchPersistentEntity<>(typeInformation);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.elasticsearch.core.mapping;
17+
18+
import static org.assertj.core.api.Assertions.*;
19+
20+
import lombok.AllArgsConstructor;
21+
import lombok.Builder;
22+
import lombok.Data;
23+
import lombok.NoArgsConstructor;
24+
25+
import java.util.Arrays;
26+
import java.util.LinkedHashMap;
27+
import java.util.Map;
28+
29+
import org.junit.jupiter.api.AfterEach;
30+
import org.junit.jupiter.api.BeforeEach;
31+
import org.junit.jupiter.api.DisplayName;
32+
import org.junit.jupiter.api.Test;
33+
import org.springframework.beans.factory.annotation.Autowired;
34+
import org.springframework.context.annotation.Configuration;
35+
import org.springframework.core.convert.converter.Converter;
36+
import org.springframework.data.convert.ReadingConverter;
37+
import org.springframework.data.convert.WritingConverter;
38+
import org.springframework.data.elasticsearch.annotations.Document;
39+
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
40+
import org.springframework.data.elasticsearch.core.IndexOperations;
41+
import org.springframework.data.elasticsearch.core.SearchHits;
42+
import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions;
43+
import org.springframework.data.elasticsearch.core.geo.GeoJsonPoint;
44+
import org.springframework.data.elasticsearch.core.query.Query;
45+
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
46+
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
47+
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
48+
import org.springframework.test.context.ContextConfiguration;
49+
50+
/**
51+
* Test that a whole entity can be converted using custom conversions
52+
*
53+
* @author Peter-Josef Meisch
54+
*/
55+
@SpringIntegrationTest
56+
@ContextConfiguration(classes = { EntityCustomConversionIntegrationTests.Config.class })
57+
public class EntityCustomConversionIntegrationTests {
58+
59+
@Configuration
60+
@EnableElasticsearchRepositories(basePackages = { "org.springframework.data.elasticsearch.core.mapping" },
61+
considerNestedRepositories = true)
62+
static class Config extends ElasticsearchRestTemplateConfiguration {
63+
@Override
64+
public ElasticsearchCustomConversions elasticsearchCustomConversions() {
65+
return new ElasticsearchCustomConversions(Arrays.asList(new EntityToMapConverter(), new MapToEntityConverter()));
66+
}
67+
}
68+
69+
@Autowired private ElasticsearchOperations operations;
70+
71+
@BeforeEach
72+
void setUp() {
73+
IndexOperations indexOps = operations.indexOps(Entity.class);
74+
indexOps.create();
75+
indexOps.putMapping();
76+
}
77+
78+
@AfterEach
79+
void tearDown() {
80+
operations.indexOps(Entity.class).delete();
81+
}
82+
83+
@Test // #1667
84+
@DisplayName("should use CustomConversions on entity")
85+
void shouldUseCustomConversionsOnEntity() {
86+
87+
Entity entity = Entity.builder() //
88+
.value("hello") //
89+
.location(GeoJsonPoint.of(8.0, 42.7)) //
90+
.build();
91+
92+
org.springframework.data.elasticsearch.core.document.Document document = org.springframework.data.elasticsearch.core.document.Document
93+
.create();
94+
operations.getElasticsearchConverter().write(entity, document);
95+
96+
assertThat(document.getString("the_value")).isEqualTo("hello");
97+
assertThat(document.getString("the_lon")).isEqualTo("8.0");
98+
assertThat(document.getString("the_lat")).isEqualTo("42.7");
99+
}
100+
101+
@Test // #1667
102+
@DisplayName("should store and load entity from Elasticsearch")
103+
void shouldStoreAndLoadEntityFromElasticsearch() {
104+
105+
Entity entity = Entity.builder() //
106+
.value("hello") //
107+
.location(GeoJsonPoint.of(8.0, 42.7)) //
108+
.build();
109+
110+
Entity savedEntity = operations.save(entity);
111+
112+
SearchHits<Entity> searchHits = operations.search(Query.findAll(), Entity.class);
113+
assertThat(searchHits.getTotalHits()).isEqualTo(1);
114+
Entity foundEntity = searchHits.getSearchHit(0).getContent();
115+
assertThat(foundEntity).isEqualTo(entity);
116+
}
117+
118+
@Data
119+
@Builder
120+
@NoArgsConstructor
121+
@AllArgsConstructor
122+
@Document(indexName = "entity-with-custom-conversions")
123+
static class Entity {
124+
private String value;
125+
private GeoJsonPoint location;
126+
}
127+
128+
@WritingConverter
129+
static class EntityToMapConverter implements Converter<Entity, Map<String, Object>> {
130+
@Override
131+
public Map<String, Object> convert(Entity source) {
132+
LinkedHashMap<String, Object> target = new LinkedHashMap<>();
133+
target.put("the_value", source.getValue());
134+
target.put("the_lat", "" + source.getLocation().getY());
135+
target.put("the_lon", "" + source.getLocation().getX());
136+
return target;
137+
}
138+
}
139+
140+
@ReadingConverter
141+
static class MapToEntityConverter implements Converter<Map<String, Object>, Entity> {
142+
143+
@Override
144+
public Entity convert(Map<String, Object> source) {
145+
Entity entity = new Entity();
146+
entity.setValue((String) source.get("the_value"));
147+
entity.setLocation(GeoJsonPoint.of( //
148+
Double.parseDouble((String) (source.get("the_lon"))), //
149+
Double.parseDouble((String) (source.get("the_lat"))) //
150+
));
151+
return entity;
152+
}
153+
}
154+
}

0 commit comments

Comments
 (0)