mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-10-31 22:59:01 +00:00
Add SpEL support for settingPath in @Settings annotation.
Original Pull Request #3188 Closes #3187 Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
This commit is contained in:
parent
b552128198
commit
21bc62b78c
@ -4,10 +4,11 @@
|
||||
[[new-features.6-0-0]]
|
||||
== New in Spring Data Elasticsearch 6.0
|
||||
|
||||
* Upgarde to Spring 7
|
||||
* Upgrade to Spring 7
|
||||
* Switch to jspecify nullability annotations
|
||||
* Upgrade to Elasticsearch 9.1.5
|
||||
* Use the new Elasticsearch Rest5Client as default
|
||||
* Add support for SpEL expressions in the `settingPath` parameter of the `@Setting` annotation
|
||||
|
||||
|
||||
[[new-features.5-5-0]]
|
||||
|
||||
@ -47,6 +47,7 @@ import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionException;
|
||||
import org.springframework.expression.ParserContext;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
@ -298,7 +299,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
Assert.notNull(fieldName, "fieldName must not be null");
|
||||
|
||||
return fieldNamePropertyCache.computeIfAbsent(fieldName, key -> {
|
||||
AtomicReference<ElasticsearchPersistentProperty> propertyRef = new AtomicReference<>();
|
||||
AtomicReference<@Nullable ElasticsearchPersistentProperty> propertyRef = new AtomicReference<>();
|
||||
doWithProperties((PropertyHandler<@NonNull ElasticsearchPersistentProperty>) property -> {
|
||||
if (key.equals(property.getFieldName())) {
|
||||
propertyRef.set(property);
|
||||
@ -423,9 +424,9 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
|
||||
try {
|
||||
Expression expression = routingExpressions.computeIfAbsent(routing, PARSER::parseExpression);
|
||||
ExpressionDependencies expressionDependencies = ExpressionDependencies.discover(expression);
|
||||
ExpressionDependencies expressionDependencies = expression != null ? ExpressionDependencies.discover(expression)
|
||||
: ExpressionDependencies.none();
|
||||
|
||||
// noinspection ConstantConditions
|
||||
EvaluationContext context = getEvaluationContext(null, expressionDependencies);
|
||||
context.setVariable("entity", bean);
|
||||
|
||||
@ -440,8 +441,20 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
|
||||
// region index settings
|
||||
@Override
|
||||
public String settingPath() {
|
||||
return settingsParameter.get().settingPath;
|
||||
public @Nullable String settingPath() {
|
||||
String settingPathFromParameter = settingsParameter.get().settingPath;
|
||||
if (settingPathFromParameter == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
Expression expression = PARSER.parseExpression(settingPathFromParameter, ParserContext.TEMPLATE_EXPRESSION);
|
||||
return (expression instanceof LiteralExpression) ? settingPathFromParameter
|
||||
: expression.getValue(getEvaluationContext(null, ExpressionDependencies.discover(expression)), String.class);
|
||||
} catch (ExpressionException e) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Could not resolve expression: " + settingPathFromParameter + " for @Setting.settingPath ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -84,7 +84,7 @@ public class QueryStringSpELEvaluator {
|
||||
|
||||
if (expr != null) {
|
||||
EvaluationContext context = evaluationContextProvider.getEvaluationContext(parameterAccessor.getValues())
|
||||
.getRequiredEvaluationContext();
|
||||
.getEvaluationContext();
|
||||
|
||||
if (context instanceof StandardEvaluationContext standardEvaluationContext) {
|
||||
standardEvaluationContext.setTypeConverter(elasticsearchSpELTypeConverter);
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchTemplateConfiguration;
|
||||
|
||||
public class IndexSettingsELCIntegrationTests extends IndexSettingsIntegrationTests {
|
||||
@Configuration
|
||||
@Import({ ElasticsearchTemplateConfiguration.class })
|
||||
static class Config {
|
||||
@Bean
|
||||
public SpelSettingPath spelSettingPath() {
|
||||
return new SpelSettingPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
|
||||
/**
|
||||
* IndexSettings test that need an regular conext setup for SpEL resolution for example.
|
||||
*/
|
||||
@SpringIntegrationTest
|
||||
public abstract class IndexSettingsIntegrationTests {
|
||||
|
||||
@Autowired protected ElasticsearchOperations operations;
|
||||
|
||||
@Test // #3187
|
||||
@DisplayName("should evaluate SpEL expression in settingPath")
|
||||
void shouldEvaluateSpElExpressionInSettingPath() {
|
||||
|
||||
var settingPath = operations.getElasticsearchConverter().getMappingContext()
|
||||
.getRequiredPersistentEntity(SettingPathWithSpel.class).settingPath();
|
||||
|
||||
assertThat(settingPath).isEqualTo(SpelSettingPath.SETTING_PATH);
|
||||
}
|
||||
|
||||
protected static class SpelSettingPath {
|
||||
public static String SETTING_PATH = "test-setting-path";
|
||||
|
||||
public String settingPath() {
|
||||
return SETTING_PATH;
|
||||
}
|
||||
}
|
||||
|
||||
@Document(indexName = "foo")
|
||||
@Setting(settingPath = "#{@spelSettingPath.settingPath}")
|
||||
private static class SettingPathWithSpel {
|
||||
@Nullable
|
||||
@Id String id;
|
||||
}
|
||||
|
||||
}
|
||||
@ -19,10 +19,16 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import static org.skyscreamer.jsonassert.JSONAssert.*;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
@ -38,6 +44,7 @@ import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
@ -60,9 +67,9 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
@Test
|
||||
public void shouldThrowExceptionGivenVersionPropertyIsNotLong() {
|
||||
|
||||
TypeInformation<EntityWithWrongVersionType> typeInformation = TypeInformation
|
||||
TypeInformation<@NonNull EntityWithWrongVersionType> typeInformation = TypeInformation
|
||||
.of(EntityWithWrongVersionType.class);
|
||||
SimpleElasticsearchPersistentEntity<EntityWithWrongVersionType> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
SimpleElasticsearchPersistentEntity<@NonNull EntityWithWrongVersionType> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
typeInformation, contextConfiguration);
|
||||
|
||||
assertThatThrownBy(() -> createProperty(entity, "version")).isInstanceOf(MappingException.class);
|
||||
@ -71,9 +78,9 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
@Test
|
||||
public void shouldThrowExceptionGivenMultipleVersionPropertiesArePresent() {
|
||||
|
||||
TypeInformation<EntityWithMultipleVersionField> typeInformation = TypeInformation
|
||||
TypeInformation<@NonNull EntityWithMultipleVersionField> typeInformation = TypeInformation
|
||||
.of(EntityWithMultipleVersionField.class);
|
||||
SimpleElasticsearchPersistentEntity<EntityWithMultipleVersionField> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
SimpleElasticsearchPersistentEntity<@NonNull EntityWithMultipleVersionField> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
typeInformation, contextConfiguration);
|
||||
SimpleElasticsearchPersistentProperty persistentProperty1 = createProperty(entity, "version1");
|
||||
SimpleElasticsearchPersistentProperty persistentProperty2 = createProperty(entity, "version2");
|
||||
@ -100,9 +107,9 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
@Test
|
||||
// DATAES-799
|
||||
void shouldReportThatThereIsNoSeqNoPrimaryTermPropertyWhenThereIsNoSuchProperty() {
|
||||
TypeInformation<EntityWithoutSeqNoPrimaryTerm> typeInformation = TypeInformation
|
||||
TypeInformation<@NonNull EntityWithoutSeqNoPrimaryTerm> typeInformation = TypeInformation
|
||||
.of(EntityWithoutSeqNoPrimaryTerm.class);
|
||||
SimpleElasticsearchPersistentEntity<EntityWithoutSeqNoPrimaryTerm> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
SimpleElasticsearchPersistentEntity<@NonNull EntityWithoutSeqNoPrimaryTerm> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
typeInformation, contextConfiguration);
|
||||
|
||||
assertThat(entity.hasSeqNoPrimaryTermProperty()).isFalse();
|
||||
@ -111,9 +118,9 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
@Test
|
||||
// DATAES-799
|
||||
void shouldReportThatThereIsSeqNoPrimaryTermPropertyWhenThereIsSuchProperty() {
|
||||
TypeInformation<EntityWithSeqNoPrimaryTerm> typeInformation = TypeInformation
|
||||
TypeInformation<@NonNull EntityWithSeqNoPrimaryTerm> typeInformation = TypeInformation
|
||||
.of(EntityWithSeqNoPrimaryTerm.class);
|
||||
SimpleElasticsearchPersistentEntity<EntityWithSeqNoPrimaryTerm> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
SimpleElasticsearchPersistentEntity<@NonNull EntityWithSeqNoPrimaryTerm> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
typeInformation, contextConfiguration);
|
||||
|
||||
entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm"));
|
||||
@ -125,9 +132,9 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
// DATAES-799
|
||||
void shouldReturnSeqNoPrimaryTermPropertyWhenThereIsSuchProperty() {
|
||||
|
||||
TypeInformation<EntityWithSeqNoPrimaryTerm> typeInformation = TypeInformation
|
||||
TypeInformation<@NonNull EntityWithSeqNoPrimaryTerm> typeInformation = TypeInformation
|
||||
.of(EntityWithSeqNoPrimaryTerm.class);
|
||||
SimpleElasticsearchPersistentEntity<EntityWithSeqNoPrimaryTerm> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
SimpleElasticsearchPersistentEntity<@NonNull EntityWithSeqNoPrimaryTerm> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
typeInformation, contextConfiguration);
|
||||
entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm"));
|
||||
EntityWithSeqNoPrimaryTerm instance = new EntityWithSeqNoPrimaryTerm();
|
||||
@ -144,9 +151,9 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
@Test
|
||||
// DATAES-799
|
||||
void shouldNotAllowMoreThanOneSeqNoPrimaryTermProperties() {
|
||||
TypeInformation<EntityWithSeqNoPrimaryTerm> typeInformation = TypeInformation
|
||||
TypeInformation<@NonNull EntityWithSeqNoPrimaryTerm> typeInformation = TypeInformation
|
||||
.of(EntityWithSeqNoPrimaryTerm.class);
|
||||
SimpleElasticsearchPersistentEntity<EntityWithSeqNoPrimaryTerm> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
SimpleElasticsearchPersistentEntity<@NonNull EntityWithSeqNoPrimaryTerm> entity = new SimpleElasticsearchPersistentEntity<>(
|
||||
typeInformation, contextConfiguration);
|
||||
entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm"));
|
||||
|
||||
@ -164,7 +171,24 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
|
||||
@Nested
|
||||
@DisplayName("index settings")
|
||||
@SpringJUnitConfig({ SettingsTests.Config.class })
|
||||
class SettingsTests {
|
||||
@Autowired private ApplicationContext applicationContext;
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
public SpelTestBean spelTestBean() {
|
||||
return new SpelTestBean();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
((SimpleElasticsearchMappingContext) elasticsearchConverter
|
||||
.get().getMappingContext()).setApplicationContext(applicationContext);
|
||||
|
||||
}
|
||||
|
||||
@Test // #1719
|
||||
@DisplayName("should error if index sorting parameters do not have the same number of arguments")
|
||||
@ -205,6 +229,24 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
String json = entity.getDefaultSettings().toJson();
|
||||
assertEquals(expected, json, false);
|
||||
}
|
||||
|
||||
@Test // #3187
|
||||
@DisplayName("should evaluate SpEL expression in settingPath")
|
||||
void shouldEvaluateSpElExpressionInSettingPath() {
|
||||
|
||||
var settingPath = elasticsearchConverter.get().getMappingContext()
|
||||
.getRequiredPersistentEntity(SettingPathWithSpel.class).settingPath();
|
||||
|
||||
assertThat(settingPath).isEqualTo(SpelTestBean.SETTING_PATH);
|
||||
}
|
||||
|
||||
private static class SpelTestBean {
|
||||
public static String SETTING_PATH = "test-setting-path";
|
||||
|
||||
public String settingPath() {
|
||||
return SETTING_PATH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@ -271,7 +313,7 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
}
|
||||
}
|
||||
|
||||
// region helper functions
|
||||
// region helper
|
||||
private static SimpleElasticsearchPersistentProperty createProperty(SimpleElasticsearchPersistentEntity<?> entity,
|
||||
String fieldName) {
|
||||
|
||||
@ -282,6 +324,7 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
return new SimpleElasticsearchPersistentProperty(property, entity, SimpleTypeHolder.DEFAULT);
|
||||
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region entities
|
||||
@ -295,7 +338,7 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
public void setVersion(@Nullable String version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@ -313,7 +356,7 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
return version1;
|
||||
}
|
||||
|
||||
public void setVersion1(Long version1) {
|
||||
public void setVersion1(@Nullable Long version1) {
|
||||
this.version1 = version1;
|
||||
}
|
||||
|
||||
@ -322,7 +365,7 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
return version2;
|
||||
}
|
||||
|
||||
public void setVersion2(Long version2) {
|
||||
public void setVersion2(@Nullable Long version2) {
|
||||
this.version2 = version2;
|
||||
}
|
||||
}
|
||||
@ -397,5 +440,12 @@ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBase
|
||||
@Nullable
|
||||
@Id String id;
|
||||
}
|
||||
|
||||
@Document(indexName = "foo")
|
||||
@Setting(settingPath = "#{@spelTestBean.settingPath}")
|
||||
private static class SettingPathWithSpel {
|
||||
@Nullable
|
||||
@Id String id;
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user