Cannot be longer than 255 bytes (note it is bytes, so multi-byte characters will count towards the 255 limit
@@ -54,50 +54,79 @@
String indexName();
/**
- * Mapping type name.
- * deprecated as Elasticsearch does not support this anymore
- * (@see Elastisearch removal of types documentation) and will remove it in
- * Elasticsearch 8.
- *
- * @deprecated since 4.0
+ * Configuration whether to create an index on repository bootstrapping.
*/
- @Deprecated
- String type() default "";
+ boolean createIndex() default true;
/**
- * Use server-side settings when creating the index.
+ * If true, the index mapping will be written on repository bootstrapping even when the index already exists. This
+ * allows for automatically updating the mapping with new properties. Changes on existing properties will lead to an
+ * error from the Elasticsearch server.
*/
- boolean useServerConfiguration() default false;
+ boolean alwaysWriteMapping() default false;
/**
- * Number of shards for the index {@link #indexName()}. Used for index creation.
- * With version 4.0, the default value is changed from 5 to 1 to reflect the change in the default settings of
- * Elasticsearch which changed to 1 as well in Elasticsearch 7.0.
+ * Configuration of version management.
*/
- short shards() default 1;
+ VersionType versionType() default VersionType.EXTERNAL;
/**
- * Number of replicas for the index {@link #indexName()}. Used for index creation.
+ * Defines if type hints should be written. {@see WriteTypeHint}.
+ *
+ * @since 4.3
*/
- short replicas() default 1;
+ WriteTypeHint writeTypeHint() default WriteTypeHint.DEFAULT;
/**
- * Refresh interval for the index {@link #indexName()}. Used for index creation.
+ * Controls how Elasticsearch dynamically adds fields to the document.
+ *
+ * @since 4.3
*/
- String refreshInterval() default "1s";
+ Dynamic dynamic() default Dynamic.INHERIT;
/**
- * Index storage type for the index {@link #indexName()}. Used for index creation.
+ * Specifies if the id property should also be stored in the Elasticsearch document source. Default value is
+ * {@literal true}
+ *
+ * @since 5.1
*/
- String indexStoreType() default "fs";
+ boolean storeIdInSource() default true;
/**
- * Configuration whether to create an index on repository bootstrapping.
+ * Specifies if the version property should also be stored in the Elasticsearch document source. Default value is
+ * true.
+ *
+ * @since 5.1
*/
- boolean createIndex() default true;
+ boolean storeVersionInSource() default true;
/**
- * Configuration of version management.
+ * Aliases for the index.
+ *
+ * @since 5.4
*/
- VersionType versionType() default VersionType.EXTERNAL;
+ Alias[] aliases() default {};
+
+ /**
+ * @since 4.3
+ */
+ enum VersionType {
+ INTERNAL("internal"), //
+ EXTERNAL("external"), //
+ EXTERNAL_GTE("external_gte"), //
+ /**
+ * @since 4.4
+ */
+ FORCE("force");
+
+ private final String esName;
+
+ VersionType(String esName) {
+ this.esName = esName;
+ }
+
+ public String getEsName() {
+ return esName;
+ }
+ }
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Dynamic.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Dynamic.java
new file mode 100644
index 0000000000..9868c6e3c6
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Dynamic.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2021-2025 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
+ *
+ * https://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.annotations;
+
+/**
+ * Values for the {@code dynamic} mapping parameter.
+ *
+ * @author Sascha Woo
+ * @since 4.3
+ */
+public enum Dynamic {
+ /**
+ * New fields are added to the mapping.
+ */
+ TRUE("true"),
+ /**
+ * New fields are added to the mapping as
+ * runtime fields. These
+ * fields are not indexed, and are loaded from {@code _source} at query time.
+ */
+ RUNTIME("runtime"),
+ /**
+ * New fields are ignored. These fields will not be indexed or searchable, but will still appear in the
+ * {@code _source} field of returned hits. These fields will not be added to the mapping, and new fields must be added
+ * explicitly.
+ */
+ FALSE("false"),
+ /**
+ * If new fields are detected, an exception is thrown and the document is rejected. New fields must be explicitly
+ * added to the mapping.
+ */
+ STRICT("strict"),
+ /**
+ * Inherit the dynamic setting from their parent object or from the mapping type.
+ */
+ INHERIT("inherit");
+
+ private final String mappedName;
+
+ Dynamic(String mappedName) {
+ this.mappedName = mappedName;
+ }
+
+ public String getMappedName() {
+ return mappedName;
+ }
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/DynamicTemplates.java b/src/main/java/org/springframework/data/elasticsearch/annotations/DynamicTemplates.java
index aa831c7873..107ee94be2 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/DynamicTemplates.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/DynamicTemplates.java
@@ -9,19 +9,17 @@
import org.springframework.data.annotation.Persistent;
/**
- * Elasticsearch dynamic templates mapping.
- * This annotation is handy if you prefer apply dynamic templates on fields with annotation e.g. {@link Field}
- * with type = FieldType.Object etc. instead of static mapping on Document via {@link Mapping} annotation.
- * DynamicTemplates annotation is ommited if {@link Mapping} annotation is used.
+ * Elasticsearch dynamic templates mapping. This annotation is handy if you prefer apply dynamic templates on fields
+ * with annotation e.g. {@link Field} with type = FieldType.Object etc. instead of static mapping on Document via
+ * {@link Mapping} annotation. DynamicTemplates annotation is omitted if {@link Mapping} annotation is used.
*
* @author Petr Kukral
*/
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
+@Target({ ElementType.TYPE })
public @interface DynamicTemplates {
String mappingPath() default "";
-
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java
index 7adaa72441..97815477ae 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2020 the original author or authors.
+ * Copyright 2013-2025 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.
@@ -33,9 +33,15 @@
* @author Kevin Leturc
* @author Peter-Josef Meisch
* @author Xiao Yu
+ * @author Aleksei Arsenev
+ * @author Brian Kimmig
+ * @author Morgan Lutz
+ * @author Sascha Woo
+ * @author Haibo Liu
+ * @author Andriy Redko
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
+@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Documented
@Inherited
public @interface Field {
@@ -49,9 +55,8 @@
String value() default "";
/**
- * The name to be used to store the field inside the document.
- *
- * √5 If not set, the name of the annotated property is used.
+ * The name to be used to store the field inside the document. If not set, the name of the annotated property
+ * is used.
*
* @since 3.2
*/
@@ -62,9 +67,9 @@
boolean index() default true;
- DateFormat format() default DateFormat.none;
+ DateFormat[] format() default { DateFormat.date_optional_time, DateFormat.epoch_millis };
- String pattern() default "";
+ String[] pattern() default {};
boolean store() default false;
@@ -125,6 +130,10 @@
boolean norms() default true;
/**
+ * NOte that null_value setting are not supported in Elasticsearch for all types. For example setting a null_value on
+ * a field with type text will throw an exception in the server when the mapping is written to Elasticsearch. Alas,
+ * the Elasticsearch documentation does not specify on which types it is allowed on which it is not.
+ *
* @since 4.0
*/
String nullValue() default "";
@@ -137,7 +146,7 @@
/**
* @since 4.0
*/
- Similarity similarity() default Similarity.Default;
+ String similarity() default Similarity.Default;
/**
* @since 4.0
@@ -148,4 +157,99 @@
* @since 4.0
*/
double scalingFactor() default 1;
+
+ /**
+ * @since 4.0
+ */
+ int maxShingleSize() default -1;
+
+ /**
+ * if true, the field will be stored in Elasticsearch even if it has a null value
+ *
+ * @since 4.1
+ */
+ boolean storeNullValue() default false;
+
+ /**
+ * to be used in combination with {@link FieldType#Rank_Feature}
+ *
+ * @since 4.1
+ */
+ boolean positiveScoreImpact() default true;
+
+ /**
+ * to be used in combination with {@link FieldType#Object}
+ *
+ * @since 4.1
+ */
+ boolean enabled() default true;
+
+ /**
+ * @since 4.1
+ */
+ boolean eagerGlobalOrdinals() default false;
+
+ /**
+ * @since 4.1
+ */
+ NullValueType nullValueType() default NullValueType.String;
+
+ /**
+ * to be used in combination with {@link FieldType#Dense_Vector}
+ *
+ * @since 4.2
+ */
+ int dims() default -1;
+
+ /**
+ * to be used in combination with {@link FieldType#Dense_Vector}
+ *
+ * @since 5.4
+ */
+ String elementType() default FieldElementType.DEFAULT;
+
+ /**
+ * to be used in combination with {@link FieldType#Dense_Vector}
+ *
+ * @since 5.4
+ */
+ KnnSimilarity knnSimilarity() default KnnSimilarity.DEFAULT;
+
+ /**
+ * to be used in combination with {@link FieldType#Dense_Vector}
+ *
+ * @since 5.4
+ */
+ KnnIndexOptions[] knnIndexOptions() default {};
+
+ /**
+ * Controls how Elasticsearch dynamically adds fields to the inner object within the document.
+ * To be used in combination with {@link FieldType#Object} or {@link FieldType#Nested}
+ *
+ * @since 4.3
+ */
+ Dynamic dynamic() default Dynamic.INHERIT;
+
+ /**
+ * marks this field to be excluded from the _source in Elasticsearch
+ * (https://www.elastic.co/guide/en/elasticsearch/reference/7.15/mapping-source-field.html#include-exclude)
+ *
+ * @since 4.3
+ */
+ boolean excludeFromSource() default false;
+
+ /**
+ * when this field is a {{@link String}}, a {{@link java.util.Collection}} or a {{@link java.util.Map}} that is empty
+ * this property controlls whether the empty value is sent to Elasticsearch.
+ *
+ * @since 5.1
+ */
+ boolean storeEmptyValue() default true;
+
+ /**
+ * overrides the field type in the mapping which otherwise will be taken from corresponding {@link FieldType}
+ *
+ * @since 5.4
+ */
+ String mappedTypeName() default "";
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Parent.java b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldElementType.java
similarity index 67%
rename from src/main/java/org/springframework/data/elasticsearch/annotations/Parent.java
rename to src/main/java/org/springframework/data/elasticsearch/annotations/FieldElementType.java
index d919f32f01..49271764ba 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Parent.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldElementType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2020 the original author or authors.
+ * Copyright 2024-2025 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.
@@ -15,21 +15,12 @@
*/
package org.springframework.data.elasticsearch.annotations;
-import java.lang.annotation.*;
-
-import org.springframework.data.annotation.Persistent;
-
/**
- * Parent
- *
- * @author Philipp Jardas
+ * @author Haibo Liu
+ * @since 5.4
*/
-
-@Persistent
-@Inherited
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface Parent {
-
- String type();
+public final class FieldElementType {
+ public final static String DEFAULT = "";
+ public final static String FLOAT = "float";
+ public final static String BYTE = "byte";
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java
index 09cc014e42..f701948d6d 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2020 the original author or authors.
+ * Copyright 2013-2025 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.
@@ -21,33 +21,80 @@
* @author Artur Konczak
* @author Zeng Zetang
* @author Peter-Josef Meisch
+ * @author Aleksei Arsenev
+ * @author Brian Kimmig
+ * @author Morgan Lutz
*/
public enum FieldType {
- Auto,
- Text,
- Keyword,
- Long,
- Integer,
- Short,
- Byte,
- Double,
- Float,
- Half_Float,
- Scaled_Float,
- Date,
- Date_Nanos,
- Boolean,
- Binary,
- Integer_Range,
- Float_Range,
- Long_Range,
- Double_Range,
- Date_Range,
- Ip_Range,
- Object,
- Nested,
- Ip,
- TokenCount,
- Percolator,
- Flattened
+ Auto("auto"), //
+ Text("text"), //
+ Keyword("keyword"), //
+ Long("long"), //
+ Integer("integer"), //
+ Short("short"), //
+ Byte("byte"), //
+ Double("double"), //
+ Float("float"), //
+ Half_Float("half_float"), //
+ Scaled_Float("scaled_float"), //
+ Date("date"), //
+ Date_Nanos("date_nanos"), //
+ Boolean("boolean"), //
+ Binary("binary"), //
+ Integer_Range("integer_range"), //
+ Float_Range("float_range"), //
+ Long_Range("long_range"), //
+ Double_Range("double_range"), //
+ Date_Range("date_range"), //
+ Ip_Range("ip_range"), //
+ Object("object"), //
+ Nested("nested"), //
+ Ip("ip"), //
+ TokenCount("token_count"), //
+ Percolator("percolator"), //
+ Flattened("flattened"), //
+ Search_As_You_Type("search_as_you_type"), //
+ /** @since 4.1 */
+ Rank_Feature("rank_feature"), //
+ /** @since 4.1 */
+ Rank_Features("rank_features"), //
+ /** since 4.2 */
+ Wildcard("wildcard"), //
+ /** @since 4.2 */
+ Dense_Vector("dense_vector"), //
+ /**
+ * @since 5.2
+ */
+ Constant_Keyword("constant_keyword"), //
+ /**
+ * @since 5.2
+ */
+ Alias("alias"), //
+ /**
+ * @since 5.2
+ */
+ Version("version"), //
+ /**
+ * @since 5.2
+ */
+ Murmur3("murmur3"), //
+ /**
+ * @since 5.2
+ */
+ Match_Only_Text("match_only_text"), //
+ /**
+ * @since 5.2
+ */
+ Annotated_Text("annotated_text") //
+ ;
+
+ private final String mappedName;
+
+ FieldType(String mappedName) {
+ this.mappedName = mappedName;
+ }
+
+ public String getMappedName() {
+ return mappedName;
+ }
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Filter.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Filter.java
new file mode 100644
index 0000000000..7f07df55d1
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Filter.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024-2025 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
+ *
+ * https://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.annotations;
+
+import org.springframework.core.annotation.AliasFor;
+
+/**
+ * Query used to limit documents.
+ *
+ * @author Youssef Aouichaoui
+ * @since 5.4
+ */
+public @interface Filter {
+ /**
+ * @return Query used to limit documents. Alias for {@link #query}.
+ */
+ @AliasFor("query")
+ String value() default "";
+
+ /**
+ * @return Query used to limit documents. Alias for {@link #value}.
+ */
+ @AliasFor("value")
+ String query() default "";
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/GeoPointField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/GeoPointField.java
index f2d5915c0f..05695abc98 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/GeoPointField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/GeoPointField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2020 the original author or authors.
+ * Copyright 2013-2025 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/GeoShapeField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/GeoShapeField.java
new file mode 100644
index 0000000000..0121b07ee1
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/GeoShapeField.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017-2025 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
+ *
+ * https://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.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Lukas Vorisek
+ * @author Peter-Josef Meisch
+ * @since 4.1
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Documented
+public @interface GeoShapeField {
+ Orientation orientation() default Orientation.ccw;
+
+ boolean ignoreMalformed() default false;
+
+ boolean ignoreZValue() default true;
+
+ boolean coerce() default false;
+
+ enum Orientation {
+ right, ccw, counterclockwise, left, cw, clockwise
+ }
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Highlight.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Highlight.java
index 075327a405..30312ab434 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Highlight.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Highlight.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2020 the original author or authors.
+ * Copyright 2020-2025 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightField.java
index ec7c0c6c1f..f6318be98a 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2020 the original author or authors.
+ * Copyright 2020-2025 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightParameters.java b/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightParameters.java
index 608a78734a..d4e8bbfd2b 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightParameters.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightParameters.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2020 the original author or authors.
+ * Copyright 2020-2025 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.
@@ -21,6 +21,7 @@
/**
* @author Peter-Josef Meisch
+ * @author Haibo Liu
* @since 4.0
*/
@Documented
@@ -59,6 +60,8 @@
int numberOfFragments() default -1;
+ Query highlightQuery() default @Query;
+
String order() default "";
int phraseLimit() default -1;
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexOptions.java b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexOptions.java
index b72db4c9cd..2de226c7b1 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexOptions.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexOptions.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2019-2025 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexPrefixes.java b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexPrefixes.java
index fa91f37f33..01adc8fbb4 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexPrefixes.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexPrefixes.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2019-2025 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexedIndexName.java b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexedIndexName.java
new file mode 100644
index 0000000000..4d76b97492
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexedIndexName.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023-2025 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
+ *
+ * https://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.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to mark a String property of an entity to be filled with the name of the index where the entity was stored
+ * after it is indexed into Elasticsearch. This can be used when the name of the index is dynamically created or when a
+ * document was indexed into a write alias.
+ *
+ * This can not be used to specify the index where an entity should be written to.
+ *
+ * @author Peter-Josef Meisch
+ * @since 5.1
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
+@Documented
+@Field(type = FieldType.Auto) // prevents the property being written to the index mapping
+public @interface IndexedIndexName {
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java
index c6fa617d7b..651bf5a825 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2020 the original author or authors.
+ * Copyright 2014-2025 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,9 +26,14 @@
* @author Sascha Woo
* @author Xiao Yu
* @author Peter-Josef Meisch
+ * @author Aleksei Arsenev
+ * @author Brian Kimmig
+ * @author Morgan Lutz
+ * @author Haibo Liu
+ * @author Andriy Redko
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
+@Target(ElementType.ANNOTATION_TYPE)
public @interface InnerField {
String suffix();
@@ -37,9 +42,9 @@
boolean index() default true;
- DateFormat format() default DateFormat.none;
+ DateFormat[] format() default { DateFormat.date_optional_time, DateFormat.epoch_millis };
- String pattern() default "";
+ String[] pattern() default {};
boolean store() default false;
@@ -106,7 +111,7 @@
/**
* @since 4.0
*/
- Similarity similarity() default Similarity.Default;
+ String similarity() default Similarity.Default;
/**
* @since 4.0
@@ -117,4 +122,61 @@
* @since 4.0
*/
double scalingFactor() default 1;
+
+ /**
+ * @since 4.0
+ */
+ int maxShingleSize() default -1;
+
+ /**
+ * to be used in combination with {@link FieldType#Rank_Feature}
+ *
+ * @since 4.1
+ */
+ boolean positiveScoreImpact() default true;
+
+ /**
+ * @since 4.1
+ */
+ boolean eagerGlobalOrdinals() default false;
+
+ /**
+ * @since 4.1
+ */
+ NullValueType nullValueType() default NullValueType.String;
+
+ /**
+ * to be used in combination with {@link FieldType#Dense_Vector}
+ *
+ * @since 4.2
+ */
+ int dims() default -1;
+
+ /**
+ * to be used in combination with {@link FieldType#Dense_Vector}
+ *
+ * @since 5.4
+ */
+ String elementType() default FieldElementType.DEFAULT;
+
+ /**
+ * to be used in combination with {@link FieldType#Dense_Vector}
+ *
+ * @since 5.4
+ */
+ KnnSimilarity knnSimilarity() default KnnSimilarity.DEFAULT;
+
+ /**
+ * to be used in combination with {@link FieldType#Dense_Vector}
+ *
+ * @since 5.4
+ */
+ KnnIndexOptions[] knnIndexOptions() default {};
+
+ /**
+ * overrides the field type in the mapping which otherwise will be taken from corresponding {@link FieldType}
+ *
+ * @since 5.4
+ */
+ String mappedTypeName() default "";
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelation.java b/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelation.java
new file mode 100644
index 0000000000..eb2e1e4623
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelation.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020-2025 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
+ *
+ * https://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.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Subhobrata Dey
+ * @since 4.1
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface JoinTypeRelation {
+
+ String parent();
+
+ String[] children();
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelations.java b/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelations.java
new file mode 100644
index 0000000000..2004200cf2
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelations.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020-2025 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
+ *
+ * https://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.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Subhobrata Dey
+ * @since 4.1
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Inherited
+public @interface JoinTypeRelations {
+
+ JoinTypeRelation[] relations();
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/KnnAlgorithmType.java b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnAlgorithmType.java
new file mode 100644
index 0000000000..6110e54be8
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnAlgorithmType.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024-2025 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
+ *
+ * https://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.annotations;
+
+/**
+ * @author Haibo Liu
+ * @since 5.4
+ */
+public enum KnnAlgorithmType {
+ HNSW("hnsw"),
+ INT8_HNSW("int8_hnsw"),
+ FLAT("flat"),
+ INT8_FLAT("int8_flat"),
+ DEFAULT("");
+
+ private final String type;
+
+ KnnAlgorithmType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/KnnIndexOptions.java b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnIndexOptions.java
new file mode 100644
index 0000000000..56d871d3b5
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnIndexOptions.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2024-2025 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
+ *
+ * https://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.annotations;
+
+/**
+ * @author Haibo Liu
+ * @since 5.4
+ */
+public @interface KnnIndexOptions {
+
+ KnnAlgorithmType type() default KnnAlgorithmType.DEFAULT;
+
+ /**
+ * Only applicable to {@link KnnAlgorithmType#HNSW} and {@link KnnAlgorithmType#INT8_HNSW} index types.
+ */
+ int m() default -1;
+
+ /**
+ * Only applicable to {@link KnnAlgorithmType#HNSW} and {@link KnnAlgorithmType#INT8_HNSW} index types.
+ */
+ int efConstruction() default -1;
+
+ /**
+ * Only applicable to {@link KnnAlgorithmType#INT8_HNSW} and {@link KnnAlgorithmType#INT8_FLAT} index types.
+ */
+ float confidenceInterval() default -1F;
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/KnnSimilarity.java b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnSimilarity.java
new file mode 100644
index 0000000000..d03c42a6fd
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnSimilarity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024-2025 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
+ *
+ * https://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.annotations;
+
+/**
+ * @author Haibo Liu
+ * @since 5.4
+ */
+public enum KnnSimilarity {
+ L2_NORM("l2_norm"),
+ DOT_PRODUCT("dot_product"),
+ COSINE("cosine"),
+ MAX_INNER_PRODUCT("max_inner_product"),
+ DEFAULT("");
+
+ private final String similarity;
+
+ KnnSimilarity(String similarity) {
+ this.similarity = similarity;
+ }
+
+ public String getSimilarity() {
+ return similarity;
+ }
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Mapping.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Mapping.java
index 9a0647a4f7..c2d48c3884 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Mapping.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Mapping.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2020 the original author or authors.
+ * Copyright 2014-2025 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.
@@ -15,20 +15,73 @@
*/
package org.springframework.data.elasticsearch.annotations;
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
import org.springframework.data.annotation.Persistent;
/**
* Elasticsearch Mapping
*
* @author Mohsin Husen
+ * @author Peter-Josef Meisch
*/
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE, ElementType.FIELD})
+@Target({ ElementType.TYPE, ElementType.FIELD })
public @interface Mapping {
String mappingPath() default "";
+ /**
+ * whether mappings are enabled
+ *
+ * @since 4.2
+ */
+ boolean enabled() default true;
+
+ /**
+ * whether date_detection is enabled
+ *
+ * @since 4.3
+ */
+ Detection dateDetection() default Detection.DEFAULT;
+
+ /**
+ * whether numeric_detection is enabled
+ *
+ * @since 4.3
+ */
+ Detection numericDetection() default Detection.DEFAULT;
+
+ /**
+ * custom dynamic date formats
+ *
+ * @since 4.3
+ */
+ String[] dynamicDateFormats() default {};
+
+ /**
+ * classpath to a JSON file containing the values for a runtime mapping definition. The file must contain the JSON
+ * object that is written as the value of the runtime property. {@see elasticsearch doc}
+ *
+ * @since 4.3
+ */
+ String runtimeFieldsPath() default "";
+
+ /**
+ * field alias definitions to be written to the index mapping
+ *
+ * @since 5.3
+ */
+ MappingAlias[] aliases() default {};
+
+ enum Detection {
+ DEFAULT, TRUE, FALSE
+ }
}
diff --git a/src/test/java/org/springframework/data/elasticsearch/junit/junit4/ElasticsearchVersion.java b/src/main/java/org/springframework/data/elasticsearch/annotations/MappingAlias.java
similarity index 63%
rename from src/test/java/org/springframework/data/elasticsearch/junit/junit4/ElasticsearchVersion.java
rename to src/main/java/org/springframework/data/elasticsearch/annotations/MappingAlias.java
index 8d936c268e..791659e9d5 100644
--- a/src/test/java/org/springframework/data/elasticsearch/junit/junit4/ElasticsearchVersion.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/MappingAlias.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2020 the original author or authors.
+ * Copyright 2024-2025 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.
@@ -13,33 +13,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.data.elasticsearch.junit.junit4;
+package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * @author Christoph Strobl
+ * Defines a field alias in the index mapping.
+ *
+ * @author Peter-Josef Meisch
+ * @since 5.3
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
+@Target(ElementType.FIELD)
@Documented
-public @interface ElasticsearchVersion {
-
+@Inherited
+public @interface MappingAlias {
/**
- * Inclusive lower bound of Elasticsearch server range.
- *
- * @return {@code 0.0.0} by default.
+ * the name of the alias.
*/
- String asOf() default "0.0.0";
+ String name();
/**
- * Exclusive upper bound of Elasticsearch server range.
- *
- * @return {@code 9999.9999.9999} by default.
+ * the path of the alias.
*/
- String until() default "9999.9999.9999";
+ String path();
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/MultiField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/MultiField.java
index 876bd8aa04..9dff38c1f1 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/MultiField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/MultiField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2020 the original author or authors.
+ * Copyright 2014-2025 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,9 +27,10 @@
* @author Artur Konczak
* @author Jonathan Yan
* @author Xiao Yu
+ * @author Peter-Josef Meisch
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
+@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Documented
public @interface MultiField {
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/DynamicMappingValue.java b/src/main/java/org/springframework/data/elasticsearch/annotations/NullValueType.java
similarity index 78%
rename from src/main/java/org/springframework/data/elasticsearch/annotations/DynamicMappingValue.java
rename to src/main/java/org/springframework/data/elasticsearch/annotations/NullValueType.java
index 54061bd6b1..a131b12a8e 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/DynamicMappingValue.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/NullValueType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2020-2025 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.
@@ -16,11 +16,9 @@
package org.springframework.data.elasticsearch.annotations;
/**
- * values for the {@link DynamicMapping annotation}
- *
* @author Peter-Josef Meisch
- * @since 4.0
+ * @since 4.1
*/
-public enum DynamicMappingValue {
- True, False, Strict
+public enum NullValueType {
+ String, Integer, Long, Double
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java
index ab4ef449b4..9f1b755c35 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2020 the original author or authors.
+ * Copyright 2013-2025 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.
@@ -15,31 +15,48 @@
*/
package org.springframework.data.elasticsearch.annotations;
-import java.lang.annotation.*;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.data.annotation.QueryAnnotation;
/**
* Query
*
* @author Rizwan Idrees
* @author Mohsin Husen
+ * @author Peter-Josef Meisch
+ * @author Steven Pearce
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
+@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Documented
+@QueryAnnotation
public @interface Query {
/**
- * Elasticsearch query to be used when executing query. May contain placeholders eg. ?0
- *
- * @return
+ * @return Elasticsearch query to be used when executing query. May contain placeholders eg. ?0. Alias for query.
*/
+ @AliasFor("query")
String value() default "";
/**
- * Named Query Named looked up by repository.
+ * @return Elasticsearch query to be used when executing query. May contain placeholders eg. ?0. Alias for value
+ * @since 5.0
+ */
+ @AliasFor("value")
+ String query() default "";
+
+ /**
+ * Returns whether the query defined should be executed as count projection.
*
- * @return
+ * @return {@literal false} by default.
+ * @since 4.2
*/
- String name() default "";
+ boolean count() default false;
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Routing.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Routing.java
new file mode 100644
index 0000000000..ea71e50564
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Routing.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright2020-2021 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
+ *
+ * https://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.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.data.annotation.Persistent;
+
+/**
+ * Annotation to enable custom routing values for an entity.
+ *
+ * @author Peter-Josef Meisch
+ * @since 4.2
+ */
+@Persistent
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE })
+public @interface Routing {
+
+ /**
+ * defines how the routing is determined. Can be either the name of a property or a SpEL expression. See the reference
+ * documentation for examples how to use this annotation.
+ */
+ String value();
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Score.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Score.java
deleted file mode 100644
index f5cd57a212..0000000000
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Score.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.springframework.data.elasticsearch.annotations;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.springframework.data.annotation.ReadOnlyProperty;
-import org.springframework.data.elasticsearch.core.SearchHit;
-
-/**
- * Specifies that this field is used for storing the document score.
- *
- * @author Sascha Woo
- * @author Peter-Josef Meisch
- * @since 3.1
- * @deprecated since 4.0, use {@link SearchHit#getScore()} instead
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-@Documented
-@Inherited
-@ReadOnlyProperty
-@Deprecated
-public @interface Score {
-}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/ScriptedField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/ScriptedField.java
index f1eb3e06a3..cc596c54f3 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/ScriptedField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/ScriptedField.java
@@ -3,6 +3,7 @@
import java.lang.annotation.*;
/**
+ * Marks a property to be populated with the result of a scripted field retrieved from an Elasticsearch response.
* @author Ryan Murfitt
*/
@Retention(RetentionPolicy.RUNTIME)
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/SearchTemplateQuery.java b/src/main/java/org/springframework/data/elasticsearch/annotations/SearchTemplateQuery.java
new file mode 100644
index 0000000000..f50675d979
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/SearchTemplateQuery.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2025 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
+ *
+ * https://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.annotations;
+
+import org.springframework.data.annotation.QueryAnnotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to mark a repository method as a search template method. The annotation defines the search template id,
+ * the parameters for the search template are taken from the method's arguments.
+ *
+ * @author P.J. Meisch (pj.meisch@sothawo.com)
+ * @since 5.5
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
+@Documented
+@QueryAnnotation
+public @interface SearchTemplateQuery {
+ /**
+ * The id of the search template. Must not be empt or null.
+ */
+ String id();
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java
index 8256f466d3..926154f1f2 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2020 the original author or authors.
+ * Copyright 2014-2025 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.
@@ -15,7 +15,11 @@
*/
package org.springframework.data.elasticsearch.annotations;
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
import org.springframework.data.annotation.Persistent;
@@ -23,14 +27,84 @@
* Elasticsearch Setting
*
* @author Mohsin Husen
+ * @author Peter-Josef Meisch
*/
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
+@Target({ ElementType.TYPE })
public @interface Setting {
+ /**
+ * Resource path for a settings configuration
+ */
String settingPath() default "";
+ /**
+ * Use server-side settings when creating the index.
+ */
+ boolean useServerConfiguration() default false;
+
+ /**
+ * Number of shards for the index. Used for index creation.
+ * With version 4.0, the default value is changed from 5 to 1 to reflect the change in the default settings of
+ * Elasticsearch which changed to 1 as well in Elasticsearch 7.0.
+ */
+ short shards() default 1;
+
+ /**
+ * Number of replicas for the index. Used for index creation.
+ */
+ short replicas() default 1;
+
+ /**
+ * Refresh interval for the index. Used for index creation.
+ */
+ String refreshInterval() default "1s";
+
+ /**
+ * Index storage type for the index. Used for index creation.
+ */
+ String indexStoreType() default "fs";
+
+ /**
+ * fields to define an index sorting
+ *
+ * @since 4.2
+ */
+ String[] sortFields() default {};
+
+ /**
+ * defines the order for {@link #sortFields()}. If present, it must have the same number of elements
+ *
+ * @since 4.2
+ */
+ SortOrder[] sortOrders() default {};
+
+ /**
+ * defines the mode for {@link #sortFields()}. If present, it must have the same number of elements
+ *
+ * @since 4.2
+ */
+ SortMode[] sortModes() default {};
+
+ /**
+ * defines the missing value for {@link #sortFields()}. If present, it must have the same number of elements
+ *
+ * @since 4.2
+ */
+ SortMissing[] sortMissingValues() default {};
+
+ enum SortOrder {
+ asc, desc
+ }
+
+ enum SortMode {
+ min, max
+ }
+
+ enum SortMissing {
+ _last, _first
+ }
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Similarity.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Similarity.java
index 54c3c8c591..46cafd91a2 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Similarity.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Similarity.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2019-2025 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.
@@ -19,18 +19,9 @@
* @author Peter-Josef Meisch
* @since 4.0
*/
-public enum Similarity {
- Default("default"), BM25("BM25"), classic("classic"), Boolean("boolean");
-
- // need to use a custom name because 'boolean' can't be used as enum name
- private final String toStringName;
-
- Similarity(String name) {
- this.toStringName = name;
- }
-
- @Override
- public String toString() {
- return toStringName;
- }
+public final class Similarity {
+ public final static String Default = "default";
+ public final static String BM25 = "BM25";
+ public final static String classic = "classic";
+ public final static String Boolean = "boolean";
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/SourceFilters.java b/src/main/java/org/springframework/data/elasticsearch/annotations/SourceFilters.java
new file mode 100644
index 0000000000..055ecc616f
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/SourceFilters.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2022-2025 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
+ *
+ * https://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.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation can be placed on repository methods to define the properties that should be requested from
+ * Elasticsearch when the method is run.
+ *
+ * @author Alexander Torres
+ * @author Peter-Josef Meisch
+ * @since 5.0
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
+@Documented
+public @interface SourceFilters {
+
+ /**
+ * Properties to be requested from Elasticsearch to be included in the response. These can be passed in as literals
+ * like
+ *
+ *
+ * {@code @SourceFilters(includes = {"property1", "property2"})}
+ *
+ *
+ * or as a parameterized value
+ *
+ *
+ * {@code @SourceFilters(includes = "?0")}
+ *
+ *
+ * when the list of properties is passed as a function parameter.
+ */
+ String[] includes() default "";
+
+ /**
+ * Properties to be requested from Elasticsearch to be excluded in the response. These can be passed in as literals
+ * like
+ *
+ *
+ * {@code @SourceFilters(excludes = {"property1", "property2"})}
+ *
+ *
+ * or as a parameterized value
+ *
+ *
+ * {@code @SourceFilters(excludes = "?0")}
+ *
+ *
+ * when the list of properties is passed as a function parameter.
+ */
+ String[] excludes() default "";
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/TermVector.java b/src/main/java/org/springframework/data/elasticsearch/annotations/TermVector.java
index ba8ec1c148..25de2cbcad 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/TermVector.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/TermVector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2019-2025 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,5 +20,5 @@
* @since 4.0
*/
public enum TermVector {
- none, no, yes, with_positions, with_offsets, woth_positions_offsets, with_positions_payloads, with_positions_offets_payloads
+ none, no, yes, with_positions, with_offsets, with_positions_offsets, with_positions_payloads, with_positions_offsets_payloads
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java b/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java
new file mode 100644
index 0000000000..eb848bfed2
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021-2025 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
+ *
+ * https://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.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter;
+
+/**
+ * Annotation to put on a property of an entity to define a value converter which can convert the property to a type
+ * that Elasticsearch understands and back.
+ *
+ * @author Peter-Josef Meisch
+ * @since 4.3
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
+@Documented
+@Inherited
+public @interface ValueConverter {
+
+ /**
+ * Defines the class implementing the {@link PropertyValueConverter} interface. If this is a normal class, it must
+ * provide a default constructor with no arguments. If this is an enum and thus implementing a singleton by enum it
+ * must only have one enum value.
+ *
+ * @return the class to use for conversion
+ */
+ Class extends PropertyValueConverter> value();
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/WriteOnlyProperty.java b/src/main/java/org/springframework/data/elasticsearch/annotations/WriteOnlyProperty.java
new file mode 100644
index 0000000000..7704450e26
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/WriteOnlyProperty.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2022-2025 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
+ *
+ * https://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.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to mark a property that will be written to Elasticsearch, but not set when reading from Elasticsearch.
+ * This is needed for synthesized fields that may be used for search but that are not available in the entity.
+ *
+ * @author Peter-Josef Meisch
+ * @since 5.0
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD, ElementType.FIELD })
+@Documented
+public @interface WriteOnlyProperty {
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/WriteTypeHint.java b/src/main/java/org/springframework/data/elasticsearch/annotations/WriteTypeHint.java
new file mode 100644
index 0000000000..86a844cc18
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/WriteTypeHint.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021-2025 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
+ *
+ * https://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.annotations;
+
+import org.springframework.data.mapping.context.MappingContext;
+
+/**
+ * Defines if type hints should be written. Used by {@link Document} annotation.
+ *
+ * @author Peter-Josef Meisch
+ * @since 4.3
+ */
+public enum WriteTypeHint {
+
+ /**
+ * Use the global settings from the {@link MappingContext}.
+ */
+ DEFAULT,
+ /**
+ * Always write type hints for the entity.
+ */
+ TRUE,
+ /**
+ * Never write type hints for the entity.
+ */
+ FALSE
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/package-info.java b/src/main/java/org/springframework/data/elasticsearch/annotations/package-info.java
index 60fe252678..4b8ccdf64e 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/package-info.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/package-info.java
@@ -1,3 +1,2 @@
-@org.springframework.lang.NonNullApi
-@org.springframework.lang.NonNullFields
+@org.jspecify.annotations.NullMarked
package org.springframework.data.elasticsearch.annotations;
diff --git a/src/main/java/org/springframework/data/elasticsearch/aot/ElasticsearchAotPredicates.java b/src/main/java/org/springframework/data/elasticsearch/aot/ElasticsearchAotPredicates.java
new file mode 100644
index 0000000000..c3921b8940
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/aot/ElasticsearchAotPredicates.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2023-2025 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
+ *
+ * https://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.aot;
+
+import java.util.function.Predicate;
+
+import org.springframework.data.util.ReactiveWrappers;
+
+/**
+ * @author Peter-Josef Meisch
+ * @since 5.1
+ */
+public class ElasticsearchAotPredicates {
+
+ public static final Predicate IS_REACTIVE_LIBRARY_AVAILABLE = (
+ lib) -> ReactiveWrappers.isAvailable(lib);
+
+ public static boolean isReactorPresent() {
+ return IS_REACTIVE_LIBRARY_AVAILABLE.test(ReactiveWrappers.ReactiveLibrary.PROJECT_REACTOR);
+ }
+
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/aot/SpringDataElasticsearchRuntimeHints.java b/src/main/java/org/springframework/data/elasticsearch/aot/SpringDataElasticsearchRuntimeHints.java
new file mode 100644
index 0000000000..100b2ae449
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/aot/SpringDataElasticsearchRuntimeHints.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2023-2025 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
+ *
+ * https://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.aot;
+
+import static org.springframework.data.elasticsearch.aot.ElasticsearchAotPredicates.*;
+
+import java.util.Arrays;
+
+import org.jspecify.annotations.Nullable;
+import org.springframework.aot.hint.MemberCategory;
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.aot.hint.RuntimeHintsRegistrar;
+import org.springframework.aot.hint.TypeReference;
+import org.springframework.data.elasticsearch.client.elc.EntityAsMap;
+import org.springframework.data.elasticsearch.core.event.AfterConvertCallback;
+import org.springframework.data.elasticsearch.core.event.AfterLoadCallback;
+import org.springframework.data.elasticsearch.core.event.AfterSaveCallback;
+import org.springframework.data.elasticsearch.core.event.BeforeConvertCallback;
+import org.springframework.data.elasticsearch.core.event.ReactiveAfterConvertCallback;
+import org.springframework.data.elasticsearch.core.event.ReactiveAfterLoadCallback;
+import org.springframework.data.elasticsearch.core.event.ReactiveAfterSaveCallback;
+import org.springframework.data.elasticsearch.core.event.ReactiveBeforeConvertCallback;
+
+/**
+ * @author Peter-Josef Meisch
+ * @since 5.1
+ */
+public class SpringDataElasticsearchRuntimeHints implements RuntimeHintsRegistrar {
+
+ @Override
+ public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
+ hints.reflection().registerTypes( //
+ Arrays.asList( //
+ TypeReference.of(AfterConvertCallback.class), //
+ TypeReference.of(AfterLoadCallback.class), //
+ TypeReference.of(AfterSaveCallback.class), //
+ TypeReference.of(BeforeConvertCallback.class), //
+ TypeReference.of(EntityAsMap.class) //
+ ), //
+ builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
+ MemberCategory.INVOKE_PUBLIC_METHODS));
+
+ if (isReactorPresent()) {
+ hints.reflection().registerTypes( //
+ Arrays.asList( //
+ TypeReference.of(ReactiveAfterConvertCallback.class), //
+ TypeReference.of(ReactiveAfterLoadCallback.class), //
+ TypeReference.of(ReactiveAfterSaveCallback.class), //
+ TypeReference.of(ReactiveBeforeConvertCallback.class) //
+ ), //
+ builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
+ MemberCategory.INVOKE_PUBLIC_METHODS));
+ }
+
+ // properties needed to log the different versions
+ hints.resources().registerPattern("versions.properties");
+ }
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/aot/package-info.java b/src/main/java/org/springframework/data/elasticsearch/aot/package-info.java
new file mode 100644
index 0000000000..56697c1029
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/aot/package-info.java
@@ -0,0 +1,2 @@
+@org.jspecify.annotations.NullMarked
+package org.springframework.data.elasticsearch.aot;
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/ClientConfiguration.java b/src/main/java/org/springframework/data/elasticsearch/client/ClientConfiguration.java
index 755f370716..f092e2bf6b 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/ClientConfiguration.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/ClientConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2020 the original author or authors.
+ * Copyright 2018-2025 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,13 +20,13 @@
import java.time.Duration;
import java.util.List;
import java.util.Optional;
-import java.util.function.Function;
+import java.util.function.Supplier;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
-import org.springframework.http.HttpHeaders;
-import org.springframework.web.reactive.function.client.WebClient;
+import org.jspecify.annotations.Nullable;
+import org.springframework.data.elasticsearch.support.HttpHeaders;
/**
* Configuration interface exposing common client configuration properties for Elasticsearch clients.
@@ -50,7 +50,6 @@ static ClientConfigurationBuilderWithRequiredEndpoint builder() {
/**
* Creates a new {@link ClientConfiguration} instance configured to localhost.
- *
*
*
* // "localhost:9200"
@@ -65,9 +64,8 @@ static ClientConfiguration localhost() {
}
/**
- * Creates a new {@link ClientConfiguration} instance configured to a single host given {@code hostAndPort}.
- *
- * For example given the endpoint http://localhost:9200
+ * Creates a new {@link ClientConfiguration} instance configured to a single host given {@code hostAndPort}. For
+ * example given the endpoint http://localhost:9200
*
*
* ClientConfiguration configuration = ClientConfiguration.create("localhost:9200");
@@ -80,9 +78,8 @@ static ClientConfiguration create(String hostAndPort) {
}
/**
- * Creates a new {@link ClientConfiguration} instance configured to a single host given {@link InetSocketAddress}.
- *
- * For example given the endpoint http://localhost:9200
+ * Creates a new {@link ClientConfiguration} instance configured to a single host given {@link InetSocketAddress}. For
+ * example given the endpoint http://localhost:9200
*
*
* ClientConfiguration configuration = ClientConfiguration
@@ -117,16 +114,22 @@ static ClientConfiguration create(InetSocketAddress socketAddress) {
boolean useSsl();
/**
- * Returns the {@link SSLContext} to use. Can be {@link Optional#empty()} if unconfigured.
+ * Returns the {@link SSLContext} to use. Can be {@link Optional#empty()} if not configured.
*
- * @return the {@link SSLContext} to use. Can be {@link Optional#empty()} if unconfigured.
+ * @return the {@link SSLContext} to use. Can be {@link Optional#empty()} if not configured.
*/
Optional getSslContext();
/**
- * Returns the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if unconfigured.
+ * @return the optional SHA-256 fingerprint of the self-signed http_ca.crt certificate output by Elasticsearch at
+ * startup time.
+ */
+ Optional getCaFingerprint();
+
+ /**
+ * Returns the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if not configured.
*
- * @return the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if unconfigured.
+ * @return the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if not configured.
*/
Optional getHostNameVerifier();
@@ -134,7 +137,6 @@ static ClientConfiguration create(InetSocketAddress socketAddress) {
* Returns the {@link java.time.Duration connect timeout}.
*
* @see java.net.Socket#connect(SocketAddress, int)
- * @see io.netty.channel.ChannelOption#CONNECT_TIMEOUT_MILLIS
*/
Duration getConnectTimeout();
@@ -142,31 +144,36 @@ static ClientConfiguration create(InetSocketAddress socketAddress) {
* Returns the {@link java.time.Duration socket timeout} which is typically applied as SO-timeout/read timeout.
*
* @see java.net.Socket#setSoTimeout(int)
- * @see io.netty.handler.timeout.ReadTimeoutHandler
- * @see io.netty.handler.timeout.WriteTimeoutHandler
*/
Duration getSocketTimeout();
/**
* Returns the path prefix that should be prepended to HTTP(s) requests for Elasticsearch behind a proxy.
- *
+ *
* @return the path prefix.
* @since 4.0
*/
+ @Nullable
String getPathPrefix();
/**
* returns an optionally set proxy in the form host:port
- *
+ *
* @return the optional proxy
* @since 4.0
*/
Optional getProxy();
/**
- * @return the function for configuring a WebClient.
+ * @return the client configuration callbacks
+ * @since 4.3
+ */
+ List> getClientConfigurers();
+
+ /**
+ * @return the supplier for custom headers.
*/
- Function getWebClientConfigurer();
+ Supplier getHeadersSupplier();
/**
* @author Christoph Strobl
@@ -226,6 +233,15 @@ interface MaybeSecureClientConfigurationBuilder extends TerminalClientConfigurat
*/
TerminalClientConfigurationBuilder usingSsl();
+ /**
+ * Connects using https if flag is true.
+ *
+ * @param flag whether to use https in the connection
+ * @return the {@link TerminalClientConfigurationBuilder}
+ * @since 5.3
+ */
+ TerminalClientConfigurationBuilder usingSsl(boolean flag);
+
/**
* Connect via {@literal https} using the given {@link SSLContext}.
* NOTE You need to leave out the protocol in
@@ -244,6 +260,15 @@ interface MaybeSecureClientConfigurationBuilder extends TerminalClientConfigurat
* @return the {@link TerminalClientConfigurationBuilder}.
*/
TerminalClientConfigurationBuilder usingSsl(SSLContext sslContext, HostnameVerifier hostnameVerifier);
+
+ /**
+ * Connect via https using a SSLContext that is build from the given certificate fingerprint.
+ *
+ * @param caFingerprint the SHA-256 fingerprint of the self-signed http_ca.crt certificate output by Elasticsearch
+ * at startup time.
+ * @return the {@link TerminalClientConfigurationBuilder}.
+ */
+ TerminalClientConfigurationBuilder usingSsl(String caFingerprint);
}
/**
@@ -259,7 +284,7 @@ interface TerminalClientConfigurationBuilder {
TerminalClientConfigurationBuilder withDefaultHeaders(HttpHeaders defaultHeaders);
/**
- * Configure the {@literal milliseconds} for the connect timeout.
+ * Configure the {@literal milliseconds} for the connect-timeout.
*
* @param millis the timeout to use.
* @return the {@link TerminalClientConfigurationBuilder}
@@ -275,7 +300,6 @@ default TerminalClientConfigurationBuilder withConnectTimeout(long millis) {
* @param timeout the timeout to use. Must not be {@literal null}.
* @return the {@link TerminalClientConfigurationBuilder}
* @see java.net.Socket#connect(SocketAddress, int)
- * @see io.netty.channel.ChannelOption#CONNECT_TIMEOUT_MILLIS
*/
TerminalClientConfigurationBuilder withConnectTimeout(Duration timeout);
@@ -296,8 +320,6 @@ default TerminalClientConfigurationBuilder withSocketTimeout(long millis) {
* @param timeout the timeout to use. Must not be {@literal null}.
* @return the {@link TerminalClientConfigurationBuilder}
* @see java.net.Socket#setSoTimeout(int)
- * @see io.netty.handler.timeout.ReadTimeoutHandler
- * @see io.netty.handler.timeout.WriteTimeoutHandler
*/
TerminalClientConfigurationBuilder withSocketTimeout(Duration timeout);
@@ -312,7 +334,7 @@ default TerminalClientConfigurationBuilder withSocketTimeout(long millis) {
/**
* Configure the path prefix that will be prepended to any HTTP(s) requests
- *
+ *
* @param pathPrefix the pathPrefix.
* @return the {@link TerminalClientConfigurationBuilder}
* @since 4.0
@@ -326,12 +348,26 @@ default TerminalClientConfigurationBuilder withSocketTimeout(long millis) {
TerminalClientConfigurationBuilder withProxy(String proxy);
/**
- * set customization hook in case of a reactive configuration
- *
- * @param webClientConfigurer function to configure the WebClient
+ * Register a {@link ClientConfigurationCallback} to configure the client.
+ *
+ * @param clientConfigurer configuration callback, must not be {@literal null}.
* @return the {@link TerminalClientConfigurationBuilder}.
+ * @since 4.3
*/
- TerminalClientConfigurationBuilder withWebClientConfigurer(Function webClientConfigurer);
+ TerminalClientConfigurationBuilder withClientConfigurer(ClientConfigurationCallback> clientConfigurer);
+
+ /**
+ * set a supplier for custom headers. This is invoked for every HTTP request to Elasticsearch to retrieve headers
+ * that should be sent with the request. A common use case is passing in authentication headers that may change.
+ *
+ * Note: When used in a reactive environment, the calling of {@link Supplier#get()} function must not do any
+ * blocking operations. It may return {@literal null}.
+ *
+ * @param headers supplier function for headers, must not be {@literal null}
+ * @return the {@link TerminalClientConfigurationBuilder}.
+ * @since 4.0
+ */
+ TerminalClientConfigurationBuilder withHeaders(Supplier headers);
/**
* Build the {@link ClientConfiguration} object.
@@ -340,4 +376,15 @@ default TerminalClientConfigurationBuilder withSocketTimeout(long millis) {
*/
ClientConfiguration build();
}
+
+ /**
+ * Callback to be executed to configure a client.
+ *
+ * @param the type of the client configuration class.
+ * @since 4.3
+ */
+ @FunctionalInterface
+ interface ClientConfigurationCallback {
+ T configure(T clientConfigurer);
+ }
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/ClientConfigurationBuilder.java b/src/main/java/org/springframework/data/elasticsearch/client/ClientConfigurationBuilder.java
index 61ae39b356..71af992127 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/ClientConfigurationBuilder.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/ClientConfigurationBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2020 the original author or authors.
+ * Copyright 2018-2025 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,19 +20,17 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.function.Function;
-import java.util.stream.Collectors;
+import java.util.function.Supplier;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
+import org.jspecify.annotations.Nullable;
import org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationBuilderWithRequiredEndpoint;
import org.springframework.data.elasticsearch.client.ClientConfiguration.MaybeSecureClientConfigurationBuilder;
import org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder;
-import org.springframework.http.HttpHeaders;
-import org.springframework.lang.Nullable;
+import org.springframework.data.elasticsearch.support.HttpHeaders;
import org.springframework.util.Assert;
-import org.springframework.web.reactive.function.client.WebClient;
/**
* Default builder implementation for {@link ClientConfiguration}.
@@ -47,18 +45,20 @@
class ClientConfigurationBuilder
implements ClientConfigurationBuilderWithRequiredEndpoint, MaybeSecureClientConfigurationBuilder {
- private List hosts = new ArrayList<>();
- private HttpHeaders headers = HttpHeaders.EMPTY;
+ private final List hosts = new ArrayList<>();
+ private HttpHeaders headers = new HttpHeaders();
private boolean useSsl;
- private @Nullable SSLContext sslContext;
- private @Nullable HostnameVerifier hostnameVerifier;
+ @Nullable private SSLContext sslContext;
+ @Nullable private String caFingerprint;
+ @Nullable private HostnameVerifier hostnameVerifier;
private Duration connectTimeout = Duration.ofSeconds(10);
private Duration soTimeout = Duration.ofSeconds(5);
- private @Nullable String username;
- private @Nullable String password;
- private @Nullable String pathPrefix;
- private @Nullable String proxy;
- private @Nullable Function webClientConfigurer;
+ @Nullable private String username;
+ @Nullable private String password;
+ @Nullable private String pathPrefix;
+ @Nullable private String proxy;
+ private Supplier headersSupplier = HttpHeaders::new;
+ private final List> clientConfigurers = new ArrayList<>();
/*
* (non-Javadoc)
@@ -69,7 +69,7 @@ public MaybeSecureClientConfigurationBuilder connectedTo(String... hostAndPorts)
Assert.notEmpty(hostAndPorts, "At least one host is required");
- this.hosts.addAll(Arrays.stream(hostAndPorts).map(ClientConfigurationBuilder::parse).collect(Collectors.toList()));
+ this.hosts.addAll(Arrays.stream(hostAndPorts).map(ClientConfigurationBuilder::parse).toList());
return this;
}
@@ -105,6 +105,13 @@ public TerminalClientConfigurationBuilder usingSsl() {
return this;
}
+ @Override
+ public TerminalClientConfigurationBuilder usingSsl(boolean flag) {
+
+ this.useSsl = flag;
+ return this;
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.ClientConfiguration.MaybeSecureClientConfigurationBuilder#usingSsl(javax.net.ssl.SSLContext)
@@ -135,10 +142,20 @@ public TerminalClientConfigurationBuilder usingSsl(SSLContext sslContext, Hostna
return this;
}
+ @Override
+ public TerminalClientConfigurationBuilder usingSsl(String caFingerprint) {
+
+ Assert.notNull(caFingerprint, "caFingerprint must not be null");
+
+ this.useSsl = true;
+ this.caFingerprint = caFingerprint;
+ return this;
+ }
+
/*
- * (non-Javadoc)
- * @see org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder#withDefaultHeaders(org.springframework.http.HttpHeaders)
- */
+ * (non-Javadoc)
+ * @see org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder#withDefaultHeaders(org.springframework.http.HttpHeaders)
+ */
@Override
public TerminalClientConfigurationBuilder withDefaultHeaders(HttpHeaders defaultHeaders) {
@@ -196,11 +213,21 @@ public TerminalClientConfigurationBuilder withPathPrefix(String pathPrefix) {
}
@Override
- public TerminalClientConfigurationBuilder withWebClientConfigurer(Function webClientConfigurer) {
+ public TerminalClientConfigurationBuilder withClientConfigurer(
+ ClientConfiguration.ClientConfigurationCallback> clientConfigurer) {
- Assert.notNull(webClientConfigurer, "webClientConfigurer must not be null");
+ Assert.notNull(clientConfigurer, "clientConfigurer must not be null");
- this.webClientConfigurer = webClientConfigurer;
+ this.clientConfigurers.add(clientConfigurer);
+ return this;
+ }
+
+ @Override
+ public TerminalClientConfigurationBuilder withHeaders(Supplier headers) {
+
+ Assert.notNull(headers, "headersSupplier must not be null");
+
+ this.headersSupplier = headers;
return this;
}
@@ -212,14 +239,15 @@ public TerminalClientConfigurationBuilder withWebClientConfigurer(Function body) {
-
- if (isEnabled()) {
-
- WIRE_LOGGER.trace("[{}] Sending request {} {} with parameters: {}{}Request body: {}", logId, method.toUpperCase(),
- endpoint, parameters, lineSeparator, body.get());
- }
- }
-
- /**
- * Log a raw HTTP response without logging the body.
- *
- * @param logId the correlation Id, see {@link #newLogId()}.
- * @param statusCode the HTTP status code.
- */
- public static void logRawResponse(String logId, HttpStatus statusCode) {
-
- if (isEnabled()) {
- WIRE_LOGGER.trace("[{}] Received raw response: {}", logId, statusCode);
- }
- }
-
- /**
- * Log a raw HTTP response along with the body.
- *
- * @param logId the correlation Id, see {@link #newLogId()}.
- * @param statusCode the HTTP status code.
- * @param body body content.
- */
- public static void logResponse(String logId, HttpStatus statusCode, String body) {
-
- if (isEnabled()) {
- WIRE_LOGGER.trace("[{}] Received response: {}{}Response body: {}", logId, statusCode, lineSeparator, body);
- }
- }
-
- /**
- * Creates a new, unique correlation Id to improve tracing across log events.
- *
- * @return a new, unique correlation Id.
- */
- public static String newLogId() {
-
- if (!isEnabled()) {
- return "-";
- }
-
- return ObjectUtils.getIdentityHexString(new Object());
- }
-}
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/ClusterNodes.java b/src/main/java/org/springframework/data/elasticsearch/client/ClusterNodes.java
deleted file mode 100644
index fc54797533..0000000000
--- a/src/main/java/org/springframework/data/elasticsearch/client/ClusterNodes.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2018-2020 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
- *
- * https://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.client;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.elasticsearch.common.transport.TransportAddress;
-import org.springframework.data.util.Streamable;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-
-/**
- * Value object to represent a list of cluster nodes.
- *
- * @author Oliver Gierke
- * @since 3.1
- */
-class ClusterNodes implements Streamable {
-
- public static ClusterNodes DEFAULT = ClusterNodes.of("127.0.0.1:9300");
-
- private static final String COLON = ":";
- private static final String COMMA = ",";
-
- private final List clusterNodes;
-
- /**
- * Creates a new {@link ClusterNodes} by parsing the given source.
- *
- * @param source must not be {@literal null} or empty.
- */
- private ClusterNodes(String source) {
-
- Assert.hasText(source, "Cluster nodes source must not be null or empty!");
-
- String[] nodes = StringUtils.delimitedListToStringArray(source, COMMA);
-
- this.clusterNodes = Arrays.stream(nodes).map(node -> {
-
- String[] segments = StringUtils.delimitedListToStringArray(node, COLON);
-
- Assert.isTrue(segments.length == 2,
- () -> String.format("Invalid cluster node %s in %s! Must be in the format host:port!", node, source));
-
- String host = segments[0].trim();
- String port = segments[1].trim();
-
- Assert.hasText(host, () -> String.format("No host name given cluster node %s!", node));
- Assert.hasText(port, () -> String.format("No port given in cluster node %s!", node));
-
- return new TransportAddress(toInetAddress(host), Integer.parseInt(port));
-
- }).collect(Collectors.toList());
- }
-
- /**
- * Creates a new {@link ClusterNodes} by parsing the given source. The expected format is a comma separated list of
- * host-port-combinations separated by a colon: {@code host:port,host:port,…}.
- *
- * @param source must not be {@literal null} or empty.
- * @return
- */
- public static ClusterNodes of(String source) {
- return new ClusterNodes(source);
- }
-
- /*
- * (non-Javadoc)
- * @see java.lang.Iterable#iterator()
- */
- @Override
- public Iterator iterator() {
- return clusterNodes.iterator();
- }
-
- private static InetAddress toInetAddress(String host) {
-
- try {
- return InetAddress.getByName(host);
- } catch (UnknownHostException o_O) {
- throw new IllegalArgumentException(o_O);
- }
- }
-}
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/DefaultClientConfiguration.java b/src/main/java/org/springframework/data/elasticsearch/client/DefaultClientConfiguration.java
index 6bdc9bea91..ea097bbb59 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/DefaultClientConfiguration.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/DefaultClientConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2020 the original author or authors.
+ * Copyright 2018-2025 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.
@@ -17,18 +17,15 @@
import java.net.InetSocketAddress;
import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Optional;
-import java.util.function.Function;
+import java.util.function.Supplier;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
-import org.springframework.http.HttpHeaders;
-import org.springframework.lang.Nullable;
-import org.springframework.web.reactive.function.client.WebClient;
+import org.jspecify.annotations.Nullable;
+import org.springframework.data.elasticsearch.support.HttpHeaders;
/**
* Default {@link ClientConfiguration} implementation.
@@ -44,28 +41,33 @@ class DefaultClientConfiguration implements ClientConfiguration {
private final List hosts;
private final HttpHeaders headers;
private final boolean useSsl;
- private final @Nullable SSLContext sslContext;
+ @Nullable private final SSLContext sslContext;
+ @Nullable private final String caFingerprint;
private final Duration soTimeout;
private final Duration connectTimeout;
- private final String pathPrefix;
- private final @Nullable HostnameVerifier hostnameVerifier;
- private final String proxy;
- private final Function webClientConfigurer;
+ @Nullable private final String pathPrefix;
+ @Nullable private final HostnameVerifier hostnameVerifier;
+ @Nullable private final String proxy;
+ private final Supplier headersSupplier;
+ private final List> clientConfigurers;
DefaultClientConfiguration(List hosts, HttpHeaders headers, boolean useSsl,
- @Nullable SSLContext sslContext, Duration soTimeout, Duration connectTimeout, @Nullable String pathPrefix,
- @Nullable HostnameVerifier hostnameVerifier, String proxy, Function webClientConfigurer) {
+ @Nullable SSLContext sslContext, @Nullable String caFingerprint, Duration soTimeout, Duration connectTimeout,
+ @Nullable String pathPrefix, @Nullable HostnameVerifier hostnameVerifier, @Nullable String proxy,
+ List> clientConfigurers, Supplier headersSupplier) {
- this.hosts = Collections.unmodifiableList(new ArrayList<>(hosts));
- this.headers = new HttpHeaders(headers);
+ this.hosts = List.copyOf(hosts);
+ this.headers = headers;
this.useSsl = useSsl;
this.sslContext = sslContext;
+ this.caFingerprint = caFingerprint;
this.soTimeout = soTimeout;
this.connectTimeout = connectTimeout;
this.pathPrefix = pathPrefix;
this.hostnameVerifier = hostnameVerifier;
this.proxy = proxy;
- this.webClientConfigurer = webClientConfigurer;
+ this.clientConfigurers = clientConfigurers;
+ this.headersSupplier = headersSupplier;
}
@Override
@@ -88,6 +90,11 @@ public Optional getSslContext() {
return Optional.ofNullable(this.sslContext);
}
+ @Override
+ public Optional getCaFingerprint() {
+ return Optional.ofNullable(this.caFingerprint);
+ }
+
@Override
public Optional getHostNameVerifier() {
return Optional.ofNullable(this.hostnameVerifier);
@@ -103,6 +110,7 @@ public Duration getSocketTimeout() {
return this.soTimeout;
}
+ @Nullable
@Override
public String getPathPrefix() {
return this.pathPrefix;
@@ -114,7 +122,12 @@ public Optional getProxy() {
}
@Override
- public Function getWebClientConfigurer() {
- return webClientConfigurer != null ? webClientConfigurer : Function.identity();
+ public List> getClientConfigurers() {
+ return clientConfigurers;
+ }
+
+ @Override
+ public Supplier getHeadersSupplier() {
+ return headersSupplier;
}
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/ElasticsearchHost.java b/src/main/java/org/springframework/data/elasticsearch/client/ElasticsearchHost.java
index 5840cddb31..014acb6328 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/ElasticsearchHost.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/ElasticsearchHost.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2020 the original author or authors.
+ * Copyright 2018-2025 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/InetSocketAddressParser.java b/src/main/java/org/springframework/data/elasticsearch/client/InetSocketAddressParser.java
index 56e0e79ef2..33f71a49ed 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/InetSocketAddressParser.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/InetSocketAddressParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2020 the original author or authors.
+ * Copyright 2018-2025 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,7 +26,7 @@
* @author Mark Paluch
* @since 3.2
*/
-class InetSocketAddressParser {
+public class InetSocketAddressParser {
/**
* Parse a host and port string into a {@link InetSocketAddress}.
@@ -36,7 +36,7 @@ class InetSocketAddressParser {
* @return a {@link InetSocketAddress} that is unresolved to avoid DNS lookups.
* @see InetSocketAddress#createUnresolved(String, int)
*/
- static InetSocketAddress parse(String hostPortString, int defaultPort) {
+ public static InetSocketAddress parse(String hostPortString, int defaultPort) {
Assert.notNull(hostPortString, "HostPortString must not be null");
String host;
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/NoReachableHostException.java b/src/main/java/org/springframework/data/elasticsearch/client/NoReachableHostException.java
index 155d6cdd93..b8a560db63 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/NoReachableHostException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/NoReachableHostException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2020 the original author or authors.
+ * Copyright 2018-2025 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/NodeClientFactoryBean.java b/src/main/java/org/springframework/data/elasticsearch/client/NodeClientFactoryBean.java
deleted file mode 100644
index 37a7cc7e5e..0000000000
--- a/src/main/java/org/springframework/data/elasticsearch/client/NodeClientFactoryBean.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2015-2020 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
- *
- * https://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.client;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.Collections;
-
-import org.elasticsearch.client.Client;
-import org.elasticsearch.client.node.NodeClient;
-import org.elasticsearch.common.logging.LogConfigurator;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.node.InternalSettingsPreparer;
-import org.elasticsearch.node.Node;
-import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.transport.Netty4Plugin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.FactoryBeanNotInitializedException;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.lang.Nullable;
-import org.springframework.util.StringUtils;
-
-/**
- * NodeClientFactoryBean
- *
- * @author Rizwan Idrees
- * @author Mohsin Husen
- * @author Ilkang Na
- * @author Peter-Josef Meisch
- */
-public class NodeClientFactoryBean implements FactoryBean, InitializingBean, DisposableBean {
-
- private static final Logger logger = LoggerFactory.getLogger(NodeClientFactoryBean.class);
- private boolean local;
- private boolean enableHttp;
- private @Nullable String clusterName;
- private @Nullable Node node;
- private @Nullable NodeClient nodeClient;
- private @Nullable String pathData;
- private @Nullable String pathHome;
- private @Nullable String pathConfiguration;
-
- public static class TestNode extends Node {
-
- private static final String DEFAULT_NODE_NAME = "spring-data-elasticsearch-nodeclientfactorybean-test";
-
- public TestNode(Settings preparedSettings, Collection> classpathPlugins) {
-
- super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, Collections.emptyMap(), null,
- () -> DEFAULT_NODE_NAME), classpathPlugins, false);
- }
-
- protected void registerDerivedNodeNameWithLogger(String nodeName) {
- try {
- LogConfigurator.setNodeName(nodeName);
- } catch (Exception e) {
- // nagh - just forget about it
- }
- }
- }
-
- NodeClientFactoryBean() {}
-
- public NodeClientFactoryBean(boolean local) {
- this.local = local;
- }
-
- @Override
- public NodeClient getObject() {
-
- if (nodeClient == null) {
- throw new FactoryBeanNotInitializedException();
- }
-
- return nodeClient;
- }
-
- @Override
- public Class extends Client> getObjectType() {
- return NodeClient.class;
- }
-
- @Override
- public boolean isSingleton() {
- return true;
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
-
- Settings settings = Settings.builder() //
- .put(loadConfig()) //
- .put("transport.type", "netty4") //
- .put("http.type", "netty4") //
- .put("path.home", this.pathHome) //
- .put("path.data", this.pathData) //
- .put("cluster.name", this.clusterName) //
- .put("node.max_local_storage_nodes", 100) //
- .build();
- node = new TestNode(settings, Collections.singletonList(Netty4Plugin.class));
- nodeClient = (NodeClient) node.start().client();
- }
-
- private Settings loadConfig() throws IOException {
- if (!StringUtils.isEmpty(pathConfiguration)) {
- InputStream stream = getClass().getClassLoader().getResourceAsStream(pathConfiguration);
- if (stream != null) {
- return Settings.builder().loadFromStream(pathConfiguration,
- getClass().getClassLoader().getResourceAsStream(pathConfiguration), false).build();
- }
- logger.error(String.format("Unable to read node configuration from file [%s]", pathConfiguration));
- }
- return Settings.builder().build();
- }
-
- public void setLocal(boolean local) {
- this.local = local;
- }
-
- public void setEnableHttp(boolean enableHttp) {
- this.enableHttp = enableHttp;
- }
-
- public void setClusterName(String clusterName) {
- this.clusterName = clusterName;
- }
-
- public void setPathData(String pathData) {
- this.pathData = pathData;
- }
-
- public void setPathHome(String pathHome) {
- this.pathHome = pathHome;
- }
-
- public void setPathConfiguration(String configuration) {
- this.pathConfiguration = configuration;
- }
-
- @Override
- public void destroy() {
- try {
- // NodeClient.close() is a noop, no need to call it here
- nodeClient = null;
- logger.info("Closing elasticSearch node");
- if (node != null) {
- node.close();
- node = null;
- }
- } catch (final Exception e) {
- logger.error("Error closing ElasticSearch client: ", e);
- }
- }
-}
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/RestClients.java b/src/main/java/org/springframework/data/elasticsearch/client/RestClients.java
deleted file mode 100644
index 7500943a6a..0000000000
--- a/src/main/java/org/springframework/data/elasticsearch/client/RestClients.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2018-2020 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
- *
- * https://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.client;
-
-import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.time.Duration;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLContext;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpResponseInterceptor;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.config.RequestConfig.Builder;
-import org.apache.http.entity.ByteArrayEntity;
-import org.apache.http.message.BasicHeader;
-import org.apache.http.protocol.HttpContext;
-import org.elasticsearch.client.RestClient;
-import org.elasticsearch.client.RestClientBuilder;
-import org.elasticsearch.client.RestHighLevelClient;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.util.Assert;
-
-/**
- * Utility class for common access to Elasticsearch clients. {@link RestClients} consolidates set up routines for the
- * various drivers into a single place.
- *
- * @author Christoph Strobl
- * @author Mark Paluch
- * @author Huw Ayling-Miller
- * @author Henrique Amaral
- * @since 3.2
- */
-public final class RestClients {
-
- /**
- * Name of whose value can be used to correlate log messages for this request.
- */
- private static final String LOG_ID_ATTRIBUTE = RestClients.class.getName() + ".LOG_ID";
-
- private RestClients() {}
-
- /**
- * Start here to create a new client tailored to your needs.
- *
- * @return new instance of {@link ElasticsearchRestClient}.
- */
- public static ElasticsearchRestClient create(ClientConfiguration clientConfiguration) {
-
- Assert.notNull(clientConfiguration, "ClientConfiguration must not be null!");
-
- HttpHost[] httpHosts = formattedHosts(clientConfiguration.getEndpoints(), clientConfiguration.useSsl()).stream()
- .map(HttpHost::create).toArray(HttpHost[]::new);
- RestClientBuilder builder = RestClient.builder(httpHosts);
-
- if (clientConfiguration.getPathPrefix() != null) {
- builder.setPathPrefix(clientConfiguration.getPathPrefix());
- }
-
- HttpHeaders headers = clientConfiguration.getDefaultHeaders();
-
- if (!headers.isEmpty()) {
-
- Header[] httpHeaders = headers.toSingleValueMap().entrySet().stream()
- .map(it -> new BasicHeader(it.getKey(), it.getValue())).toArray(Header[]::new);
- builder.setDefaultHeaders(httpHeaders);
- }
-
- builder.setHttpClientConfigCallback(clientBuilder -> {
-
- Optional