1
0
mirror of synced 2026-05-23 04:33:17 +00:00

Compare commits

...

149 Commits

Author SHA1 Message Date
Christoph Strobl 53ac53d146 Release version 6.0.2 (2025.1.2).
See #3214
2026-01-16 10:36:18 +01:00
Christoph Strobl 6c656dff17 Prepare 6.0.2 (2025.1.2).
See #3214
2026-01-16 10:35:37 +01:00
Mark Paluch cfa303c6a3 Add Readme templates.
See spring-projects/spring-data-build#2758
2026-01-12 15:27:26 +01:00
Mark Paluch 353c463aa8 Extend license header copyright years to present.
See #3221
2026-01-05 08:45:42 +01:00
Peter-Josef Meisch cb67bfb534 Upgrade to Elasticsearch 9.2.3.
Closes #3217

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-12-24 16:21:03 +01:00
Mark Paluch 49cce254ce After release cleanups.
See #3197
2025-12-12 12:22:56 +01:00
Mark Paluch 597409c4c2 Prepare next development iteration.
See #3197
2025-12-12 12:22:55 +01:00
Mark Paluch 66144d10f8 Release version 6.0.1 (2025.1.1).
See #3197
2025-12-12 12:20:35 +01:00
Mark Paluch e6aefc8180 Prepare 6.0.1 (2025.1.1).
See #3197
2025-12-12 12:20:16 +01:00
Mark Paluch a7bd311106 Polishing.
Simplify test dependency setup, remove no longer required servlet/xbean dependencies, exclude commons-lang3 in favor of the Testcontainers variant. Remove outdated commons-codec dependency in favor of the Testcontainers variant.

See #3212
2025-12-11 09:02:48 +01:00
Mark Paluch 003d75f022 Add @ContextConfiguration(…) to test classes that use @SpringIntegrationTest on super classes.
Closes #3212
2025-12-11 09:02:48 +01:00
Mark Paluch 535b407085 Update CI Properties.
See #3197
2025-12-10 08:35:04 +01:00
Peter-Josef Meisch 44919d4cbe Upgrade Elasticsearch to 9.2.2.
Close #3208

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-12-05 00:01:14 +01:00
Peter-Josef Meisch 6260f278ba Fix UpdateQuery.Builder to allow only a scriptname to be set.
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
(cherry picked from commit 69746441e1)
2025-12-04 23:25:34 +01:00
Peter-Josef Meisch b3bd77aa46 Adjust aot hints for Elasticsearch 9 client.
The hints for the old httpclient are only needed when the old library is on the classpath, in case a user still uses the old RestClient. For the new Elasticsearch client there are no aot hints required.

