Compare commits
149 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53ac53d146 | |||
| 6c656dff17 | |||
| cfa303c6a3 | |||
| 353c463aa8 | |||
| cb67bfb534 | |||
| 49cce254ce | |||
| 597409c4c2 | |||
| 66144d10f8 | |||
| e6aefc8180 | |||
| a7bd311106 | |||
| 003d75f022 | |||
| 535b407085 | |||
| 44919d4cbe | |||
| 6260f278ba | |||
| b3bd77aa46 | |||
| bea651bc95 | |||
| 175614cd94 | |||
| c4c73709c8 | |||
| e4fb2908c0 | |||
| 97c2524db5 | |||
| 6e3654866a | |||
| 5c25ca922e | |||
| bc7cfdf6e9 | |||
| 6f0263b3af | |||
| bcbe4534c2 | |||
| c999465876 | |||
| 5b87eeca69 | |||
| 54b1983eef | |||
| 68c9f04619 | |||
| 2c49dc75de | |||
| 828f588f3e | |||
| 21bc62b78c | |||
| b552128198 | |||
| 18d582af6a | |||
| fa3e7741f2 | |||
| e9e6da239e | |||
| 923d3b413d | |||
| 16f3addaf6 | |||
| 0e1a97a27a | |||
| df79368299 | |||
| 11b3cd5b3e | |||
| e06aca9594 | |||
| 5529af8f76 | |||
| c0dd082f4e | |||
| 9aa65560cc | |||
| 560d1e9153 | |||
| 78cbad5093 | |||
| be3aee93fb | |||
| fb986e17f8 | |||
| 3911b69869 | |||
| b49fedaafc | |||
| 087f3a80c5 | |||
| 46e997b81d | |||
| 1f5747294e | |||
| 92b6f28e31 | |||
| 646f07c42b | |||
| 875ba54d33 | |||
| 80b406ea22 | |||
| 9d987cbcc9 | |||
| 1505dd5129 | |||
| 6697755b45 | |||
| e49bb63df4 | |||
| 006cda6de6 | |||
| f51efa2cad | |||
| 6e30801a59 | |||
| e64d0ada62 | |||
| 7f7cf3f52e | |||
| 55d470fc91 | |||
| b7290b5d9c | |||
| 40414f0bde | |||
| cb71caa504 | |||
| ed9abce7af | |||
| 12ddb74fae | |||
| 6324b72707 | |||
| 6e49980c7c | |||
| f9509f2696 | |||
| 7f53944e1b | |||
| a9d2aaa93d | |||
| 158f5fc342 | |||
| 6268133506 | |||
| 923787c2d1 | |||
| 62fcbd44fa | |||
| 77ba620fc6 | |||
| 06704d974d | |||
| 897cb0a957 | |||
| a8557a36dc | |||
| 2678cdc7b6 | |||
| eb42312ebe | |||
| af13fe0247 | |||
| e81810c0d7 | |||
| e9c7c0ee95 | |||
| 3a4425053e | |||
| 09984f86e6 | |||
| 710526c5f6 | |||
| 1acd392af7 | |||
| 76fe240a24 | |||
| e298bc9f7a | |||
| 49d5dee5aa | |||
| df6a127629 | |||
| 08a1ef3a28 | |||
| 62a34cf09c | |||
| cc5f149c5a | |||
| 0728c8e4aa | |||
| ebbe242a72 | |||
| 0ce9a1c400 | |||
| 22763d17a7 | |||
| 9870de1e77 | |||
| 8c9d9ae1e7 | |||
| 945179e4eb | |||
| ea38ef1d41 | |||
| acbfba94ac | |||
| 5a0f556a3b | |||
| a07ac3c93d | |||
| 9d025dd469 | |||
| 925921f174 | |||
| 2f0a259045 | |||
| 9ffcb092db | |||
| 0e5af90581 | |||
| 95059b3282 | |||
| 1ae6301c2f | |||
| 2366f67bba | |||
| 6f424318ec | |||
| 300fe2ac8b | |||
| 1fdee7399f | |||
| ace17b9751 | |||
| 42383624ea | |||
| 35e7b45f1a | |||
| 89f60f2356 | |||
| fa979249fc | |||
| 8b43af2d33 | |||
| 64f88ae9ac | |||
| 15f086359d | |||
| 78ea67b6a6 | |||
| 6d0825b121 | |||
| 846344891d | |||
| f9f64e6b39 | |||
| 7fe4d8e1a4 | |||
| bd87dae1a3 | |||
| ea62cf0abd | |||
| cb77b328ae | |||
| 5568c7bbc4 | |||
| 03591326d7 | |||
| a94b74c877 | |||
| 944e7e81dd | |||
| 5f297f1dc3 | |||
| 028239fbdb | |||
| 01d2d24916 | |||
| 4f159d5de5 | |||
| 00f13ac3e9 |
@@ -0,0 +1,83 @@
|
||||
= Spring Data for Elasticsearch image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-elasticsearch%2Fmain&subject=Build[link=https://jenkins.spring.io/view/SpringData/job/spring-data-elasticsearch/] https://gitter.im/spring-projects/spring-data[image:https://badges.gitter.im/spring-projects/spring-data.svg[Gitter]] image:https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A["Revved up by Develocity", link="https://ge.spring.io/scans?search.rootProjectNames=Spring Data Elasticsearch"]
|
||||
|
||||
The primary goal of the https://projects.spring.io/spring-data[Spring Data] project is to make it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services.
|
||||
|
||||
The Spring Data Elasticsearch project provides integration with the https://www.elastic.co/[Elasticsearch] search engine.
|
||||
Key functional areas of Spring Data Elasticsearch are a POJO centric model for interacting with Elasticsearch Documents and easily writing a Repository style data access layer.
|
||||
|
||||
This project is lead and maintained by the community.
|
||||
|
||||
== Features
|
||||
|
||||
* Spring configuration support using Java based `@Configuration` classes or an XML namespace for an ES client instances.
|
||||
* `ElasticsearchOperations` class and implementations that increases productivity performing common ES operations.
|
||||
Includes integrated object mapping between documents and POJOs.
|
||||
* Feature Rich Object Mapping integrated with Spring’s Conversion Service
|
||||
* Annotation based mapping metadata
|
||||
* Automatic implementation of `Repository` interfaces including support for custom search methods.
|
||||
* CDI support for repositories
|
||||
|
||||
include::https://raw.githubusercontent.com/spring-projects/spring-data-build/refs/heads/main/etc/readme/code-of-conduct.adoc[]
|
||||
|
||||
== Getting Started
|
||||
|
||||
Here is a quick teaser of an application using Spring Data Repositories in Java:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface PersonRepository extends CrudRepository<Person, Long> {
|
||||
|
||||
List<Person> findByLastname(String lastname);
|
||||
|
||||
List<Person> findByFirstnameLike(String firstname);
|
||||
}
|
||||
|
||||
@Service
|
||||
public class MyService {
|
||||
|
||||
private final PersonRepository repository;
|
||||
|
||||
public MyService(PersonRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public void doWork() {
|
||||
|
||||
repository.deleteAll();
|
||||
|
||||
Person person = new Person();
|
||||
person.setFirstname("Oliver");
|
||||
person.setLastname("Gierke");
|
||||
repository.save(person);
|
||||
|
||||
List<Person> lastNameResults = repository.findByLastname("Gierke");
|
||||
List<Person> firstNameResults = repository.findByFirstnameLike("Oli");
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
=== Using the RestClient
|
||||
|
||||
Please check the https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.configuration[official documentation].
|
||||
|
||||
include::https://raw.githubusercontent.com/spring-projects/spring-data-build/refs/heads/main/etc/readme/dependencies.adoc[]
|
||||
|
||||
**Compatibility Matrix**
|
||||
|
||||
The compatibility between Spring Data Elasticsearch, Elasticsearch client drivers and Spring Boot versions can be found in the https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#preface.versions[reference documentation].
|
||||
|
||||
To use the Release candidate versions of the upcoming major version, use our Maven milestone repository and declare the appropriate dependency version:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>${version}.RCx</version> <!-- x being 1, 2, ... -->
|
||||
</dependency>
|
||||
----
|
||||
|
||||
include::https://raw.githubusercontent.com/spring-projects/spring-data-build/refs/heads/main/etc/readme/getting-help.adoc[]
|
||||
|
||||
include::https://raw.githubusercontent.com/spring-projects/spring-data-build/refs/heads/main/etc/readme/license.adoc[]
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# GitHub Actions for CodeQL Scanning
|
||||
|
||||
name: "CodeQL Advanced"
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule
|
||||
- cron: '0 5 * * *'
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
codeql-analysis-call:
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
uses: spring-io/github-actions/.github/workflows/codeql-analysis.yml@1
|
||||
@@ -0,0 +1,45 @@
|
||||
# GitHub Actions to automate GitHub issues for Spring Data Project Management
|
||||
|
||||
name: Spring Data GitHub Issues
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited, reopened]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_target:
|
||||
types: [opened, edited, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
Inbox:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'spring-projects' && (github.event.action == 'opened' || github.event.action == 'reopened') && github.event.pull_request == null && !contains(join(github.event.issue.labels.*.name, ', '), 'dependency-upgrade') && !contains(github.event.issue.title, 'Release ')
|
||||
steps:
|
||||
- name: Create or Update Issue Card
|
||||
uses: actions/add-to-project@v1.0.2
|
||||
with:
|
||||
project-url: https://github.com/orgs/spring-projects/projects/25
|
||||
github-token: ${{ secrets.GH_ISSUES_TOKEN_SPRING_DATA }}
|
||||
Pull-Request:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'spring-projects' && (github.event.action == 'opened' || github.event.action == 'reopened') && github.event.pull_request != null
|
||||
steps:
|
||||
- name: Create or Update Pull Request Card
|
||||
uses: actions/add-to-project@v1.0.2
|
||||
with:
|
||||
project-url: https://github.com/orgs/spring-projects/projects/25
|
||||
github-token: ${{ secrets.GH_ISSUES_TOKEN_SPRING_DATA }}
|
||||
Feedback-Provided:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'spring-projects' && github.event_name == 'issue_comment' && github.event.action == 'created' && github.actor != 'spring-projects-issues' && github.event.pull_request == null && github.event.issue.state == 'open' && contains(toJSON(github.event.issue.labels), 'waiting-for-feedback')
|
||||
steps:
|
||||
- name: Update Project Card
|
||||
uses: actions/add-to-project@v1.0.2
|
||||
with:
|
||||
project-url: https://github.com/orgs/spring-projects/projects/25
|
||||
github-token: ${{ secrets.GH_ISSUES_TOKEN_SPRING_DATA }}
|
||||
@@ -33,3 +33,4 @@ node
|
||||
package-lock.json
|
||||
|
||||
.mvn/.develocity
|
||||
/src/test/resources/testcontainers-local.properties
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
<extension>
|
||||
<groupId>io.spring.develocity.conventions</groupId>
|
||||
<artifactId>develocity-conventions-maven-extension</artifactId>
|
||||
<version>0.0.19</version>
|
||||
<version>0.0.22</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
|
||||
--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
|
||||
--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
|
||||
--add-opens=java.base/java.util=ALL-UNNAMED
|
||||
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED
|
||||
--add-opens=java.base/java.text=ALL-UNNAMED
|
||||
--add-opens=java.desktop/java.awt.font=ALL-UNNAMED
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
#Thu Nov 07 09:47:28 CET 2024
|
||||
#Thu Jul 17 13:59:56 CEST 2025
|
||||
wrapperUrl=https\://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
|
||||
|
||||
Vendored
+1
-1
@@ -9,7 +9,7 @@ pipeline {
|
||||
|
||||
triggers {
|
||||
pollSCM 'H/10 * * * *'
|
||||
upstream(upstreamProjects: "spring-data-commons/main", threshold: hudson.model.Result.SUCCESS)
|
||||
upstream(upstreamProjects: "spring-data-commons/4.0.x", threshold: hudson.model.Result.SUCCESS)
|
||||
}
|
||||
|
||||
options {
|
||||
|
||||
+2
-2
@@ -62,7 +62,7 @@ public class MyService {
|
||||
|
||||
=== Using the RestClient
|
||||
|
||||
Please check the [official documentation](https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.configuration).
|
||||
Please check the https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.configuration[official documentation].
|
||||
|
||||
=== Maven configuration
|
||||
|
||||
@@ -168,7 +168,7 @@ Building the documentation builds also the project without running tests.
|
||||
$ ./mvnw clean install -Pantora
|
||||
----
|
||||
|
||||
The generated documentation is available from `target/antora/site/index.html`.
|
||||
The generated documentation is available from `target/site/index.html`.
|
||||
|
||||
== Examples
|
||||
|
||||
|
||||
+11
-5
@@ -1,9 +1,15 @@
|
||||
# Security Policy
|
||||
= Security Policy
|
||||
|
||||
## Supported Versions
|
||||
== Reporting a Vulnerability
|
||||
|
||||
Please see the https://spring.io/projects/spring-data-elasticsearch[Spring Data Elasticsearch] project page for supported versions.
|
||||
Please, https://github.com/spring-projects/security-advisories/security/advisories/new[open a draft security advisory] if you need to disclose and discuss a security issue in private with the Spring Data team.
|
||||
Note that we only accept reports against https://spring.io/projects/spring-data#support[supported versions].
|
||||
|
||||
## Reporting a Vulnerability
|
||||
For more details, check out our https://spring.io/security-policy[security policy].
|
||||
|
||||
Please don't raise security vulnerabilities here. Head over to https://pivotal.io/security to learn how to disclose them responsibly.
|
||||
== JAR signing
|
||||
|
||||
Spring Data JARs released on Maven Central are signed.
|
||||
You'll find more information about the key here: https://spring.io/GPG-KEY-spring.txt
|
||||
|
||||
Versions released prior to 2023 may be signed with a different key.
|
||||
|
||||
+9
-12
@@ -1,28 +1,25 @@
|
||||
# Java versions
|
||||
java.main.tag=17.0.13_11-jdk-focal
|
||||
java.next.tag=23.0.1_11-jdk-noble
|
||||
java.main.tag=25-jdk-noble
|
||||
java.next.tag=25-jdk-noble
|
||||
|
||||
# Docker container images - standard
|
||||
docker.java.main.image=library/eclipse-temurin:${java.main.tag}
|
||||
docker.java.next.image=library/eclipse-temurin:${java.next.tag}
|
||||
|
||||
# Supported versions of MongoDB
|
||||
docker.mongodb.4.4.version=4.4.25
|
||||
docker.mongodb.5.0.version=5.0.21
|
||||
docker.mongodb.6.0.version=6.0.10
|
||||
docker.mongodb.7.0.version=7.0.2
|
||||
docker.mongodb.8.0.version=8.0.0
|
||||
docker.mongodb.6.0.version=6.0.23
|
||||
docker.mongodb.7.0.version=7.0.20
|
||||
docker.mongodb.8.0.version=8.0.9
|
||||
|
||||
# Supported versions of Redis
|
||||
docker.redis.6.version=6.2.13
|
||||
docker.redis.7.version=7.2.4
|
||||
|
||||
# Supported versions of Cassandra
|
||||
docker.cassandra.3.version=3.11.16
|
||||
docker.redis.8.version=8.2.2
|
||||
docker.valkey.8.version=8.1.1
|
||||
|
||||
# Docker environment settings
|
||||
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
|
||||
docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home
|
||||
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home --ulimit nofile=32000:32000
|
||||
docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home --ulimit nofile=32000:32000
|
||||
|
||||
# Credentials
|
||||
docker.registry=
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>5.4.0</version>
|
||||
<version>6.0.2</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>4.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>Spring Data Elasticsearch</name>
|
||||
@@ -18,16 +18,16 @@
|
||||
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
|
||||
|
||||
<properties>
|
||||
<springdata.commons>3.4.0</springdata.commons>
|
||||
<springdata.commons>4.0.2</springdata.commons>
|
||||
|
||||
<!-- version of the ElasticsearchClient -->
|
||||
<elasticsearch-java>8.15.3</elasticsearch-java>
|
||||
<elasticsearch-java>9.2.3</elasticsearch-java>
|
||||
<elasticsearch-rest-client>9.2.3</elasticsearch-rest-client>
|
||||
|
||||
<hoverfly>0.19.0</hoverfly>
|
||||
<log4j>2.23.1</log4j>
|
||||
<hoverfly>0.20.2</hoverfly>
|
||||
<log4j>2.25.1</log4j>
|
||||
<jsonassert>1.5.3</jsonassert>
|
||||
<testcontainers>1.20.0</testcontainers>
|
||||
<wiremock>3.9.1</wiremock>
|
||||
<wiremock>3.9.2</wiremock>
|
||||
|
||||
<java-module-name>spring.data.elasticsearch</java-module-name>
|
||||
|
||||
@@ -41,6 +41,15 @@
|
||||
</properties>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>sothawo</id>
|
||||
<name>Peter-Josef Meisch</name>
|
||||
<email>pj.meisch at sothawo.com</email>
|
||||
<roles>
|
||||
<role>Project Lead</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>biomedcentral</id>
|
||||
<name>BioMed Central Development Team</name>
|
||||
@@ -77,16 +86,32 @@
|
||||
</developerConnection>
|
||||
</scm>
|
||||
|
||||
<ciManagement>
|
||||
<system>Bamboo</system>
|
||||
<url>https://build.spring.io/browse/SPRINGDATAES</url>
|
||||
</ciManagement>
|
||||
|
||||
<issueManagement>
|
||||
<system>GitHub</system>
|
||||
<url>https://github.com/spring-projects/spring-data-elasticsearch/issues</url>
|
||||
</issueManagement>
|
||||
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.19.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.20.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring -->
|
||||
@@ -132,6 +157,27 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- the old RestCLient is an optional dependency for user that still want to use it-->
|
||||
<dependency>
|
||||
<groupId>org.elasticsearch.client</groupId>
|
||||
<artifactId>elasticsearch-rest-client</artifactId>
|
||||
<version>${elasticsearch-rest-client}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-core</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson JSON Mapper -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
@@ -217,6 +263,14 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>26.0.2-1</version>
|
||||
<scope>test</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
@@ -268,21 +322,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Upgrade xbean to 4.5 to prevent incompatibilities due to ASM versions -->
|
||||
<dependency>
|
||||
<groupId>org.apache.xbean</groupId>
|
||||
<artifactId>xbean-asm5-shaded</artifactId>
|
||||
<version>4.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
@@ -292,16 +331,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>elasticsearch</artifactId>
|
||||
<version>${testcontainers}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!--we need Murmur3Hash in a test, before 5.2 we had it from the old Elasticsearch dependency -->
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.15</version>
|
||||
<artifactId>testcontainers-elasticsearch</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ content:
|
||||
- url: https://github.com/spring-projects/spring-data-commons
|
||||
# Refname matching:
|
||||
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
|
||||
branches: [ main, 3.2.x ]
|
||||
branches: [ main ]
|
||||
start_path: src/main/antora
|
||||
asciidoc:
|
||||
attributes:
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
*** xref:migration-guides/migration-guide-5.1-5.2.adoc[]
|
||||
*** xref:migration-guides/migration-guide-5.2-5.3.adoc[]
|
||||
*** xref:migration-guides/migration-guide-5.3-5.4.adoc[]
|
||||
*** xref:migration-guides/migration-guide-5.4-5.5.adoc[]
|
||||
*** xref:migration-guides/migration-guide-5.5-6.0.adoc[]
|
||||
|
||||
|
||||
* xref:elasticsearch.adoc[]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Spring Data support for Elasticsearch contains a wide range of features:
|
||||
|
||||
* Spring configuration support for various xref:elasticsearch/clients.adoc[Elasticsearch clients].
|
||||
* The xref:elasticsearch/template.adoc[`ElasticsearchTemplate` and `ReactiveElasticsearchTemplate`] helper classes that provide object mapping between ES index operations and POJOs.
|
||||
* The xref:elasticsearch/template.adoc[`ElasticsearchTemplate` and `ReactiveElasticsearchTemplate`] helper classes that provide object mapping between Elasticsearch index operations and POJOs.
|
||||
* xref:elasticsearch/template.adoc#exception-translation[Exception translation] into Spring's portable {springDocsUrl}data-access.html#dao-exceptions[Data Access Exception Hierarchy].
|
||||
* Feature rich xref:elasticsearch/object-mapping.adoc[object mapping] integrated with _Spring's_ {springDocsUrl}core.html#core-convert[Conversion Service].
|
||||
* xref:elasticsearch/object-mapping.adoc#elasticsearch.mapping.meta-model.annotations[Annotation-based mapping] metadata that is extensible to support other metadata formats.
|
||||
|
||||
@@ -10,7 +10,7 @@ In order for the auditing code to be able to decide whether an entity instance i
|
||||
----
|
||||
package org.springframework.data.domain;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public interface Persistable<ID> {
|
||||
@Nullable
|
||||
@@ -81,5 +81,5 @@ class MyConfiguration {
|
||||
}
|
||||
----
|
||||
|
||||
If your code contains more than one `AuditorAware` bean for different types, you must provide the name of the bean to use as an argument to the `auditorAwareRef` parameter of the
|
||||
`@EnableElasticsearchAuditing` annotation.
|
||||
If your code contains more than one `AuditorAware` bean for different types, you must provide the name of the bean to use as an argument to the `auditorAwareRef` parameter of the
|
||||
`@EnableElasticsearchAuditing` annotation.
|
||||
|
||||
@@ -6,10 +6,10 @@ This chapter illustrates configuration and usage of supported Elasticsearch clie
|
||||
Spring Data Elasticsearch operates upon an Elasticsearch client (provided by Elasticsearch client libraries) that is connected to a single Elasticsearch node or a cluster.
|
||||
Although the Elasticsearch Client can be used directly to work with the cluster, applications using Spring Data Elasticsearch normally use the higher level abstractions of xref:elasticsearch/template.adoc[Elasticsearch Operations] and xref:elasticsearch/repositories/elasticsearch-repositories.adoc[Elasticsearch Repositories].
|
||||
|
||||
[[elasticsearch.clients.restclient]]
|
||||
== Imperative Rest Client
|
||||
[[elasticsearch.clients.rest5client]]
|
||||
== Imperative Rest5Client
|
||||
|
||||
To use the imperative (non-reactive) client, a configuration bean must be configured like this:
|
||||
To use the imperative (non-reactive) Rest5Client - the default client provided by the Elasticsearch Java client library from version 9 on -, a configuration bean must be configured like this:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
@@ -31,7 +31,7 @@ public class MyClientConfig extends ElasticsearchConfiguration {
|
||||
<.> for a detailed description of the builder methods see xref:elasticsearch/clients.adoc#elasticsearch.clients.configuration[Client Configuration]
|
||||
====
|
||||
|
||||
The javadoc:org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration[]] class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
|
||||
The javadoc:org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration[] class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
|
||||
|
||||
|
||||
The following beans can then be injected in other Spring components:
|
||||
@@ -39,7 +39,85 @@ The following beans can then be injected in other Spring components:
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.beans.factory.annotation.Autowired;@Autowired
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@Autowired
|
||||
ElasticsearchOperations operations; <.>
|
||||
|
||||
@Autowired
|
||||
ElasticsearchClient elasticsearchClient; <.>
|
||||
|
||||
@Autowired
|
||||
Rest5Client rest5Client; <.>
|
||||
|
||||
@Autowired
|
||||
JsonpMapper jsonpMapper; <.>
|
||||
----
|
||||
|
||||
<.> an implementation of javadoc:org.springframework.data.elasticsearch.core.ElasticsearchOperations[]
|
||||
<.> the `co.elastic.clients.elasticsearch.ElasticsearchClient` that is used.
|
||||
<.> the low level `Rest5Client` from the Elasticsearch libraries
|
||||
<.> the `JsonpMapper` user by the Elasticsearch `Transport`
|
||||
====
|
||||
|
||||
Basically one should just use the javadoc:org.springframework.data.elasticsearch.core.ElasticsearchOperations[] to interact with the Elasticsearch cluster.
|
||||
When using repositories, this instance is used under the hood as well.
|
||||
|
||||
[[elasticsearch.clients.restclient]]
|
||||
== Deprecated Imperative RestClient
|
||||
|
||||
To use the imperative (non-reactive) RestClient - deprecated since version 6 - , the following dependency needs to be added, adapt the correct version. The exclusion is needed in a Spring Boot application:
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.elasticsearch.client</groupId>
|
||||
<artifactId>elasticsearch-rest-client</artifactId>
|
||||
<version>${elasticsearch-client.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
----
|
||||
====
|
||||
|
||||
The configuration bean must then be configured like this:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.data.elasticsearch.client.elc.ElasticsearchLegacyRestClientConfiguration;
|
||||
|
||||
@Configuration
|
||||
public class MyClientConfig extends ElasticsearchLegacyRestClientConfiguration {
|
||||
|
||||
@Override
|
||||
public ClientConfiguration clientConfiguration() {
|
||||
return ClientConfiguration.builder() <.>
|
||||
.connectedTo("localhost:9200")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
<.> for a detailed description of the builder methods see xref:elasticsearch/clients.adoc#elasticsearch.clients.configuration[Client Configuration]
|
||||
====
|
||||
|
||||
The javadoc:org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration[] class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
|
||||
|
||||
|
||||
The following beans can then be injected in other Spring components:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@Autowired
|
||||
ElasticsearchOperations operations; <.>
|
||||
|
||||
@Autowired
|
||||
@@ -61,8 +139,8 @@ JsonpMapper jsonpMapper; <.>
|
||||
Basically one should just use the javadoc:org.springframework.data.elasticsearch.core.ElasticsearchOperations[] to interact with the Elasticsearch cluster.
|
||||
When using repositories, this instance is used under the hood as well.
|
||||
|
||||
[[elasticsearch.clients.reactiverestclient]]
|
||||
== Reactive Rest Client
|
||||
[[elasticsearch.clients.reactiverest5client]]
|
||||
== Reactive Rest5Client
|
||||
|
||||
When working with the reactive stack, the configuration must be derived from a different class:
|
||||
|
||||
@@ -93,6 +171,69 @@ The following beans can then be injected in other Spring components:
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@Autowired
|
||||
ReactiveElasticsearchOperations operations; <.>
|
||||
|
||||
@Autowired
|
||||
ReactiveElasticsearchClient elasticsearchClient; <.>
|
||||
|
||||
@Autowired
|
||||
Rest5Client rest5Client; <.>
|
||||
|
||||
@Autowired
|
||||
JsonpMapper jsonpMapper; <.>
|
||||
----
|
||||
|
||||
the following can be injected:
|
||||
|
||||
<.> an implementation of javadoc:org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations[]
|
||||
<.> the `org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient` that is used.
|
||||
This is a reactive implementation based on the Elasticsearch client implementation.
|
||||
<.> the low level `RestClient` from the Elasticsearch libraries
|
||||
<.> the `JsonpMapper` user by the Elasticsearch `Transport`
|
||||
====
|
||||
|
||||
Basically one should just use the javadoc:org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations[] to interact with the Elasticsearch cluster.
|
||||
When using repositories, this instance is used under the hood as well.
|
||||
|
||||
[[elasticsearch.clients.reactiverestclient]]
|
||||
== Deprecated Reactive RestClient
|
||||
|
||||
See the section above for the imperative code to use the deprecated RestClient for the necessary dependencies to include.
|
||||
|
||||
When working with the reactive stack, the configuration must be derived from a different class:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchLegacyRestClientConfiguration;
|
||||
|
||||
@Configuration
|
||||
public class MyClientConfig extends ReactiveElasticsearchLegacyRestClientConfiguration {
|
||||
|
||||
@Override
|
||||
public ClientConfiguration clientConfiguration() {
|
||||
return ClientConfiguration.builder() <.>
|
||||
.connectedTo("localhost:9200")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
<.> for a detailed description of the builder methods see xref:elasticsearch/clients.adoc#elasticsearch.clients.configuration[Client Configuration]
|
||||
====
|
||||
|
||||
The javadoc:org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration[] class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
|
||||
|
||||
The following beans can then be injected in other Spring components:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@Autowired
|
||||
ReactiveElasticsearchOperations operations; <.>
|
||||
|
||||
@@ -161,7 +302,7 @@ ClientConfiguration clientConfiguration = ClientConfiguration.builder()
|
||||
|
||||
<.> Define default headers, if they need to be customized
|
||||
<.> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
|
||||
<.> Optionally enable SSL.There exist overloads of this function that can take a `SSLContext` or as an alternative the fingerprint of the certificate as it is output by Elasticsearch 8 on startup.
|
||||
<.> Optionally enable SSL.There exist overloads of this function that can take a `SSLContext` or as an alternative the fingerprint of the certificate as it is output by Elasticsearch on startup (since version 8).
|
||||
<.> Optionally set a proxy.
|
||||
<.> Optionally set a path prefix, mostly used when different clusters a behind some reverse proxy.
|
||||
<.> Set the connection timeout.
|
||||
@@ -183,8 +324,25 @@ In the case this is not enough, the user can add callback functions by using the
|
||||
|
||||
The following callbacks are provided:
|
||||
|
||||
[[elasticsearch.clients.configuration.callbacks.rest5]]
|
||||
==== Configuration of the low level Elasticsearch `Rest5Client`:
|
||||
|
||||
This callback provides a `org.elasticsearch.client.RestClientBuilder` that can be used to configure the Elasticsearch
|
||||
`Rest5Client`:
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
ClientConfiguration.builder()
|
||||
.connectedTo("localhost:9200", "localhost:9291")
|
||||
.withClientConfigurer(Rest5Clients.ElasticsearchRest5ClientConfigurationCallback.from(restClientBuilder -> {
|
||||
// configure the Elasticsearch Rest5Client
|
||||
return restClientBuilder;
|
||||
}))
|
||||
.build();
|
||||
----
|
||||
====
|
||||
[[elasticsearch.clients.configuration.callbacks.rest]]
|
||||
==== Configuration of the low level Elasticsearch `RestClient`:
|
||||
==== Configuration of the deprecated low level Elasticsearch `RestClient`:
|
||||
|
||||
This callback provides a `org.elasticsearch.client.RestClientBuilder` that can be used to configure the Elasticsearch
|
||||
`RestClient`:
|
||||
@@ -193,7 +351,7 @@ This callback provides a `org.elasticsearch.client.RestClientBuilder` that can b
|
||||
----
|
||||
ClientConfiguration.builder()
|
||||
.connectedTo("localhost:9200", "localhost:9291")
|
||||
.withClientConfigurer(ElasticsearchClients.ElasticsearchRestClientConfigurationCallback.from(restClientBuilder -> {
|
||||
.withClientConfigurer(RestClients.ElasticsearchRestClientConfigurationCallback.from(restClientBuilder -> {
|
||||
// configure the Elasticsearch RestClient
|
||||
return restClientBuilder;
|
||||
}))
|
||||
@@ -201,10 +359,29 @@ ClientConfiguration.builder()
|
||||
----
|
||||
====
|
||||
|
||||
[[elasticsearch.clients.configurationcallbacks.httpasync]]
|
||||
==== Configuration of the HttpAsyncClient used by the low level Elasticsearch `RestClient`:
|
||||
[[elasticsearch.clients.configurationcallbacks.httpasync5]]
|
||||
==== Configuration of the HttpAsyncClient used by the low level Elasticsearch `Rest5Client`:
|
||||
|
||||
This callback provides a `org.apache.http.impl.nio.client.HttpAsyncClientBuilder` to configure the HttpCLient that is
|
||||
This callback provides a `org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder` to configure the HttpClient that is
|
||||
used by the `Rest5Client`.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
ClientConfiguration.builder()
|
||||
.connectedTo("localhost:9200", "localhost:9291")
|
||||
.withClientConfigurer(Rest5Clients.ElasticsearchHttpClientConfigurationCallback.from(httpAsyncClientBuilder -> {
|
||||
// configure the HttpAsyncClient
|
||||
return httpAsyncClientBuilder;
|
||||
}))
|
||||
.build();
|
||||
----
|
||||
====
|
||||
|
||||
[[elasticsearch.clients.configurationcallbacks.httpasync]]
|
||||
==== Configuration of the HttpAsyncClient used by the deprecated low level Elasticsearch `RestClient`:
|
||||
|
||||
This callback provides a `org.apache.http.impl.nio.client.HttpAsyncClientBuilder` to configure the HttpClient that is
|
||||
used by the `RestClient`.
|
||||
|
||||
====
|
||||
@@ -212,7 +389,7 @@ used by the `RestClient`.
|
||||
----
|
||||
ClientConfiguration.builder()
|
||||
.connectedTo("localhost:9200", "localhost:9291")
|
||||
.withClientConfigurer(ElasticsearchClients.ElasticsearchHttpClientConfigurationCallback.from(httpAsyncClientBuilder -> {
|
||||
.withClientConfigurer(RestClients.ElasticsearchHttpClientConfigurationCallback.from(httpAsyncClientBuilder -> {
|
||||
// configure the HttpAsyncClient
|
||||
return httpAsyncClientBuilder;
|
||||
}))
|
||||
@@ -220,15 +397,92 @@ ClientConfiguration.builder()
|
||||
----
|
||||
====
|
||||
|
||||
[[elasticsearch.clients.configurationcallbacks.connectionconfig]]
|
||||
==== Configuration of the ConnectionConfig used by the low level Elasticsearch `Rest5Client`:
|
||||
|
||||
This callback provides a `org.apache.hc.client5.http.config.ConnectionConfig` to configure the connection that is
|
||||
used by the `Rest5Client`.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
ClientConfiguration.builder()
|
||||
.connectedTo("localhost:9200", "localhost:9291")
|
||||
.withClientConfigurer(Rest5Clients.ElasticsearchConnectionConfigurationCallback.from(connectionConfigBuilder -> {
|
||||
// configure the connection
|
||||
return connectionConfigBuilder;
|
||||
}))
|
||||
.build();
|
||||
----
|
||||
====
|
||||
|
||||
[[elasticsearch.clients.configurationcallbacks.connectioncmanager]]
|
||||
==== Configuration of the ConnectionManager used by the low level Elasticsearch `Rest5Client`:
|
||||
|
||||
This callback provides a `org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder` to configure the connection manager that is
|
||||
used by the `Rest5Client`.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
ClientConfiguration.builder()
|
||||
.connectedTo("localhost:9200", "localhost:9291")
|
||||
.withClientConfigurer(Rest5Clients.ElasticsearchConnectionManagerCallback.from(connectionManagerBuilder -> {
|
||||
// configure the connection manager
|
||||
return connectionManagerBuilder;
|
||||
}))
|
||||
.build();
|
||||
----
|
||||
====
|
||||
|
||||
[[elasticsearch.clients.configurationcallbacks.requestconfig]]
|
||||
==== Configuration of the RequestConfig used by the low level Elasticsearch `Rest5Client`:
|
||||
|
||||
This callback provides a `org.apache.hc.client5.http.config.RequestConfig` to configure the RequestConfig that is
|
||||
used by the `Rest5Client`.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
ClientConfiguration.builder()
|
||||
.connectedTo("localhost:9200", "localhost:9291")
|
||||
.withClientConfigurer(Rest5Clients.ElasticsearchRequestConfigCallback.from(requestConfigBuilder -> {
|
||||
// configure the request config
|
||||
return requestConfigBuilder;
|
||||
}))
|
||||
.build();
|
||||
----
|
||||
====
|
||||
|
||||
[[elasticsearch.clients.logging]]
|
||||
== Client Logging
|
||||
|
||||
To see what is actually sent to and received from the server `Request` / `Response` logging on the transport level needs to be turned on as outlined in the snippet below.
|
||||
This can be enabled in the Elasticsearch client by setting the level of the `tracer` package to "trace" (see
|
||||
https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/java-rest-low-usage-logging.html)
|
||||
This can be enabled in the Elasticsearch client by setting the level of the `co.elastic.clients.transport.rest5_client.low_level.Request` package to "trace" (see
|
||||
https://www.elastic.co/docs/reference/elasticsearch/clients/java/transport/rest5-client/usage/logging)
|
||||
|
||||
.Enable transport layer logging
|
||||
[tabs]
|
||||
======
|
||||
XML::
|
||||
+
|
||||
[source,xml]
|
||||
----
|
||||
<logger name="tracer" level="trace"/>
|
||||
<logger name="co.elastic.clients.transport.rest5_client.low_level.Request" level="trace"/>
|
||||
----
|
||||
|
||||
yml::
|
||||
+
|
||||
[source,yml]
|
||||
----
|
||||
logging.level:
|
||||
co.elastic.clients.transport.rest5_client.low_level.Request: trace
|
||||
----
|
||||
|
||||
ini::
|
||||
+
|
||||
[source,ini]
|
||||
----
|
||||
logging.level.co.elastic.clients.transport.rest5_client.low_level.Request=trace
|
||||
----
|
||||
======
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
[[new-features]]
|
||||
= What's new
|
||||
|
||||
[[new-features.6-0-0]]
|
||||
== New in Spring Data Elasticsearch 6.0
|
||||
|
||||
* Upgrade to Spring 7
|
||||
* Switch to jspecify nullability annotations
|
||||
* Upgrade to Elasticsearch 9.2.2
|
||||
* Use the new Elasticsearch Rest5Client as default
|
||||
* Add support for SpEL expressions in the `settingPath` parameter of the `@Setting` annotation
|
||||
|
||||
|
||||
[[new-features.5-5-0]]
|
||||
== New in Spring Data Elasticsearch 5.5
|
||||
|
||||
* Upgrade to Elasticsearch 8.18.1.
|
||||
* Add support for the `@SearchTemplateQuery` annotation on repository methods.
|
||||
* Scripted field properties of type collection can be populated from scripts returning arrays.
|
||||
|
||||
[[new-features.5-4-0]]
|
||||
== New in Spring Data Elasticsearch 5.4
|
||||
|
||||
* Upgrade to Elasticsearch 8.15.3.
|
||||
* Allow to customize the mapped type name for `@InnerField` and `@Field` annotations.
|
||||
* Support for Elasticsearch SQL.
|
||||
* Add support for retrieving request executionDuration.
|
||||
* Add support for retrieving request executionDuration.
|
||||
|
||||
[[new-features.5-3-0]]
|
||||
== New in Spring Data Elasticsearch 5.3
|
||||
|
||||
@@ -11,7 +11,7 @@ When creating Elasticsearch indices with Spring Data Elasticsearch different ind
|
||||
The following arguments are available:
|
||||
|
||||
* `useServerConfiguration` does not send any settings parameters, so the Elasticsearch server configuration determines them.
|
||||
* `settingPath` refers to a JSON file defining the settings that must be resolvable in the classpath
|
||||
* `settingPath` refers to a JSON file defining the settings that must be resolvable in the classpath, it is possible to use a SpEL expression here
|
||||
* `shards` the number of shards to use, defaults to _1_
|
||||
* `replicas` the number of replicas, defaults to _1_
|
||||
* `refreshIntervall`, defaults to _"1s"_
|
||||
@@ -365,6 +365,8 @@ operations.putScript( <.>
|
||||
|
||||
To use a search template in a search query, Spring Data Elasticsearch provides the `SearchTemplateQuery`, an implementation of the `org.springframework.data.elasticsearch.core.query.Query` interface.
|
||||
|
||||
NOTE: Although `SearchTemplateQuery` is an implementation of the `Query` interface, not all of the functionality provided by the base class is available for a `SearchTemplateQuery` like setting a `Pageable` or a `Sort`. Values for this functionality must be added to the stored script like shown in the following example for paging parameters. If these values are set on the `Query` object, they will be ignored.
|
||||
|
||||
In the following code, we will add a call using a search template query to a custom repository implementation (see
|
||||
xref:repositories/custom-implementations.adoc[]) as an example how this can be integrated into a repository call.
|
||||
|
||||
@@ -449,4 +451,3 @@ var query = Query.findAll().addSort(Sort.by(order));
|
||||
About the filter query: It is not possible to use a `CriteriaQuery` here, as this query would be converted into a Elasticsearch nested query which does not work in the filter context. So only `StringQuery` or `NativeQuery` can be used here. When using one of these, like the term query above, the Elasticsearch field names must be used, so take care, when these are redefined with the `@Field(name="...")` definition.
|
||||
|
||||
For the definition of the order path and the nested paths, the Java entity property names should be used.
|
||||
|
||||
|
||||
+38
-8
@@ -10,7 +10,9 @@ The Elasticsearch module supports all basic query building feature as string que
|
||||
=== Declared queries
|
||||
|
||||
Deriving the query from the method name is not always sufficient and/or may result in unreadable method names.
|
||||
In this case one might make use of the `@Query` annotation (see xref:elasticsearch/repositories/elasticsearch-repository-queries.adoc#elasticsearch.query-methods.at-query[Using @Query Annotation] ).
|
||||
In this case one might make use of the `@Query` annotation (see xref:elasticsearch/repositories/elasticsearch-repository-queries.adoc#elasticsearch.query-methods.at-query[Using the @Query Annotation] ).
|
||||
|
||||
Another possibility is the use of a search-template, (see xref:elasticsearch/repositories/elasticsearch-repository-queries.adoc#elasticsearch.query-methods.at-searchtemplate-query[Using the @SearchTemplateQuery Annotation] ).
|
||||
|
||||
[[elasticsearch.query-methods.criterions]]
|
||||
== Query creation
|
||||
@@ -312,11 +314,13 @@ Repository methods can be defined to have the following return types for returni
|
||||
* `SearchPage<T>`
|
||||
|
||||
[[elasticsearch.query-methods.at-query]]
|
||||
== Using @Query Annotation
|
||||
== Using the @Query Annotation
|
||||
|
||||
.Declare query on the method using the `@Query` annotation.
|
||||
====
|
||||
The arguments passed to the method can be inserted into placeholders in the query string. The placeholders are of the form `?0`, `?1`, `?2` etc. for the first, second, third parameter and so on.
|
||||
The arguments passed to the method can be inserted into placeholders in the query string.
|
||||
The placeholders are of the form `?0`, `?1`, `?2` etc. for the first, second, third parameter and so on.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
||||
@@ -341,15 +345,20 @@ It will be sent to Easticsearch as value of the query element; if for example th
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
.`@Query` annotation on a method taking a Collection argument
|
||||
====
|
||||
A repository method such as
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Query("{\"ids\": {\"values\": ?0 }}")
|
||||
List<SampleEntity> getByIds(Collection<String> ids);
|
||||
----
|
||||
would make an https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-ids-query.html[IDs query] to return all the matching documents. So calling the method with a `List` of `["id1", "id2", "id3"]` would produce the query body
|
||||
|
||||
would make an https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-ids-query.html[IDs query] to return all the matching documents.
|
||||
So calling the method with a `List` of `["id1", "id2", "id3"]` would produce the query body
|
||||
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
@@ -367,8 +376,7 @@ would make an https://www.elastic.co/guide/en/elasticsearch/reference/current/qu
|
||||
|
||||
.Declare query on the method using the `@Query` annotation with SpEL expression.
|
||||
====
|
||||
https://docs.spring.io/spring-framework/reference/core/expressions.html[SpEL expression] is also supported when defining query in `@Query`.
|
||||
|
||||
{spring-framework-docs}/core/expressions.html[SpEL expression] is also supported when defining query in `@Query`.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -411,6 +419,7 @@ If for example the function is called with the parameter _John_, it would produc
|
||||
.accessing parameter property.
|
||||
====
|
||||
Supposing that we have the following class as query parameter type:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public record QueryParameter(String value) {
|
||||
@@ -444,7 +453,9 @@ We can pass `new QueryParameter("John")` as the parameter now, and it will produ
|
||||
|
||||
.accessing bean property.
|
||||
====
|
||||
https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/bean-references.html[Bean property] is also supported to access. Given that there is a bean named `queryParameter` of type `QueryParameter`, we can access the bean with symbol `@` rather than `#`, and there is no need to declare a parameter of type `QueryParameter` in the query method:
|
||||
{spring-framework-docs}/core/expressions/language-ref/bean-references.html[Bean property] is also supported to access.
|
||||
Given that there is a bean named `queryParameter` of type `QueryParameter`, we can access the bean with symbol `@` rather than `#`, and there is no need to declare a parameter of type `QueryParameter` in the query method:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
||||
@@ -493,6 +504,7 @@ interface BookRepository extends ElasticsearchRepository<Book, String> {
|
||||
NOTE: collection values should not be quoted when declaring the elasticsearch json query.
|
||||
|
||||
A collection of `names` like `List.of("name1", "name2")` will produce the following terms query:
|
||||
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
@@ -511,7 +523,7 @@ A collection of `names` like `List.of("name1", "name2")` will produce the follow
|
||||
|
||||
.access property in the `Collection` param.
|
||||
====
|
||||
https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/collection-projection.html[SpEL Collection Projection] is convenient to use when values in the `Collection` parameter is not plain `String`:
|
||||
{spring-framework-docs}/core/expressions/language-ref/collection-projection.html[SpEL Collection Projection] is convenient to use when values in the `Collection` parameter is not plain `String`:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -532,6 +544,7 @@ interface BookRepository extends ElasticsearchRepository<Book, String> {
|
||||
Page<Book> findByName(Collection<QueryParameter> parameters, Pageable pageable);
|
||||
}
|
||||
----
|
||||
|
||||
This will extract all the `value` property values as a new `Collection` from `QueryParameter` collection, thus takes the same effect as above.
|
||||
====
|
||||
|
||||
@@ -560,3 +573,20 @@ interface BookRepository extends ElasticsearchRepository<Book, String> {
|
||||
----
|
||||
|
||||
====
|
||||
|
||||
[[elasticsearch.query-methods.at-searchtemplate-query]]
|
||||
== Using the @SearchTemplateQuery Annotation
|
||||
|
||||
When using Elasticsearch search templates - (see xref:elasticsearch/misc.adoc#elasticsearch.misc.searchtemplates [Search Template support]) it is possible to specify that a repository method should use a template by adding the `@SearchTemplateQuery` annotation to that method.
|
||||
|
||||
Let's assume that there is a search template stored with the name "book-by-title" and this template need a parameter named "title", then a repository method using that search template can be defined like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
||||
@SearchTemplateQuery(id = "book-by-title")
|
||||
SearchHits<Book> findByTitle(String title);
|
||||
}
|
||||
----
|
||||
|
||||
The parameters of the repository method are sent to the seacrh template as key/value pairs where the key is the parameter name and the value is taken from the actual value when the method is invoked.
|
||||
|
||||
@@ -20,12 +20,12 @@ Whereas the birthdate is fix, the age depends on the time when a query is issued
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.ScriptedField;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
@@ -6,11 +6,13 @@ The following table shows the Elasticsearch and Spring versions that are used by
|
||||
[cols="^,^,^,^",options="header"]
|
||||
|===
|
||||
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework
|
||||
| 2024.1 (in development) | 5.3.x | 8.15.3 | 6.1.x
|
||||
| 2024.0 | 5.3.1 | 8.13.4 | 6.1.x
|
||||
| 2023.1 (Vaughan) | 5.2.x | 8.11.1 | 6.1.x
|
||||
| 2023.0 (Ullmann) | 5.1.x | 8.7.1 | 6.0.x
|
||||
| 2022.0 (Turing) | 5.0.xfootnote:oom[Out of maintenance] | 8.5.3 | 6.0.x
|
||||
| 2025.1 | 6.0.x | 9.2.3 | 7.0.x
|
||||
| 2025.0 | 5.5.x | 8.18.1 | 6.2.x
|
||||
| 2024.1 | 5.4.xfootnote:oom[Out of maintenance] | 8.15.5 | 6.1.x
|
||||
| 2024.0 | 5.3.xfootnote:oom[] | 8.13.4 | 6.1.x
|
||||
| 2023.1 (Vaughan) | 5.2.xfootnote:oom[] | 8.11.1 | 6.1.x
|
||||
| 2023.0 (Ullmann) | 5.1.xfootnote:oom[] | 8.7.1 | 6.0.x
|
||||
| 2022.0 (Turing) | 5.0.xfootnote:oom[] | 8.5.3 | 6.0.x
|
||||
| 2021.2 (Raj) | 4.4.xfootnote:oom[] | 7.17.3 | 5.3.x
|
||||
| 2021.1 (Q) | 4.3.xfootnote:oom[] | 7.15.2 | 5.3.x
|
||||
| 2021.0 (Pascal) | 4.2.xfootnote:oom[] | 7.12.0 | 5.3.x
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
[[elasticsearch-migration-guide-5.4-5.5]]
|
||||
= Upgrading from 5.4.x to 5.5.x
|
||||
|
||||
This section describes breaking changes from version 5.4.x to 5.5.x and how removed features can be replaced by new introduced features.
|
||||
|
||||
[[elasticsearch-migration-guide-5.4-5.5.breaking-changes]]
|
||||
== Breaking Changes
|
||||
|
||||
[[elasticsearch-migration-guide-5.4-5.5.deprecations]]
|
||||
== Deprecations
|
||||
|
||||
Some classes that probably are not used by a library user have been renamed, the classes with the old names are still there, but are deprecated:
|
||||
|
||||
|===
|
||||
|old name|new name
|
||||
|
||||
|ElasticsearchPartQuery|RepositoryPartQuery
|
||||
|ElasticsearchStringQuery|RepositoryStringQuery
|
||||
|ReactiveElasticsearchStringQuery|ReactiveRepositoryStringQuery
|
||||
|===
|
||||
|
||||
=== Removals
|
||||
|
||||
The following methods that had been deprecated since release 5.3 have been removed:
|
||||
```
|
||||
DocumentOperations.delete(Query, Class<?>)
|
||||
DocumentOperations.delete(Query, Class<?>, IndexCoordinates)
|
||||
ReactiveDocumentOperations.delete(Query, Class<?>)
|
||||
ReactiveDocumentOperations.delete(Query, Class<?>, IndexCoordinates)
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
[[elasticsearch-migration-guide-5.5-6.0]]
|
||||
= Upgrading from 5.5.x to 6.0.x
|
||||
|
||||
This section describes breaking changes from version 5.5.x to 6.0.x and how removed features can be replaced by new introduced features.
|
||||
|
||||
[[elasticsearch-migration-guide-5.5-6.0.breaking-changes]]
|
||||
== Breaking Changes
|
||||
|
||||
From version 6.0 on, Spring Data Elasticsearch uses the Elasticsearch 9 libraries and as default the new `Rest5Client` provided by these libraries. It is still possible to use the old `RestClient`, check xref:elasticsearch/clients.adoc[Elasticsearch clients] for information. The configuration callbacks for this `RestClient` have been moved from `org.springframework.data.elasticsearch.client.elc.ElasticsearchClients` to the `org.springframework.data.elasticsearch.client.elc.rest_client.RestClients` class.
|
||||
|
||||
In the `org.springframework.data.elasticsearch.core.query.UpdateQuery` class the type of the two fields `ifSeqNo` and `ifPrimaryTerm` has changed from `Integer` to `Long` to align with the normal query and the underlying Elasticsearch client.
|
||||
|
||||
[[elasticsearch-migration-guide-5.5-6.0.deprecations]]
|
||||
== Deprecations
|
||||
|
||||
All the code using the old `RestClient` has been moved to the `org.springframework.data.elasticsearch.client.elc.rest_client` package and has been deprecated. Users should switch to the classes from the `org.springframework.data.elasticsearch.client.elc.rest5_client` package.
|
||||
|
||||
|
||||
=== Removals
|
||||
|
||||
The `org.springframework.data.elasticsearch.core.query.ScriptType` enum has been removed. To distinguish between an inline and a stored script set the appropriate values in the `org.springframework.data.elasticsearch.core.query.ScriptData` record.
|
||||
|
||||
These methods have been removed because the Elasticsearch Client 9 does not support them anymore:
|
||||
```
|
||||
org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchIndicesClient.unfreeze(UnfreezeRequest)
|
||||
org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchIndicesClient.unfreeze(Function<UnfreezeRequest.Builder, ObjectBuilder<UnfreezeRequest>>)
|
||||
```
|
||||
@@ -3,19 +3,20 @@ prerelease: ${antora-component.prerelease}
|
||||
|
||||
asciidoc:
|
||||
attributes:
|
||||
copyright-year: ${current.year}
|
||||
version: ${project.version}
|
||||
springversionshort: ${spring.short}
|
||||
springversion: ${spring}
|
||||
attribute-missing: 'warn'
|
||||
commons: ${springdata.commons.docs}
|
||||
chomp: 'all'
|
||||
version: '${project.version}'
|
||||
copyright-year: '${current.year}'
|
||||
springversionshort: '${spring.short}'
|
||||
springversion: '${spring}'
|
||||
commons: '${springdata.commons.docs}'
|
||||
include-xml-namespaces: false
|
||||
spring-data-commons-docs-url: https://docs.spring.io/spring-data/commons/reference
|
||||
spring-data-commons-javadoc-base: https://docs.spring.io/spring-data/commons/docs/${springdata.commons}/api/
|
||||
springdocsurl: https://docs.spring.io/spring-framework/reference/{springversionshort}
|
||||
springjavadocurl: https://docs.spring.io/spring-framework/docs/${spring}/javadoc-api
|
||||
spring-data-commons-docs-url: '${documentation.baseurl}/spring-data/commons/reference/${springdata.commons.short}'
|
||||
spring-data-commons-javadoc-base: '{spring-data-commons-docs-url}/api/java'
|
||||
springdocsurl: '${documentation.baseurl}/spring-framework/reference/{springversionshort}'
|
||||
spring-framework-docs: '{springdocsurl}'
|
||||
springjavadocurl: '${documentation.spring-javadoc-url}'
|
||||
spring-framework-javadoc: '{springjavadocurl}'
|
||||
springhateoasversion: ${spring-hateoas}
|
||||
releasetrainversion: ${releasetrain}
|
||||
springhateoasversion: '${spring-hateoas}'
|
||||
releasetrainversion: '${releasetrain}'
|
||||
store: Elasticsearch
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
* Copyright 2020-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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,10 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Object describing an Elasticsearch error
|
||||
*
|
||||
@@ -26,8 +26,7 @@ import java.util.List;
|
||||
* @since 4.4
|
||||
*/
|
||||
public class ElasticsearchErrorCause {
|
||||
@Nullable
|
||||
private final String type;
|
||||
@Nullable private final String type;
|
||||
|
||||
private final String reason;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 the original author or authors.
|
||||
* Copyright 2019-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
* Copyright 2020-present 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,8 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.dao.UncategorizedDataAccessException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2024 the original author or authors.
|
||||
* Copyright 2023-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* Copyright 2024-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* Copyright 2024-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 the original author or authors.
|
||||
* Copyright 2019-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 the original author or authors.
|
||||
* Copyright 2013-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 the original author or authors.
|
||||
* Copyright 2013-present 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.
|
||||
@@ -107,17 +107,15 @@ public @interface Document {
|
||||
*/
|
||||
Alias[] aliases() default {};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Note: the enum value FORCE, which was introduced in 4.4 has been removed
|
||||
* again by Elasticsearch.
|
||||
* @since 4.3
|
||||
*/
|
||||
enum VersionType {
|
||||
INTERNAL("internal"), //
|
||||
EXTERNAL("external"), //
|
||||
EXTERNAL_GTE("external_gte"), //
|
||||
/**
|
||||
* @since 4.4
|
||||
*/
|
||||
FORCE("force");
|
||||
EXTERNAL_GTE("external_gte"); //
|
||||
|
||||
private final String esName;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 the original author or authors.
|
||||
* Copyright 2013-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* Copyright 2024-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 the original author or authors.
|
||||
* Copyright 2013-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* Copyright 2024-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 the original author or authors.
|
||||
* Copyright 2013-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2024 the original author or authors.
|
||||
* Copyright 2017-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
* Copyright 2020-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
* Copyright 2020-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
* Copyright 2020-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 the original author or authors.
|
||||
* Copyright 2019-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 the original author or authors.
|
||||
* Copyright 2019-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2024 the original author or authors.
|
||||
* Copyright 2023-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
* Copyright 2020-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
* Copyright 2020-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* Copyright 2024-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* Copyright 2024-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* Copyright 2024-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* Copyright 2024-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
* Copyright 2020-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 the original author or authors.
|
||||
* Copyright 2013-present 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.
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2025-present 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();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 the original author or authors.
|
||||
* Copyright 2019-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 the original author or authors.
|
||||
* Copyright 2019-present 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
@@ -41,7 +41,7 @@ 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();
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
@org.springframework.lang.NonNullApi
|
||||
@org.springframework.lang.NonNullFields
|
||||
@org.jspecify.annotations.NullMarked
|
||||
package org.springframework.data.elasticsearch.annotations;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2024 the original author or authors.
|
||||
* Copyright 2023-present 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,7 +17,7 @@ package org.springframework.data.elasticsearch.aot;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.data.util.ReactiveWrappers;
|
||||
import org.springframework.data.core.ReactiveWrappers;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2024 the original author or authors.
|
||||
* Copyright 2023-present 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,6 +19,7 @@ import static org.springframework.data.elasticsearch.aot.ElasticsearchAotPredica
|
||||
|
||||
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;
|
||||
@@ -32,7 +33,6 @@ import org.springframework.data.elasticsearch.core.event.ReactiveAfterConvertCal
|
||||
import org.springframework.data.elasticsearch.core.event.ReactiveAfterLoadCallback;
|
||||
import org.springframework.data.elasticsearch.core.event.ReactiveAfterSaveCallback;
|
||||
import org.springframework.data.elasticsearch.core.event.ReactiveBeforeConvertCallback;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
@org.springframework.lang.NonNullApi
|
||||
@org.springframework.lang.NonNullFields
|
||||
@org.jspecify.annotations.NullMarked
|
||||
package org.springframework.data.elasticsearch.aot;
|
||||
|
||||
+9
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 the original author or authors.
|
||||
* Copyright 2018-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,8 +25,8 @@ 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.support.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Configuration interface exposing common client configuration properties for Elasticsearch clients.
|
||||
@@ -127,10 +127,16 @@ public interface ClientConfiguration {
|
||||
Optional<String> getCaFingerprint();
|
||||
|
||||
/**
|
||||
* Returns the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if not configured.
|
||||
* Returns the {@link HostnameVerifier} to use. Must be {@link Optional#empty()} if not configured.
|
||||
* Cannot be used with the Rest5Client used from Elasticsearch 9 on as the underlying Apache http components 5 does not offer a way
|
||||
* to set this. Users that need a hostname verifier must integrate this in a SSLContext.
|
||||
* Returning a value here is ignored in this case
|
||||
*
|
||||
* @return the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if not configured.
|
||||
* @deprecated since 6.0
|
||||
*/
|
||||
// todo #3117 document this
|
||||
@Deprecated(since = "6.0", forRemoval=true)
|
||||
Optional<HostnameVerifier> getHostNameVerifier();
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 the original author or authors.
|
||||
* Copyright 2018-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,11 +25,11 @@ 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.data.elasticsearch.support.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 the original author or authors.
|
||||
* Copyright 2018-present 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.
|
||||
@@ -24,9 +24,8 @@ import java.util.function.Supplier;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Default {@link ClientConfiguration} implementation.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 the original author or authors.
|
||||
* Copyright 2018-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 the original author or authors.
|
||||
* Copyright 2018-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 the original author or authors.
|
||||
* Copyright 2018-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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.
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* Copyright 2024-present 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,10 +17,10 @@ package org.springframework.data.elasticsearch.client.elc;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* An abstract class that serves as a base for query processors. It provides a common interface and basic functionality
|
||||
@@ -38,8 +38,8 @@ public abstract class AbstractQueryProcessor {
|
||||
* @param queryConverter correct mapped field names and the values to the converted values.
|
||||
* @return an Elasticsearch {@literal query}.
|
||||
*/
|
||||
@Nullable
|
||||
static co.elastic.clients.elasticsearch._types.query_dsl.Query getEsQuery(@Nullable Query query,
|
||||
|
||||
static co.elastic.clients.elasticsearch._types.query_dsl.@Nullable Query getEsQuery(@Nullable Query query,
|
||||
@Nullable Consumer<Query> queryConverter) {
|
||||
if (query == null) {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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.
|
||||
|
||||
+8
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,8 @@ package org.springframework.data.elasticsearch.client.elc;
|
||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -36,7 +38,10 @@ public class AutoCloseableElasticsearchClient extends ElasticsearchClient implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
transport.close();
|
||||
public void close() throws IOException {
|
||||
// since Elasticsearch 8.16 the ElasticsearchClient implements (through ApiClient) the Closeable interface and
|
||||
// handles closing of the underlying transport. We now just call the base class, but keep this as we
|
||||
// have been implementing AutoCloseable since 4.4 and won't change that to a mere Closeable
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
@@ -31,13 +31,13 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.Field;
|
||||
import org.springframework.data.elasticsearch.core.query.HasChildQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.HasParentQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.InnerHitsQuery;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
||||
+156
-156
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
@@ -24,16 +24,9 @@ import co.elastic.clients.elasticsearch.core.search.Hit;
|
||||
import co.elastic.clients.elasticsearch.core.search.NestedIdentity;
|
||||
import co.elastic.clients.json.JsonData;
|
||||
import co.elastic.clients.json.JsonpMapper;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.data.elasticsearch.core.MultiGetItem;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.document.Explanation;
|
||||
@@ -41,9 +34,15 @@ import org.springframework.data.elasticsearch.core.document.NestedMetaData;
|
||||
import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
||||
import org.springframework.data.elasticsearch.core.document.SearchDocumentAdapter;
|
||||
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Utility class to adapt different Elasticsearch responses to a
|
||||
* {@link org.springframework.data.elasticsearch.core.document.Document}
|
||||
@@ -55,187 +54,188 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
final class DocumentAdapters {
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog(DocumentAdapters.class);
|
||||
private static final Log LOGGER = LogFactory.getLog(DocumentAdapters.class);
|
||||
|
||||
private DocumentAdapters() {}
|
||||
private DocumentAdapters() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SearchDocument} from a {@link Hit} returned by the Elasticsearch client.
|
||||
*
|
||||
* @param hit the hit object
|
||||
* @param jsonpMapper to map JsonData objects
|
||||
* @return the created {@link SearchDocument}
|
||||
*/
|
||||
public static SearchDocument from(Hit<?> hit, JsonpMapper jsonpMapper) {
|
||||
/**
|
||||
* Creates a {@link SearchDocument} from a {@link Hit} returned by the Elasticsearch client.
|
||||
*
|
||||
* @param hit the hit object
|
||||
* @param jsonpMapper to map JsonData objects
|
||||
* @return the created {@link SearchDocument}
|
||||
*/
|
||||
public static SearchDocument from(Hit<?> hit, JsonpMapper jsonpMapper) {
|
||||
|
||||
Assert.notNull(hit, "hit must not be null");
|
||||
Assert.notNull(hit, "hit must not be null");
|
||||
|
||||
Map<String, List<String>> highlightFields = hit.highlight();
|
||||
Map<String, List<String>> highlightFields = hit.highlight();
|
||||
|
||||
Map<String, SearchDocumentResponse> innerHits = new LinkedHashMap<>();
|
||||
hit.innerHits().forEach((name, innerHitsResult) -> {
|
||||
// noinspection ReturnOfNull
|
||||
innerHits.put(name, SearchDocumentResponseBuilder.from(innerHitsResult.hits(), null, null, null, 0, null, null,
|
||||
searchDocument -> null, jsonpMapper));
|
||||
});
|
||||
Map<String, SearchDocumentResponse> innerHits = new LinkedHashMap<>();
|
||||
hit.innerHits().forEach((name, innerHitsResult) -> {
|
||||
// noinspection ReturnOfNull
|
||||
innerHits.put(name, SearchDocumentResponseBuilder.from(innerHitsResult.hits(), null, null, null, 0, null, null,
|
||||
searchDocument -> null, jsonpMapper));
|
||||
});
|
||||
|
||||
NestedMetaData nestedMetaData = from(hit.nested());
|
||||
NestedMetaData nestedMetaData = from(hit.nested());
|
||||
|
||||
Explanation explanation = from(hit.explanation());
|
||||
Explanation explanation = from(hit.explanation());
|
||||
|
||||
List<String> matchedQueries = hit.matchedQueries();
|
||||
Map<String, Double> matchedQueries = hit.matchedQueries();
|
||||
|
||||
Function<Map<String, JsonData>, EntityAsMap> fromFields = fields -> {
|
||||
StringBuilder sb = new StringBuilder("{");
|
||||
final boolean[] firstField = { true };
|
||||
hit.fields().forEach((key, jsonData) -> {
|
||||
if (!firstField[0]) {
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append('"').append(key).append("\":") //
|
||||
.append(jsonData.toJson(jsonpMapper).toString());
|
||||
firstField[0] = false;
|
||||
});
|
||||
sb.append('}');
|
||||
return new EntityAsMap().fromJson(sb.toString());
|
||||
};
|
||||
Function<Map<String, JsonData>, EntityAsMap> fromFields = fields -> {
|
||||
StringBuilder sb = new StringBuilder("{");
|
||||
final boolean[] firstField = {true};
|
||||
hit.fields().forEach((key, jsonData) -> {
|
||||
if (!firstField[0]) {
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append('"').append(key).append("\":") //
|
||||
.append(jsonData.toJson(jsonpMapper).toString());
|
||||
firstField[0] = false;
|
||||
});
|
||||
sb.append('}');
|
||||
return new EntityAsMap().fromJson(sb.toString());
|
||||
};
|
||||
|
||||
EntityAsMap hitFieldsAsMap = fromFields.apply(hit.fields());
|
||||
EntityAsMap hitFieldsAsMap = fromFields.apply(hit.fields());
|
||||
|
||||
Map<String, List<Object>> documentFields = new LinkedHashMap<>();
|
||||
hitFieldsAsMap.forEach((key, value) -> {
|
||||
if (value instanceof List) {
|
||||
// noinspection unchecked
|
||||
documentFields.put(key, (List<Object>) value);
|
||||
} else {
|
||||
documentFields.put(key, Collections.singletonList(value));
|
||||
}
|
||||
});
|
||||
Map<String, List<Object>> documentFields = new LinkedHashMap<>();
|
||||
hitFieldsAsMap.forEach((key, value) -> {
|
||||
if (value instanceof List) {
|
||||
// noinspection unchecked
|
||||
documentFields.put(key, (List<Object>) value);
|
||||
} else {
|
||||
documentFields.put(key, Collections.singletonList(value));
|
||||
}
|
||||
});
|
||||
|
||||
Document document;
|
||||
Object source = hit.source();
|
||||
if (source == null) {
|
||||
document = Document.from(hitFieldsAsMap);
|
||||
} else {
|
||||
if (source instanceof EntityAsMap entityAsMap) {
|
||||
document = Document.from(entityAsMap);
|
||||
} else if (source instanceof JsonData jsonData) {
|
||||
document = Document.from(jsonData.to(EntityAsMap.class));
|
||||
} else {
|
||||
Document document;
|
||||
Object source = hit.source();
|
||||
if (source == null) {
|
||||
document = Document.from(hitFieldsAsMap);
|
||||
} else {
|
||||
if (source instanceof EntityAsMap entityAsMap) {
|
||||
document = Document.from(entityAsMap);
|
||||
} else if (source instanceof JsonData jsonData) {
|
||||
document = Document.from(jsonData.to(EntityAsMap.class));
|
||||
} else {
|
||||
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn(String.format("Cannot map from type " + source.getClass().getName()));
|
||||
}
|
||||
document = Document.create();
|
||||
}
|
||||
}
|
||||
document.setIndex(hit.index());
|
||||
document.setId(hit.id());
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn(String.format("Cannot map from type " + source.getClass().getName()));
|
||||
}
|
||||
document = Document.create();
|
||||
}
|
||||
}
|
||||
document.setIndex(hit.index());
|
||||
document.setId(hit.id());
|
||||
|
||||
if (hit.version() != null) {
|
||||
document.setVersion(hit.version());
|
||||
}
|
||||
document.setSeqNo(hit.seqNo() != null && hit.seqNo() >= 0 ? hit.seqNo() : -2); // -2 was the default value in the
|
||||
// old client
|
||||
document.setPrimaryTerm(hit.primaryTerm() != null && hit.primaryTerm() > 0 ? hit.primaryTerm() : 0);
|
||||
if (hit.version() != null) {
|
||||
document.setVersion(hit.version());
|
||||
}
|
||||
document.setSeqNo(hit.seqNo() != null && hit.seqNo() >= 0 ? hit.seqNo() : -2); // -2 was the default value in the
|
||||
// old client
|
||||
document.setPrimaryTerm(hit.primaryTerm() != null && hit.primaryTerm() > 0 ? hit.primaryTerm() : 0);
|
||||
|
||||
float score = hit.score() != null ? hit.score().floatValue() : Float.NaN;
|
||||
return new SearchDocumentAdapter(document, score, hit.sort().stream().map(TypeUtils::toObject).toArray(),
|
||||
documentFields, highlightFields, innerHits, nestedMetaData, explanation, matchedQueries, hit.routing());
|
||||
}
|
||||
float score = hit.score() != null ? hit.score().floatValue() : Float.NaN;
|
||||
return new SearchDocumentAdapter(document, score, hit.sort().stream().map(TypeUtils::toObject).toArray(),
|
||||
documentFields, highlightFields, innerHits, nestedMetaData, explanation, matchedQueries, hit.routing());
|
||||
}
|
||||
|
||||
public static SearchDocument from(CompletionSuggestOption<EntityAsMap> completionSuggestOption) {
|
||||
public static SearchDocument from(CompletionSuggestOption<EntityAsMap> completionSuggestOption) {
|
||||
|
||||
Document document = completionSuggestOption.source() != null ? Document.from(completionSuggestOption.source())
|
||||
: Document.create();
|
||||
document.setIndex(completionSuggestOption.index());
|
||||
Document document = completionSuggestOption.source() != null ? Document.from(completionSuggestOption.source())
|
||||
: Document.create();
|
||||
document.setIndex(completionSuggestOption.index());
|
||||
|
||||
if (completionSuggestOption.id() != null) {
|
||||
document.setId(completionSuggestOption.id());
|
||||
}
|
||||
if (completionSuggestOption.id() != null) {
|
||||
document.setId(completionSuggestOption.id());
|
||||
}
|
||||
|
||||
float score = completionSuggestOption.score() != null ? completionSuggestOption.score().floatValue() : Float.NaN;
|
||||
return new SearchDocumentAdapter(document, score, new Object[] {}, Collections.emptyMap(), Collections.emptyMap(),
|
||||
Collections.emptyMap(), null, null, null, completionSuggestOption.routing());
|
||||
}
|
||||
float score = completionSuggestOption.score() != null ? completionSuggestOption.score().floatValue() : Float.NaN;
|
||||
return new SearchDocumentAdapter(document, score, new Object[]{}, Collections.emptyMap(), Collections.emptyMap(),
|
||||
Collections.emptyMap(), null, null, null, completionSuggestOption.routing());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Explanation from(@Nullable co.elastic.clients.elasticsearch.core.explain.Explanation explanation) {
|
||||
@Nullable
|
||||
private static Explanation from(co.elastic.clients.elasticsearch.core.explain.@Nullable Explanation explanation) {
|
||||
|
||||
if (explanation == null) {
|
||||
return null;
|
||||
}
|
||||
List<Explanation> details = explanation.details().stream().map(DocumentAdapters::from).collect(Collectors.toList());
|
||||
return new Explanation(true, (double) explanation.value(), explanation.description(), details);
|
||||
}
|
||||
if (explanation == null) {
|
||||
return null;
|
||||
}
|
||||
List<Explanation> details = explanation.details().stream().map(DocumentAdapters::from).collect(Collectors.toList());
|
||||
return new Explanation(true, (double) explanation.value(), explanation.description(), details);
|
||||
}
|
||||
|
||||
private static Explanation from(ExplanationDetail explanationDetail) {
|
||||
private static Explanation from(ExplanationDetail explanationDetail) {
|
||||
|
||||
List<Explanation> details = explanationDetail.details().stream().map(DocumentAdapters::from)
|
||||
.collect(Collectors.toList());
|
||||
return new Explanation(null, (double) explanationDetail.value(), explanationDetail.description(), details);
|
||||
}
|
||||
List<Explanation> details = explanationDetail.details().stream().map(DocumentAdapters::from)
|
||||
.collect(Collectors.toList());
|
||||
return new Explanation(null, (double) explanationDetail.value(), explanationDetail.description(), details);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static NestedMetaData from(@Nullable NestedIdentity nestedIdentity) {
|
||||
@Nullable
|
||||
private static NestedMetaData from(@Nullable NestedIdentity nestedIdentity) {
|
||||
|
||||
if (nestedIdentity == null) {
|
||||
return null;
|
||||
}
|
||||
if (nestedIdentity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NestedMetaData child = from(nestedIdentity.nested());
|
||||
return NestedMetaData.of(nestedIdentity.field(), nestedIdentity.offset(), child);
|
||||
}
|
||||
NestedMetaData child = from(nestedIdentity.nested());
|
||||
return NestedMetaData.of(nestedIdentity.field(), nestedIdentity.offset(), child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Document} from a {@link GetResponse} where the found document is contained as {@link EntityAsMap}.
|
||||
*
|
||||
* @param getResponse the response instance
|
||||
* @return the Document
|
||||
*/
|
||||
@Nullable
|
||||
public static Document from(GetResult<EntityAsMap> getResponse) {
|
||||
/**
|
||||
* Creates a {@link Document} from a {@link GetResponse} where the found document is contained as {@link EntityAsMap}.
|
||||
*
|
||||
* @param getResponse the response instance
|
||||
* @return the Document
|
||||
*/
|
||||
@Nullable
|
||||
public static Document from(GetResult<EntityAsMap> getResponse) {
|
||||
|
||||
Assert.notNull(getResponse, "getResponse must not be null");
|
||||
Assert.notNull(getResponse, "getResponse must not be null");
|
||||
|
||||
if (!getResponse.found()) {
|
||||
return null;
|
||||
}
|
||||
if (!getResponse.found()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Document document = getResponse.source() != null ? Document.from(getResponse.source()) : Document.create();
|
||||
document.setIndex(getResponse.index());
|
||||
document.setId(getResponse.id());
|
||||
Document document = getResponse.source() != null ? Document.from(getResponse.source()) : Document.create();
|
||||
document.setIndex(getResponse.index());
|
||||
document.setId(getResponse.id());
|
||||
|
||||
if (getResponse.version() != null) {
|
||||
document.setVersion(getResponse.version());
|
||||
}
|
||||
if (getResponse.version() != null) {
|
||||
document.setVersion(getResponse.version());
|
||||
}
|
||||
|
||||
if (getResponse.seqNo() != null) {
|
||||
document.setSeqNo(getResponse.seqNo());
|
||||
}
|
||||
if (getResponse.seqNo() != null) {
|
||||
document.setSeqNo(getResponse.seqNo());
|
||||
}
|
||||
|
||||
if (getResponse.primaryTerm() != null) {
|
||||
document.setPrimaryTerm(getResponse.primaryTerm());
|
||||
}
|
||||
if (getResponse.primaryTerm() != null) {
|
||||
document.setPrimaryTerm(getResponse.primaryTerm());
|
||||
}
|
||||
|
||||
return document;
|
||||
}
|
||||
return document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of {@link MultiGetItem}s from a {@link MgetResponse} where the data is contained as
|
||||
* {@link EntityAsMap} instances.
|
||||
*
|
||||
* @param mgetResponse the response instance
|
||||
* @return list of multiget items
|
||||
*/
|
||||
public static List<MultiGetItem<Document>> from(MgetResponse<EntityAsMap> mgetResponse) {
|
||||
/**
|
||||
* Creates a list of {@link MultiGetItem}s from a {@link MgetResponse} where the data is contained as
|
||||
* {@link EntityAsMap} instances.
|
||||
*
|
||||
* @param mgetResponse the response instance
|
||||
* @return list of multiget items
|
||||
*/
|
||||
public static List<MultiGetItem<Document>> from(MgetResponse<EntityAsMap> mgetResponse) {
|
||||
|
||||
Assert.notNull(mgetResponse, "mgetResponse must not be null");
|
||||
Assert.notNull(mgetResponse, "mgetResponse must not be null");
|
||||
|
||||
return mgetResponse.docs().stream() //
|
||||
.map(itemResponse -> MultiGetItem.of( //
|
||||
itemResponse.isFailure() ? null : from(itemResponse.result()), //
|
||||
ResponseConverter.getFailure(itemResponse)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return mgetResponse.docs().stream() //
|
||||
.map(itemResponse -> MultiGetItem.of( //
|
||||
itemResponse.isFailure() ? null : from(itemResponse.result()), //
|
||||
ResponseConverter.getFailure(itemResponse)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
@@ -22,8 +22,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.data.elasticsearch.core.AggregationsContainer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
* Copyright 2022-present 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,12 +19,12 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
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.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
||||
+117
-178
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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,44 +15,38 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.client.elc;
|
||||
|
||||
import static org.springframework.data.elasticsearch.client.elc.rest5_client.Rest5Clients.*;
|
||||
import static org.springframework.data.elasticsearch.client.elc.rest_client.RestClients.*;
|
||||
|
||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||
import co.elastic.clients.json.JsonpMapper;
|
||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||
import co.elastic.clients.transport.TransportOptions;
|
||||
import co.elastic.clients.transport.TransportUtils;
|
||||
import co.elastic.clients.transport.Version;
|
||||
import co.elastic.clients.transport.rest5_client.Rest5ClientOptions;
|
||||
import co.elastic.clients.transport.rest5_client.Rest5ClientTransport;
|
||||
import co.elastic.clients.transport.rest5_client.low_level.RequestOptions;
|
||||
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
|
||||
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
||||
import co.elastic.clients.transport.rest_client.RestClientTransport;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpRequestInterceptor;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.elasticsearch.client.RestClientBuilder;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.data.elasticsearch.support.VersionInfo;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Utility class to create the different Elasticsearch clients
|
||||
* Utility class to create the different Elasticsearch clients. The RestClient class is the one used in Elasticsearch
|
||||
* until version 9, it is still available, but it's use is deprecated. The Rest5Client class is the one that should be
|
||||
* used from Elasticsearch 9 on.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 4.4
|
||||
@@ -119,18 +113,32 @@ public final class ElasticsearchClients {
|
||||
*
|
||||
* @param restClient the underlying {@link RestClient}
|
||||
* @return the {@link ReactiveElasticsearchClient}
|
||||
* @deprecated since 6.0, use the version with a Rest5Client.
|
||||
*/
|
||||
@Deprecated(since = "6.0", forRemoval = true)
|
||||
public static ReactiveElasticsearchClient createReactive(RestClient restClient) {
|
||||
return createReactive(restClient, null, DEFAULT_JSONP_MAPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ReactiveElasticsearchClient}.
|
||||
*
|
||||
* @param rest5Client the underlying {@link RestClient}
|
||||
* @return the {@link ReactiveElasticsearchClient}
|
||||
*/
|
||||
public static ReactiveElasticsearchClient createReactive(Rest5Client rest5Client) {
|
||||
return createReactive(rest5Client, null, DEFAULT_JSONP_MAPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ReactiveElasticsearchClient}.
|
||||
*
|
||||
* @param restClient the underlying {@link RestClient}
|
||||
* @param transportOptions options to be added to each request.
|
||||
* @return the {@link ReactiveElasticsearchClient}
|
||||
* @deprecated since 6.0, use the version with a Rest5Client.
|
||||
*/
|
||||
@Deprecated(since = "6.0", forRemoval = true)
|
||||
public static ReactiveElasticsearchClient createReactive(RestClient restClient,
|
||||
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
||||
|
||||
@@ -139,6 +147,21 @@ public final class ElasticsearchClients {
|
||||
var transport = getElasticsearchTransport(restClient, REACTIVE_CLIENT, transportOptions, jsonpMapper);
|
||||
return createReactive(transport);
|
||||
}
|
||||
/**
|
||||
* Creates a new {@link ReactiveElasticsearchClient}.
|
||||
*
|
||||
* @param rest5Client the underlying {@link RestClient}
|
||||
* @param transportOptions options to be added to each request.
|
||||
* @return the {@link ReactiveElasticsearchClient}
|
||||
*/
|
||||
public static ReactiveElasticsearchClient createReactive(Rest5Client rest5Client,
|
||||
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
||||
|
||||
Assert.notNull(rest5Client, "restClient must not be null");
|
||||
|
||||
var transport = getElasticsearchTransport(rest5Client, REACTIVE_CLIENT, transportOptions, jsonpMapper);
|
||||
return createReactive(transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ReactiveElasticsearchClient} that uses the given {@link ElasticsearchTransport}.
|
||||
@@ -156,17 +179,21 @@ public final class ElasticsearchClients {
|
||||
|
||||
// region imperative client
|
||||
/**
|
||||
* Creates a new imperative {@link ElasticsearchClient}
|
||||
* Creates a new imperative {@link ElasticsearchClient}. This uses a RestClient, if the old RestClient is needed, this
|
||||
* must be created with the {@link org.springframework.data.elasticsearch.client.elc.rest_client.RestClients} class
|
||||
* and passed in as parameter.
|
||||
*
|
||||
* @param clientConfiguration configuration options, must not be {@literal null}.
|
||||
* @return the {@link ElasticsearchClient}
|
||||
*/
|
||||
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration) {
|
||||
return createImperative(getRestClient(clientConfiguration), null, DEFAULT_JSONP_MAPPER);
|
||||
return createImperative(getRest5Client(clientConfiguration), null, DEFAULT_JSONP_MAPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new imperative {@link ElasticsearchClient}
|
||||
* Creates a new imperative {@link ElasticsearchClient}. This uses a RestClient, if the old RestClient is needed, this
|
||||
* must be created with the {@link org.springframework.data.elasticsearch.client.elc.rest_client.RestClients} class
|
||||
* and passed in as parameter.
|
||||
*
|
||||
* @param clientConfiguration configuration options, must not be {@literal null}.
|
||||
* @param transportOptions options to be added to each request.
|
||||
@@ -174,7 +201,7 @@ public final class ElasticsearchClients {
|
||||
*/
|
||||
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration,
|
||||
TransportOptions transportOptions) {
|
||||
return createImperative(getRestClient(clientConfiguration), transportOptions, DEFAULT_JSONP_MAPPER);
|
||||
return createImperative(getRest5Client(clientConfiguration), transportOptions, DEFAULT_JSONP_MAPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,11 +209,23 @@ public final class ElasticsearchClients {
|
||||
*
|
||||
* @param restClient the RestClient to use
|
||||
* @return the {@link ElasticsearchClient}
|
||||
* @deprecated since 6.0, use the version with a Rest5Client.
|
||||
*/
|
||||
@Deprecated(since = "6.0", forRemoval = true)
|
||||
public static ElasticsearchClient createImperative(RestClient restClient) {
|
||||
return createImperative(restClient, null, DEFAULT_JSONP_MAPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new imperative {@link ElasticsearchClient}
|
||||
*
|
||||
* @param rest5Client the Rest5Client to use
|
||||
* @return the {@link ElasticsearchClient}
|
||||
*/
|
||||
public static ElasticsearchClient createImperative(Rest5Client rest5Client) {
|
||||
return createImperative(rest5Client, null, DEFAULT_JSONP_MAPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new imperative {@link ElasticsearchClient}
|
||||
*
|
||||
@@ -194,7 +233,9 @@ public final class ElasticsearchClients {
|
||||
* @param transportOptions options to be added to each request.
|
||||
* @param jsonpMapper the mapper for the transport to use
|
||||
* @return the {@link ElasticsearchClient}
|
||||
* @deprecated since 6.0, use the version with a Rest5Client.
|
||||
*/
|
||||
@Deprecated(since = "6.0", forRemoval = true)
|
||||
public static ElasticsearchClient createImperative(RestClient restClient, @Nullable TransportOptions transportOptions,
|
||||
JsonpMapper jsonpMapper) {
|
||||
|
||||
@@ -206,6 +247,27 @@ public final class ElasticsearchClients {
|
||||
return createImperative(transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new imperative {@link ElasticsearchClient}
|
||||
*
|
||||
* @param rest5Client the Rest5Client to use
|
||||
* @param transportOptions options to be added to each request.
|
||||
* @param jsonpMapper the mapper for the transport to use
|
||||
* @return the {@link ElasticsearchClient}
|
||||
* @since 6.0
|
||||
*/
|
||||
public static ElasticsearchClient createImperative(Rest5Client rest5Client,
|
||||
@Nullable TransportOptions transportOptions,
|
||||
JsonpMapper jsonpMapper) {
|
||||
|
||||
Assert.notNull(rest5Client, "restClient must not be null");
|
||||
|
||||
ElasticsearchTransport transport = getElasticsearchTransport(rest5Client, IMPERATIVE_CLIENT, transportOptions,
|
||||
jsonpMapper);
|
||||
|
||||
return createImperative(transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ElasticsearchClient} that uses the given {@link ElasticsearchTransport}.
|
||||
*
|
||||
@@ -220,96 +282,6 @@ public final class ElasticsearchClients {
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region low level RestClient
|
||||
private static RestClientOptions.Builder getRestClientOptionsBuilder(@Nullable TransportOptions transportOptions) {
|
||||
|
||||
if (transportOptions instanceof RestClientOptions restClientOptions) {
|
||||
return restClientOptions.toBuilder();
|
||||
}
|
||||
|
||||
var builder = new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder());
|
||||
|
||||
if (transportOptions != null) {
|
||||
transportOptions.headers().forEach(header -> builder.addHeader(header.getKey(), header.getValue()));
|
||||
transportOptions.queryParameters().forEach(builder::setParameter);
|
||||
builder.onWarnings(transportOptions.onWarnings());
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a low level {@link RestClient} for the given configuration.
|
||||
*
|
||||
* @param clientConfiguration must not be {@literal null}
|
||||
* @return the {@link RestClient}
|
||||
*/
|
||||
public static RestClient getRestClient(ClientConfiguration clientConfiguration) {
|
||||
return getRestClientBuilder(clientConfiguration).build();
|
||||
}
|
||||
|
||||
private static RestClientBuilder getRestClientBuilder(ClientConfiguration clientConfiguration) {
|
||||
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()) {
|
||||
builder.setDefaultHeaders(toHeaderArray(headers));
|
||||
}
|
||||
|
||||
builder.setHttpClientConfigCallback(clientBuilder -> {
|
||||
if (clientConfiguration.getCaFingerprint().isPresent()) {
|
||||
clientBuilder
|
||||
.setSSLContext(TransportUtils.sslContextFromCaFingerprint(clientConfiguration.getCaFingerprint().get()));
|
||||
}
|
||||
clientConfiguration.getSslContext().ifPresent(clientBuilder::setSSLContext);
|
||||
clientConfiguration.getHostNameVerifier().ifPresent(clientBuilder::setSSLHostnameVerifier);
|
||||
clientBuilder.addInterceptorLast(new CustomHeaderInjector(clientConfiguration.getHeadersSupplier()));
|
||||
|
||||
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
|
||||
Duration connectTimeout = clientConfiguration.getConnectTimeout();
|
||||
|
||||
if (!connectTimeout.isNegative()) {
|
||||
requestConfigBuilder.setConnectTimeout(Math.toIntExact(connectTimeout.toMillis()));
|
||||
}
|
||||
|
||||
Duration socketTimeout = clientConfiguration.getSocketTimeout();
|
||||
|
||||
if (!socketTimeout.isNegative()) {
|
||||
requestConfigBuilder.setSocketTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
||||
requestConfigBuilder.setConnectionRequestTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
||||
}
|
||||
|
||||
clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
|
||||
|
||||
clientConfiguration.getProxy().map(HttpHost::create).ifPresent(clientBuilder::setProxy);
|
||||
|
||||
for (ClientConfiguration.ClientConfigurationCallback<?> clientConfigurer : clientConfiguration
|
||||
.getClientConfigurers()) {
|
||||
if (clientConfigurer instanceof ElasticsearchHttpClientConfigurationCallback restClientConfigurationCallback) {
|
||||
clientBuilder = restClientConfigurationCallback.configure(clientBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
return clientBuilder;
|
||||
});
|
||||
|
||||
for (ClientConfiguration.ClientConfigurationCallback<?> clientConfigurationCallback : clientConfiguration
|
||||
.getClientConfigurers()) {
|
||||
if (clientConfigurationCallback instanceof ElasticsearchRestClientConfigurationCallback configurationCallback) {
|
||||
builder = configurationCallback.configure(builder);
|
||||
}
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Elasticsearch transport
|
||||
/**
|
||||
* Creates an {@link ElasticsearchTransport} that will use the given client that additionally is customized with a
|
||||
@@ -320,7 +292,9 @@ public final class ElasticsearchClients {
|
||||
* @param transportOptions options for the transport
|
||||
* @param jsonpMapper mapper for the transport
|
||||
* @return ElasticsearchTransport
|
||||
* @deprecated since 6.0, use the version taking a Rest5Client
|
||||
*/
|
||||
@Deprecated(since = "6.0", forRemoval = true)
|
||||
public static ElasticsearchTransport getElasticsearchTransport(RestClient restClient, String clientType,
|
||||
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
||||
|
||||
@@ -329,7 +303,7 @@ public final class ElasticsearchClients {
|
||||
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
||||
|
||||
TransportOptions.Builder transportOptionsBuilder = transportOptions != null ? transportOptions.toBuilder()
|
||||
: new RestClientOptions(RequestOptions.DEFAULT).toBuilder();
|
||||
: new RestClientOptions(org.elasticsearch.client.RequestOptions.DEFAULT, false).toBuilder();
|
||||
|
||||
RestClientOptions.Builder restClientOptionsBuilder = getRestClientOptionsBuilder(transportOptions);
|
||||
|
||||
@@ -353,70 +327,35 @@ public final class ElasticsearchClients {
|
||||
|
||||
return new RestClientTransport(restClient, jsonpMapper, restClientOptionsBuilder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link ElasticsearchTransport} that will use the given client that additionally is customized with a
|
||||
* header to contain the clientType
|
||||
*
|
||||
* @param rest5Client the client to use
|
||||
* @param clientType the client type to pass in each request as header
|
||||
* @param transportOptions options for the transport
|
||||
* @param jsonpMapper mapper for the transport
|
||||
* @return ElasticsearchTransport
|
||||
*/
|
||||
public static ElasticsearchTransport getElasticsearchTransport(Rest5Client rest5Client, String clientType,
|
||||
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
||||
|
||||
Assert.notNull(rest5Client, "restClient must not be null");
|
||||
Assert.notNull(clientType, "clientType must not be null");
|
||||
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
||||
|
||||
TransportOptions.Builder transportOptionsBuilder = transportOptions != null ? transportOptions.toBuilder()
|
||||
: new Rest5ClientOptions(RequestOptions.DEFAULT, false).toBuilder();
|
||||
|
||||
Rest5ClientOptions.Builder rest5ClientOptionsBuilder = getRest5ClientOptionsBuilder(transportOptions);
|
||||
|
||||
rest5ClientOptionsBuilder.addHeader(X_SPRING_DATA_ELASTICSEARCH_CLIENT,
|
||||
VersionInfo.clientVersions() + " / " + clientType);
|
||||
|
||||
return new Rest5ClientTransport(rest5Client, jsonpMapper, rest5ClientOptionsBuilder.build());
|
||||
}
|
||||
// endregion
|
||||
|
||||
private static List<String> formattedHosts(List<InetSocketAddress> hosts, boolean useSsl) {
|
||||
return hosts.stream().map(it -> (useSsl ? "https" : "http") + "://" + it.getHostString() + ':' + it.getPort())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static org.apache.http.Header[] toHeaderArray(HttpHeaders headers) {
|
||||
return headers.entrySet().stream() //
|
||||
.flatMap(entry -> entry.getValue().stream() //
|
||||
.map(value -> new BasicHeader(entry.getKey(), value))) //
|
||||
.toArray(org.apache.http.Header[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interceptor to inject custom supplied headers.
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
private record CustomHeaderInjector(Supplier<HttpHeaders> headersSupplier) implements HttpRequestInterceptor {
|
||||
|
||||
@Override
|
||||
public void process(HttpRequest request, HttpContext context) {
|
||||
HttpHeaders httpHeaders = headersSupplier.get();
|
||||
|
||||
if (httpHeaders != null && !httpHeaders.isEmpty()) {
|
||||
Arrays.stream(toHeaderArray(httpHeaders)).forEach(request::addHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationCallback} to configure
|
||||
* the Elasticsearch RestClient's Http client with a {@link HttpAsyncClientBuilder}
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
public interface ElasticsearchHttpClientConfigurationCallback
|
||||
extends ClientConfiguration.ClientConfigurationCallback<HttpAsyncClientBuilder> {
|
||||
|
||||
static ElasticsearchHttpClientConfigurationCallback from(
|
||||
Function<HttpAsyncClientBuilder, HttpAsyncClientBuilder> httpClientBuilderCallback) {
|
||||
|
||||
Assert.notNull(httpClientBuilderCallback, "httpClientBuilderCallback must not be null");
|
||||
|
||||
return httpClientBuilderCallback::apply;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationCallback} to configure
|
||||
* the RestClient client with a {@link RestClientBuilder}
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface ElasticsearchRestClientConfigurationCallback
|
||||
extends ClientConfiguration.ClientConfigurationCallback<RestClientBuilder> {
|
||||
|
||||
static ElasticsearchRestClientConfigurationCallback from(
|
||||
Function<RestClientBuilder, RestClientBuilder> restClientBuilderCallback) {
|
||||
|
||||
Assert.notNull(restClientBuilderCallback, "restClientBuilderCallback must not be null");
|
||||
|
||||
return restClientBuilderCallback::apply;
|
||||
}
|
||||
}
|
||||
// todo #3117 remove and document that ElasticsearchHttpClientConfigurationCallback has been move to RestClients.
|
||||
}
|
||||
|
||||
+16
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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,12 +20,13 @@ import co.elastic.clients.json.JsonpMapper;
|
||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||
import co.elastic.clients.transport.TransportOptions;
|
||||
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
||||
import co.elastic.clients.transport.rest5_client.Rest5ClientOptions;
|
||||
import co.elastic.clients.transport.rest5_client.low_level.RequestOptions;
|
||||
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
|
||||
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.data.elasticsearch.client.elc.rest5_client.Rest5Clients;
|
||||
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
@@ -38,7 +39,9 @@ import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
/**
|
||||
* Base class for a @{@link org.springframework.context.annotation.Configuration} class to set up the Elasticsearch
|
||||
* connection using the Elasticsearch Client. This class exposes different parts of the setup as Spring beans. Deriving
|
||||
* classes must provide the {@link ClientConfiguration} to use.
|
||||
* classes must provide the {@link ClientConfiguration} to use. From Version 6.0 on, this class uses the new Rest5Client
|
||||
* from Elasticsearch 9. The old implementation using the RestClient is still available under the name
|
||||
* {@link ElasticsearchLegacyRestClientConfiguration}.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 4.4
|
||||
@@ -60,27 +63,27 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
|
||||
* @return RestClient
|
||||
*/
|
||||
@Bean
|
||||
public RestClient elasticsearchRestClient(ClientConfiguration clientConfiguration) {
|
||||
public Rest5Client elasticsearchRest5Client(ClientConfiguration clientConfiguration) {
|
||||
|
||||
Assert.notNull(clientConfiguration, "clientConfiguration must not be null");
|
||||
|
||||
return ElasticsearchClients.getRestClient(clientConfiguration);
|
||||
return Rest5Clients.getRest5Client(clientConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the Elasticsearch transport to be used. The default implementation uses the {@link RestClient} bean and
|
||||
* Provides the Elasticsearch transport to be used. The default implementation uses the {@link Rest5Client} bean and
|
||||
* the {@link JsonpMapper} bean provided in this class.
|
||||
*
|
||||
* @return the {@link ElasticsearchTransport}
|
||||
* @since 5.2
|
||||
*/
|
||||
@Bean
|
||||
public ElasticsearchTransport elasticsearchTransport(RestClient restClient, JsonpMapper jsonpMapper) {
|
||||
public ElasticsearchTransport elasticsearchTransport(Rest5Client rest5Client, JsonpMapper jsonpMapper) {
|
||||
|
||||
Assert.notNull(restClient, "restClient must not be null");
|
||||
Assert.notNull(rest5Client, "restClient must not be null");
|
||||
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
||||
|
||||
return ElasticsearchClients.getElasticsearchTransport(restClient, ElasticsearchClients.IMPERATIVE_CLIENT,
|
||||
return ElasticsearchClients.getElasticsearchTransport(rest5Client, ElasticsearchClients.IMPERATIVE_CLIENT,
|
||||
transportOptions(), jsonpMapper);
|
||||
}
|
||||
|
||||
@@ -115,7 +118,7 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the JsonpMapper bean that is used in the {@link #elasticsearchTransport(RestClient, JsonpMapper)} method.
|
||||
* Provides the JsonpMapper bean that is used in the {@link #elasticsearchTransport(Rest5Client, JsonpMapper)} method.
|
||||
*
|
||||
* @return the {@link JsonpMapper} to use
|
||||
* @since 5.2
|
||||
@@ -135,6 +138,6 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
|
||||
* @return the options that should be added to every request. Must not be {@literal null}
|
||||
*/
|
||||
public TransportOptions transportOptions() {
|
||||
return new RestClientOptions(RequestOptions.DEFAULT);
|
||||
return new Rest5ClientOptions(RequestOptions.DEFAULT, false);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 the original author or authors.
|
||||
* Copyright 2021-present 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.
|
||||
@@ -24,6 +24,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.elasticsearch.client.ResponseException;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
@@ -33,6 +34,7 @@ import org.springframework.data.elasticsearch.NoSuchIndexException;
|
||||
import org.springframework.data.elasticsearch.ResourceNotFoundException;
|
||||
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.VersionConflictException;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Simple {@link PersistenceExceptionTranslator} for Elasticsearch. Convert the given runtime exception to an
|
||||
@@ -45,6 +47,9 @@ import org.springframework.data.elasticsearch.VersionConflictException;
|
||||
*/
|
||||
public class ElasticsearchExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
public static final boolean LEGACY_RESTCLIENT_PRESENT = ClassUtils
|
||||
.isPresent("org.elasticsearch.client.ResponseException", ElasticsearchExceptionTranslator.class.getClassLoader());
|
||||
|
||||
private final JsonpMapper jsonpMapper;
|
||||
|
||||
public ElasticsearchExceptionTranslator(JsonpMapper jsonpMapper) {
|
||||
@@ -68,7 +73,7 @@ public class ElasticsearchExceptionTranslator implements PersistenceExceptionTra
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
public @Nullable DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
|
||||
checkForConflictException(ex);
|
||||
|
||||
@@ -118,15 +123,20 @@ public class ElasticsearchExceptionTranslator implements PersistenceExceptionTra
|
||||
Integer status = null;
|
||||
String message = null;
|
||||
|
||||
if (exception instanceof ResponseException responseException) {
|
||||
if (LEGACY_RESTCLIENT_PRESENT && exception instanceof ResponseException responseException) {
|
||||
// this code is for the old RestClient
|
||||
status = responseException.getResponse().getStatusLine().getStatusCode();
|
||||
message = responseException.getMessage();
|
||||
} else if (exception instanceof ElasticsearchException elasticsearchException) {
|
||||
// using the RestClient throws this
|
||||
status = elasticsearchException.status();
|
||||
message = elasticsearchException.getMessage();
|
||||
} else if (exception.getCause() != null) {
|
||||
checkForConflictException(exception.getCause());
|
||||
}
|
||||
|
||||
if (status != null && message != null) {
|
||||
if (status == 409 && message.contains("type\":\"version_conflict_engine_exception"))
|
||||
if (status == 409 && message.contains("version_conflict_engine_exception"))
|
||||
if (message.contains("version conflict, required seqNo")) {
|
||||
throw new OptimisticLockingFailureException("Cannot index a document due to seq_no+primary_term conflict",
|
||||
exception);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user