Closes: #3203

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
(cherry picked from commit e31b66768b)
2025-11-25 20:11:04 +01:00
Peter-Josef Meisch bea651bc95 Fix documentation.
Closes #3199

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
(cherry picked from commit 5821a81db9)
2025-11-14 19:02:47 +01:00
Mark Paluch 175614cd94 After release cleanups.
See #3186
2025-11-14 13:56:30 +01:00
Mark Paluch c4c73709c8 Prepare next development iteration.
See #3186
2025-11-14 13:56:29 +01:00
Mark Paluch e4fb2908c0 Release version 6.0 GA (2025.1.0).
See #3186
2025-11-14 13:53:51 +01:00
Mark Paluch 97c2524db5 Prepare 6.0 GA (2025.1.0).
See #3186
2025-11-14 13:53:27 +01:00
Mark Paluch 6e3654866a Update Update security documentation.
See #3186
2025-11-14 10:43:37 +01:00
Mark Paluch 5c25ca922e Upgrade to Elasticsearch 9.2.1.
Closes #3194
2025-11-14 09:47:05 +01:00
Steven bc7cfdf6e9 Update clients.adoc to show how to log Request/Response for Rest5_Client (#3157)
* Update clients.adoc to show how to log Request/Response for Rest5_Client

Signed-off-by: Steven <steven.pearce@nowyoyo.com>

* Update clients.adoc to use tabs when available

---------

Signed-off-by: Steven <steven.pearce@nowyoyo.com>
2025-11-08 18:46:28 +01:00
Peter-Josef Meisch 6f0263b3af Update documentation.
Closes #3192

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-11-08 18:42:02 +01:00
Christoph Strobl bcbe4534c2 After release cleanups.
See #3189
2025-10-31 11:14:16 +01:00
Christoph Strobl c999465876 Prepare next development iteration.
See #3189
2025-10-31 11:14:15 +01:00
Christoph Strobl 5b87eeca69 Release version 6.0 RC2 (2025.1.0).
See #3189
2025-10-31 11:10:24 +01:00
Christoph Strobl 54b1983eef Prepare 6.0 RC2 (2025.1.0).
See #3189
2025-10-31 11:09:52 +01:00
Mark Paluch 68c9f04619 Move Commons PropertyPath and TypeInformation types to core package.
See spring-projects/spring-data-commons#3393
2025-10-30 11:27:35 +01:00
Mark Paluch 2c49dc75de Upgrade to Testcontainers 2.0.
See spring-projects/spring-data-build#2688
2025-10-28 11:07:05 +01:00
Peter-Josef Meisch 828f588f3e Upgrade to Elasticsearch 9.2.0
Original Pull Request #3191
Closes: #3190
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-10-27 18:16:34 +01:00
Peter-Josef Meisch 21bc62b78c Add SpEL support for settingPath in @Settings annotation.
Original Pull Request #3188
Closes #3187
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-10-26 18:25:56 +01:00
Christoph Strobl b552128198 After release cleanups.
See #3171
2025-10-17 12:41:12 +02:00
Christoph Strobl 18d582af6a Prepare next development iteration.
See #3171
2025-10-17 12:41:10 +02:00
Christoph Strobl fa3e7741f2 Release version 6.0 RC1 (2025.1.0).
See #3171
2025-10-17 12:36:47 +02:00
Christoph Strobl e9e6da239e Prepare 6.0 RC1 (2025.1.0).
See #3171
2025-10-17 12:35:34 +02:00
Peter-Josef Meisch 923d3b413d Upgrade to Elasticsearch 9.1.5.
Original Pull Request #3182
Closes #3180
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-10-17 00:03:18 +02:00
Mark Paluch 16f3addaf6 Remove accidental org.jetbrains:annotations usage.
See spring-projects/spring-data-build#2670
2025-10-10 09:25:17 +02:00
Peter-Josef Meisch 0e1a97a27a Fix string comparison in TypeUtils.
Original Pull Request #3177
Closes #3176
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-10-03 10:48:25 +02:00
Mark Paluch df79368299 Update CI Properties.
See #3171
2025-09-26 12:01:27 +02:00
Mark Paluch 11b3cd5b3e Update GitHub Actions.
See #3171
2025-09-23 10:52:08 +02:00
Peter-Josef Meisch e06aca9594 Upgrade to Elasticsearch 9.1.4
Original Pull Request #3174
Closes #3173

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-09-21 08:33:51 +02:00
Peter-Josef Meisch 5529af8f76 Adjust test to slower performance of build machines in Jenkins
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-09-20 20:14:59 +02:00
Peter-Josef Meisch c0dd082f4e Speedup Criteria hashcode calculation
Original Pull Request #3172
Closes #3083
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-09-20 19:49:38 +02:00
Christoph Strobl 9aa65560cc After release cleanups.
See #3154
2025-09-12 12:47:16 +02:00
Christoph Strobl 560d1e9153 Prepare next development iteration.
See #3154
2025-09-12 12:47:15 +02:00
Christoph Strobl 78cbad5093 Release version 6.0 M6 (2025.1.0).
See #3154
2025-09-12 12:43:45 +02:00
Christoph Strobl be3aee93fb Prepare 6.0 M6 (2025.1.0).
See #3154
2025-09-12 12:42:59 +02:00
Mark Paluch fb986e17f8 Polishing.
Update project metadata, add PJ as project lead (long overdue).

See #3154
2025-09-12 11:39:35 +02:00
Mark Paluch 3911b69869 Upgrade to elasticsearch-java 9.1.4.
Closes #3168
2025-09-12 11:37:29 +02:00
Mark Paluch b49fedaafc Adapt tests to MappingException cause when entity creation fails.
Closes #3167
2025-09-09 15:33:41 +02:00
Peter-Josef Meisch 087f3a80c5 Upgrade to Elasticsearch 9.1.3.
Original Pull Request #3165
Closes #3161

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-31 17:27:35 +02:00
Peter-Josef Meisch 46e997b81d Upgrade dependencies.
Original Pull Request #3163
Closes #3162

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-31 12:00:55 +02:00
Mark Paluch 1f5747294e Refine version properties for documentation build.
See spring-projects/spring-data-build#2638
2025-08-18 09:16:47 +02:00
Mark Paluch 92b6f28e31 After release cleanups.
See #3135
2025-08-15 10:47:30 +02:00
Mark Paluch 646f07c42b Prepare next development iteration.
See #3135
2025-08-15 10:47:29 +02:00
Mark Paluch 875ba54d33 Release version 6.0 M5 (2025.1.0).
See #3135
2025-08-15 10:45:11 +02:00
Mark Paluch 80b406ea22 Prepare 6.0 M5 (2025.1.0).
See #3135
2025-08-15 10:44:53 +02:00
Mark Paluch 9d987cbcc9 Polishing.
Use documentation variables for references, reorder antora keys.

See #3135
2025-08-14 17:27:50 +02:00
Peter-Josef Meisch 1505dd5129 Upgrade to Elasticsearch 9.1.1.
Original Pull Request #3150
Closes #3148
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-12 18:07:14 +02:00
Peter-Josef Meisch 6697755b45 Upgrade Elasticsearch to 9.1.0.
Original Pull Request #3147
Closes #3145
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-06 20:52:04 +02:00
Peter-Josef Meisch e49bb63df4 Fix handling of ResponseException from legacy client dependency.
Original Pull Request #3146
Closes #3144

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-04 20:50:47 +02:00
Peter-Josef Meisch 006cda6de6 Adjust Rest5Client building by using and exposing the callbacks provided by the Elasticsearch Java client library.
Original Pull Request #3143
Closes #3129

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-02 18:33:04 +02:00
Peter-Josef Meisch f51efa2cad Cleanup nullability issues
Original Pull Request #3142
Closes #3141
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-02 13:20:28 +02:00
Peter-Josef Meisch 6e30801a59 Upgrade to Elasticsearch 9.0.4
Original Pull Request #3140
Closes #3139

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-02 07:49:32 +02:00
Peter-Josef Meisch e64d0ada62 Polishing
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-07-22 18:36:04 +02:00
Anton 7f7cf3f52e Fixed PrimaryTerm/SeqNo datatypes in UpdateQuery.
Original Pull Request #3137
Closes #3136

Signed-off-by: Anton Buz <buzdalkin.a@vlprojects.pro>
2025-07-22 18:35:43 +02:00
Mark Paluch 55d470fc91 After release cleanups.
See #3115
2025-07-18 13:14:47 +02:00
Mark Paluch b7290b5d9c Prepare next development iteration.
See #3115
2025-07-18 13:14:46 +02:00
Mark Paluch 40414f0bde Release version 6.0 M4 (2025.1.0).
See #3115
2025-07-18 13:12:28 +02:00
Mark Paluch cb71caa504 Prepare 6.0 M4 (2025.1.0).
See #3115
2025-07-18 13:12:11 +02:00
Mark Paluch ed9abce7af Upgrade to Maven Wrapper 3.9.11.
See #3130
2025-07-17 13:59:56 +02:00
Peter-Josef Meisch 12ddb74fae Fix the calculation of the requested number of documents.
Original Pull Request #3128
Closes #3127

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-07-15 18:28:51 +02:00
Peter-Josef Meisch 6324b72707 Use the new Rest5Client as default, provide the old RestClient as optional.
Original Pull Request: #3125
Closes #3117

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-06-25 20:09:00 +02:00
Peter-Josef Meisch 6e49980c7c Upgrade to Elasticsearch 9.0.3.
Original Pull Request #3124
Closes #3123
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-06-25 17:24:08 +02:00
Peter-Josef Meisch f9509f2696 Upgrade to Elasticsearch 9.0.2.
Original Pull Request #3122
Closes #3121
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-06-14 17:30:22 +02:00
Mark Paluch 7f53944e1b Adapt to generics changes in CoroutineCrudRepository.
Closes #3118
2025-06-12 09:14:22 +02:00
Peter-Josef Meisch a9d2aaa93d Polishing.
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-29 18:10:48 +02:00
Laura Trotta 158f5fc342 es java client major update.
Original Pull Request #3116
Closes #3110
Signed-off-by: Laura Trotta <laura.trotta@elastic.co>
2025-05-29 15:56:35 +02:00
Peter-Josef Meisch 6268133506 Update versions documentation
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-24 14:58:04 +02:00
Mark Paluch 923787c2d1 After release cleanups.
See #3097
2025-05-16 14:18:48 +02:00
Mark Paluch 62fcbd44fa Prepare next development iteration.
See #3097
2025-05-16 14:18:47 +02:00
Mark Paluch 77ba620fc6 Release version 6.0 M3 (2025.1.0).
See #3097
2025-05-16 14:16:18 +02:00
Mark Paluch 06704d974d Prepare 6.0 M3 (2025.1.0).
See #3097
2025-05-16 14:15:56 +02:00
Mark Paluch 897cb0a957 Add optional Querydsl dependency.
Closes #3107
2025-05-16 12:18:51 +02:00
Mark Paluch a8557a36dc Update CI Properties.
See #3097
2025-05-16 12:18:51 +02:00
Mark Paluch 2678cdc7b6 After release cleanups.
See #3047
2025-05-16 12:18:51 +02:00
Mark Paluch eb42312ebe Prepare next development iteration.
See #3047
2025-05-16 12:18:51 +02:00
Mark Paluch af13fe0247 Release version 6.0 M2 (2025.1.0).
See #3047
2025-05-16 12:18:51 +02:00
Mark Paluch e81810c0d7 Prepare 6.0 M2 (2025.1.0).
See #3047
2025-05-16 12:18:51 +02:00
Peter-Josef Meisch e9c7c0ee95 Switch to jspecify nullability annotations.
Original Pull Request #3065
Closes #2984

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-16 12:18:50 +02:00
Peter-Josef Meisch 3a4425053e Cleanup unneeded imports after deprecation removal
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-16 12:18:50 +02:00
Christoph Strobl 09984f86e6 After release cleanups.
See #3006
2025-05-16 12:18:50 +02:00
Christoph Strobl 710526c5f6 Prepare next development iteration.
See #3006
2025-05-16 12:18:50 +02:00
Christoph Strobl 1acd392af7 Release version 6.0 M1 (2025.1.0).
See #3006
2025-05-16 12:18:50 +02:00
Christoph Strobl 76fe240a24 Prepare 6.0 M1 (2025.1.0).
See #3006
2025-05-16 12:18:50 +02:00
Mark Paluch e298bc9f7a Adopt to changes in Spring Framework 7.
See #3038
2025-05-16 12:18:50 +02:00
Peter-Josef Meisch 49d5dee5aa Update versions documentation
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-16 12:18:49 +02:00
Mark Paluch df6a127629 After release cleanups.
See #3096
2025-05-16 12:18:48 +02:00
Mark Paluch 08a1ef3a28 Prepare next development iteration.
See #3096
2025-05-16 11:31:15 +02:00
Mark Paluch 62a34cf09c Release version 5.5 GA (2025.0.0).
See #3096
2025-05-16 11:28:31 +02:00
Mark Paluch cc5f149c5a Prepare 5.5 GA (2025.0.0).
See #3096
2025-05-16 11:28:10 +02:00
Peter-Josef Meisch 0728c8e4aa Update versions doc for the next release
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-15 17:39:17 +02:00
Peter-Josef Meisch ebbe242a72 Fix missing return value in ByQueryResponse.
Original Pull Request #3109
Closes #3108

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-14 13:53:58 +02:00
Mark Paluch 0ce9a1c400 Update CI Properties.
See #3096
2025-05-12 09:33:06 +02:00
Mark Paluch 22763d17a7 Update CI Properties.
See #3096
2025-05-12 09:00:23 +02:00
Mark Paluch 9870de1e77 Update CI Properties.
See #3096
2025-05-12 08:56:22 +02:00
Mark Paluch 8c9d9ae1e7 Update CI Properties.
See #3096
2025-05-12 08:55:54 +02:00
Peter-Josef Meisch 945179e4eb Fix handling of page size and max results in search request preparation.
Original Pull Request #3106
Closes #3089

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-10 21:21:17 +02:00
Peter-Josef Meisch ea38ef1d41 Upgrade Elasticsearch libraries to 8.18.1.
Original Pull Request #3105
Closes #3103

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-09 20:35:30 +02:00
Mark Paluch acbfba94ac Exclude commons-logging dependency.
`elasticsearch-rest-client` pulls in `commons-logging` and we don't want that to happen as it conflicts with our dependency setup.

Closes #3104
2025-05-09 12:10:07 +02:00
Peter-Josef Meisch 5a0f556a3b Upgrade Elasticsearch dependencies to 8.18.0
Original Pull request #3101
Adjust to changes in Elasticsearch.
Closes #3100

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-05-02 10:21:24 +02:00
Peter-Josef Meisch a07ac3c93d Fix code not terminating on repository saving an empty flux.
Original Pull Request #3099
Closes: #3039

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-04-26 10:40:31 +02:00
Mark Paluch 9d025dd469 After release cleanups.
See #3079
2025-04-22 11:41:58 +02:00
Mark Paluch 925921f174 Prepare next development iteration.
See #3079
2025-04-22 11:41:58 +02:00
Mark Paluch 2f0a259045 Release version 5.5 RC1 (2025.0.0).
See #3079
2025-04-22 11:41:58 +02:00
Mark Paluch 9ffcb092db Prepare 5.5 RC1 (2025.0.0).
See #3079
2025-04-22 11:41:58 +02:00
Peter-Josef Meisch 0e5af90581 Fix implementation of equlas/hashcode for Criteria class.
Original Pull Request: #3088
Closes: #3083

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-04-05 20:44:01 +02:00
Peter-Josef Meisch 95059b3282 Upgrade to Elasticsearch 8.17.4.
Original Pull Request: #3085
Closes #3084

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-03-31 16:36:42 +02:00
Peter-Josef Meisch 1ae6301c2f Fix cutting of unknown properties in property paths for search.
Original Pull Request #3082
Closes #3081

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-03-24 21:44:53 +01:00
Peter-Josef Meisch 2366f67bba Enable scripted fields and runtime fields of collection type.
Original Pull Request #3080
Closes #3076

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-03-18 20:24:02 +01:00
Mark Paluch 6f424318ec After release cleanups.
See #3058
2025-03-14 09:33:43 +01:00
Mark Paluch 300fe2ac8b Prepare next development iteration.
See #3058
2025-03-14 09:33:42 +01:00
Mark Paluch 1fdee7399f Release version 5.5 M2 (2025.0.0).
See #3058
2025-03-14 09:31:05 +01:00
Mark Paluch ace17b9751 Prepare 5.5 M2 (2025.0.0).
See #3058
2025-03-14 09:30:46 +01:00
Peter-Josef Meisch 42383624ea Fix mapping of property names in sort parameters.
Original Pull Request #3074
Closes #3072

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-03-09 12:31:59 +01:00
Hope Kim 35e7b45f1a Fix syntax errors in link formatting in adoc files.
Original Pull Request: #3070
Closes #3071

Signed-off-by: esperar <s22043@gsm.hs.kr>
2025-03-04 19:25:25 +01:00
Volodymyr 89f60f2356 Fix typo.
Original Pull Request #3069
Closes: #3068

Signed-off-by: Dgray16 <vova235@gmail.com>
2025-03-02 09:45:59 +01:00
Peter-Josef Meisch fa979249fc Remove deprecated methods.
Original Pull Request #3067
Closes #3066

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-02-23 12:37:26 +01:00
정보교 (Bogus Jung) 8b43af2d33 optimize capacity & add assert messages in GeoJson.
Original Pull Request #3064
Closes #3063

Signed-off-by: 정보교 (Bogus Jung) <bogusjung0317@gmail.com>
2025-02-21 14:24:58 +01:00
Peter-Josef Meisch 64f88ae9ac Add testcontainers-local.properties handling.
Original Pull Request #3062
Closes #3061

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-02-19 20:14:16 +01:00
Mark Paluch 15f086359d After release cleanups.
See #3005
2025-02-14 12:25:09 +01:00
Mark Paluch 78ea67b6a6 Prepare next development iteration.
See #3005
2025-02-14 12:25:08 +01:00
Mark Paluch 6d0825b121 Release version 5.5 M1 (2025.0.0).
See #3005
2025-02-14 12:22:37 +01:00
Mark Paluch 846344891d Prepare 5.5 M1 (2025.0.0).
See #3005
2025-02-14 12:22:19 +01:00
Peter-Josef Meisch f9f64e6b39 Upgrade to Elasticsearch 8.17.2.
Closes #3054

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-02-12 07:54:06 +01:00
Mark Paluch 7fe4d8e1a4 Update CI Properties.
See #3005
2025-02-11 15:23:14 +01:00
Peter-Josef Meisch bd87dae1a3 Upgrade to Elasticsearch 8.17.1.
Original Pull Request #3053
Closes #3052 

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-02-11 12:47:00 +01:00
Peter-Josef Meisch ea62cf0abd Adopt to deprecation removals in Commons.
Original Pull Request #3051
Closes #3050 

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-02-09 20:20:01 +01:00
Peter-Josef Meisch cb77b328ae Add repository method support for search templates.
Original Pull Request #3049
Closes #2997 

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-02-08 12:17:42 +01:00
Peter-Josef Meisch 5568c7bbc4 Add IndexQuery.builder() method.
Original Pull Request: #3041
Closes #3030

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-01-11 13:21:55 +01:00
Peter-Josef Meisch 03591326d7 Update copyright comment to 2025.
Original Pull Request #3031
Closes #3030
2025-01-02 19:12:45 +01:00
Peter-Josef Meisch a94b74c877 Upgrade to Elasticsearch 8.17.0. (#3027)
Closes #3026
2024-12-15 19:16:38 +01:00
Alfonso 944e7e81dd fix: use scripted field name to populate entity.
Original Pull Request: #3023
Closes: #3022
2024-12-14 18:04:06 +01:00
Peter-Josef Meisch 5f297f1dc3 Upgrade to Elasticsearch 8.16.1.
Original Pull Request #3019
Closes #3017
2024-12-01 13:49:43 +01:00
Peter-Josef Meisch 028239fbdb Add optional fetchSource flag to the SourceFilter.
Original Pull Request #3014
Closes #3009
2024-11-28 15:37:19 +01:00
Peter-Josef Meisch 01d2d24916 Update versions documentation.
Original Pull Request #3013
Closes #3012
2024-11-24 10:43:11 +01:00
Mark Paluch 4f159d5de5 After release cleanups.
See #2990
2024-11-15 14:13:09 +01:00
Mark Paluch 00f13ac3e9 Prepare next development iteration.
See #2990
2024-11-15 14:13:08 +01:00
686 changed files with 6911 additions and 3043 deletions
+83
View File
@@ -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 Springs 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[]
+21
View File
@@ -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
+45
View File
@@ -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 }}
+1
View File
@@ -33,3 +33,4 @@ node
package-lock.json
.mvn/.develocity
/src/test/resources/testcontainers-local.properties
+1 -1
View File
@@ -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>
+14
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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=
+69 -39
View File
@@ -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>
+1 -1
View File
@@ -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:
+2
View File
@@ -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.
@@ -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.
@@ -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,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 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,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,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 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,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,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 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 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 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.
@@ -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.
@@ -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,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;
@@ -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
@@ -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;
@@ -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();
/**
@@ -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;
/**
@@ -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,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,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,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 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 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.
@@ -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,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 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 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 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;
/**
@@ -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,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.
@@ -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,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 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;
/**
@@ -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.
}
@@ -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);
}
}
@@ -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