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

Compare commits

...

206 Commits

Author SHA1 Message Date
Mark Paluch f16f70ff0f Release version 4.2.6 (2021.0.6).
See #1936
2021-10-18 11:11:46 +02:00
Mark Paluch 7494d344c5 Prepare 4.2.6 (2021.0.6).
See #1936
2021-10-18 11:10:49 +02:00
Mark Paluch ca61901c1c After release cleanups.
See #1898
2021-09-17 09:27:40 +02:00
Mark Paluch 323ccc9729 Prepare next development iteration.
See #1898
2021-09-17 09:27:36 +02:00
Mark Paluch d2960d764f Release version 4.2.5 (2021.0.5).
See #1898
2021-09-17 09:18:33 +02:00
Mark Paluch 8bb0a60450 Prepare 4.2.5 (2021.0.5).
See #1898
2021-09-17 09:17:30 +02:00
Christoph Strobl e33fe4d9fd Change visibility of PersistentEntitiesFactoryBean.
Closes: #1934
2021-09-16 08:08:41 +02:00
Mark Paluch 0fd1b96ef3 Upgrade to Maven Wrapper 3.8.2.
See #1927
2021-09-10 15:39:43 +02:00
Peter-Josef Meisch 30bc91c753 Polishing
(cherry picked from commit 6941e31ba4)
2021-09-10 08:31:51 +02:00
Nic Hines 92806d2e11 Change mapping of connectionRequestTimeout to ConnPool leaseTimeout.
Original Pull Request: #1925
Closes: #1926

(cherry picked from commit 3b8f0c9d56)
2021-09-10 08:31:51 +02:00
Peter-Josef Meisch 2dd0a6771f Fix @Query method implementation for unpaged queries.
Original Pull Request #1919
Closes #1917

(cherry picked from commit e71758686c)
2021-09-03 21:50:26 +02:00
Jens Schauder 79e0260f48 After release cleanups.
See #1875
2021-08-12 11:37:31 +02:00
Jens Schauder 8d79a3efcf Prepare next development iteration.
See #1875
2021-08-12 11:37:30 +02:00
Jens Schauder d785c6c33c Release version 4.2.4 (2021.0.4).
See #1875
2021-08-12 11:22:50 +02:00
Jens Schauder c89368ce42 Prepare 4.2.4 (2021.0.4).
See #1875
2021-08-12 11:22:27 +02:00
Peter-Josef Meisch c0781efbaa Fix NPE on IndexQuery with source and version.
Original Pull Request #1894
Closes #1893

(cherry picked from commit 36b449c385)
2021-08-06 22:39:41 +02:00
Peter-Josef Meisch d371404f90 Fix http URL in license header
(cherry picked from commit e6869bcdfd)
2021-07-22 07:32:58 +02:00
Peter-Josef Meisch cc5b4fa635 Upgrade maven wrapper to use maven 3.8.1.
Original Pull Request #1878
Closes #1877

(cherry picked from commit d2e3ea26b8)
2021-07-22 07:32:58 +02:00
Peter-Josef Meisch deae205fd4 Polishing.
(cherry picked from commit d3e8c9fce5)
2021-07-17 19:18:45 +02:00
Frnandu Martinski 796a5ebe34 Fix uri encode bug when url path start with '/'.
Original Pull Request #1873
Closes #1870

(cherry picked from commit d88fb037da)
2021-07-17 19:18:44 +02:00
Jens Schauder 2c63ba4097 After release cleanups.
See #1850
2021-07-16 11:51:06 +02:00
Jens Schauder fe255c1bdc Prepare next development iteration.
See #1850
2021-07-16 11:51:03 +02:00
Jens Schauder 6f89e17451 Release version 4.2.3 (2021.0.3).
See #1850
2021-07-16 11:35:23 +02:00
Jens Schauder 0ad4fcb2eb Prepare 4.2.3 (2021.0.3).
See #1850
2021-07-16 11:34:28 +02:00
Jens Schauder 4c3281f1eb Updated changelog.
See #1850
2021-07-16 11:34:25 +02:00
Peter-Josef Meisch 303438ae63 Use registered converters for parameters of @Query annotated methods.
Original Pull Request #1867
Closes #1866

(cherry picked from commit 27094724dc)
2021-07-14 20:02:44 +02:00
Niklas Herder 254948d1c9 Support collection parameters in @Query methods.
Original Pull Request #1856
Closes #1858

(cherry picked from commit 6f84a1c589)
2021-07-03 18:08:36 +02:00
Sascha Woo 0bb239a674 Add missing hashCode and equals methods to JoinField.
Original Pull Request #1847
Closes #1846

(cherry picked from commit a16a87f3fa)
2021-06-23 20:37:32 +02:00
Mark Paluch 3336ceade8 After release cleanups.
See #1814
2021-06-22 16:05:23 +02:00
Mark Paluch e7398df948 Prepare next development iteration.
See #1814
2021-06-22 16:05:20 +02:00
Mark Paluch a7ed13db83 Release version 4.2.2 (2021.0.2).
See #1814
2021-06-22 15:52:29 +02:00
Mark Paluch 7db3dc1a37 Prepare 4.2.2 (2021.0.2).
See #1814
2021-06-22 15:51:40 +02:00
Mark Paluch 0cabc3372e Updated changelog.
See #1814
2021-06-22 15:51:35 +02:00
Mark Paluch ab2fba6581 Updated changelog.
See #1813
2021-06-22 15:29:55 +02:00
Peter-Josef Meisch 45a0e2213f Adapt XNamedContents used by ReactiveElasticsearchClient for missing entries (terms and aggregations).
Original Pull Request #1837
Closes #1834

(cherry picked from commit 38dc7fb0fb)
2021-06-02 22:18:52 +02:00
Peter-Josef Meisch 8c8c0eba4f update versions table 2021-05-24 18:10:00 +02:00
Mark Paluch 90b366cf5f After release cleanups.
See #1775
2021-05-14 12:34:22 +02:00
Mark Paluch c5d93c5cd2 Prepare next development iteration.
See #1775
2021-05-14 12:34:18 +02:00
Mark Paluch 2ac1085d03 Release version 4.2.1 (2021.0.1).
See #1775
2021-05-14 12:23:57 +02:00
Mark Paluch e0760e8567 Prepare 4.2.1 (2021.0.1).
See #1775
2021-05-14 12:23:22 +02:00
Mark Paluch f8860c890a Updated changelog.
See #1775
2021-05-14 12:23:19 +02:00
Mark Paluch 3a00ef4375 Updated changelog.
See #1774
2021-05-14 12:06:47 +02:00
Peter-Josef Meisch ad6022f64c SearchPage result in StringQuery methods.
Original Pull Request #1812
Closes #1811

(cherry picked from commit e96d09fa51)
2021-05-13 17:02:57 +02:00
Peter-Josef Meisch da384e5eda update Elasticsearch to 7.12.1
Original Pull Request #1806 
Closes #1805
2021-05-10 18:17:44 +02:00
Peter-Josef Meisch 8ab1a4f098 Refactor DefaultReactiveElasticsearchClient to do request customization with the WebClient. (#1795)
Original Pull Request #1795
Closes #1794

(cherry picked from commit 775bf66401)
2021-04-30 07:31:22 +02:00
Peter-Josef Meisch 40972b21e0 Escape strings with quotes in custom query parameters.
Original Pull Request #1793
Closes #1790

(cherry picked from commit f8fbf7721a)
2021-04-29 06:24:05 +02:00
Peter-Josef Meisch 85af54635d Search with MoreLikeThisQuery should use Pageable.
Original Pull Request #1789
Closes #1787

(cherry picked from commit a2ca312fb2)
2021-04-26 22:32:48 +02:00
Peter-Josef Meisch 105607f6d6 Fix documentation.
Original Pull Request #1786
Closes #1785

(cherry picked from commit 8b7f0f8327)
2021-04-23 17:52:28 +02:00
Greg L. Turnquist d0ee4efd87 Polishing. 2021-04-20 11:05:17 -05:00
Greg L. Turnquist 9c900eca21 Polishing. 2021-04-20 11:00:33 -05:00
Greg L. Turnquist 8cfe165754 Authenticate with artifactory.
See #1750.
2021-04-20 10:41:43 -05:00
Peter-Josef Meisch 30bfee24f0 Custom property names must be used in SourceFilter and source fields.
Original Pull Request #1780
Closes #1778
2021-04-18 14:24:20 +02:00
Peter-Josef Meisch f339fda512 DynamicMapping annotation should be applicable to any object field.
Original Pull Request #1779
Closes #1767
2021-04-17 18:49:18 +02:00
Mark Paluch b2a480df83 After release cleanups.
See #1750
2021-04-14 14:30:41 +02:00
Mark Paluch f765ecac69 Prepare next development iteration.
See #1750
2021-04-14 14:30:38 +02:00
Mark Paluch 8bc06c9f41 Release version 4.2 GA (2021.0.0).
See #1750
2021-04-14 14:18:49 +02:00
Mark Paluch 03da6535cd Prepare 4.2 GA (2021.0.0).
See #1750
2021-04-14 14:18:22 +02:00
Mark Paluch 4e6df37e2a Updated changelog.
See #1750
2021-04-14 14:18:19 +02:00
Mark Paluch 58f1012874 Updated changelog.
See #1751
2021-04-14 11:43:34 +02:00
Mark Paluch 84391ae62a Updated changelog.
See #1730
2021-04-14 11:17:43 +02:00
Peter-Josef Meisch 010c0cb6ad Remove @Persistent from entity-scan include filters (#1772)
Original PR: #1772 
Closes: #1771
2021-04-13 20:53:39 +02:00
Peter-Josef Meisch d561c91678 Introduce cluster operations.
Original Pull Request: #1768 
Closes #1390
2021-04-11 11:05:37 +02:00
Peter-Josef Meisch 58bca88386 Fix reactive connection handling.
Original Pull Request #1766
Closes #1759
2021-04-08 22:00:46 +02:00
Peter-Josef Meisch 4782414596 CriteriaQuery must use nested query only with properties of type nested.
Original Pull Request #1763
Closes #1761
2021-04-06 20:50:24 +02:00
Peter-Josef Meisch ab73c68ca9 Nested Criteria queries must consider sub-fields.
Original Pull Request #1760 
Closes #1758
2021-04-05 15:42:02 +02:00
Peter-Josef Meisch 2bd4ef75cf CriteriaQuery must support nested queries.
Original Pull Request: #1757 
Closes #1753
2021-04-03 15:31:04 +02:00
Peter-Josef Meisch 4ad002746e #1755-Documentation-fix-to-not-show-deprecated-calls.
Original Pull Request #1756 
Closes #1755
2021-04-03 08:53:40 +02:00
Rahul Lokurte d66f8a0650 Documentation fix: Types are in the process of being removed.
Original Pull Request: #1754
2021-04-03 08:25:54 +02:00
Mark Paluch dfc68cd33b Updated changelog.
See #1731
2021-03-31 18:30:46 +02:00
Mark Paluch cb08adc0c9 After release cleanups.
See #1699
2021-03-31 17:24:06 +02:00
Mark Paluch 2a016f1aea Prepare next development iteration.
See #1699
2021-03-31 17:24:04 +02:00
Mark Paluch f9e4ac4d42 Release version 4.2 RC1 (2021.0.0).
See #1699
2021-03-31 17:05:09 +02:00
Mark Paluch 76d979cbba Prepare 4.2 RC1 (2021.0.0).
See #1699
2021-03-31 17:04:35 +02:00
Mark Paluch 0c4f0d8af9 Updated changelog.
See #1699
2021-03-31 17:04:31 +02:00
Peter-Josef Meisch 19ecf89455 Upgrade to Elasticsearch 7.12.0.
Original Pull Request #1749
Closes #1741
2021-03-28 16:16:41 +02:00
Peter-Josef Meisch 2e9bef0edb Configure index settings with @Setting annotation.
Original Pull Request #1748
Closes #1719
2021-03-28 13:24:52 +02:00
Peter-Josef Meisch 13ab2b9e95 Automatically close scroll context when returning streamed results.
Original Pull Request #1746
Closes #1745
2021-03-27 15:44:46 +01:00
Peter-Josef Meisch 3500dad2bc Readme lists artifacts with .RELEASE and .BUILD-SNAPSHOT suffixes (#1740)
Original Pull Request #1740
Closes #1738
2021-03-23 07:15:18 +01:00
Peter-Josef Meisch 2e5d2e0fd0 Update CI to Java 16
Original Pull Request #1739
Closes #1733
2021-03-22 22:03:22 +01:00
Peter-Josef Meisch a3e87a8525 Upgrade to OpenWebBeans 2.
Original Pull Request #1737 
Closes #1736
2021-03-21 21:31:14 +01:00
Peter-Josef Meisch 843fd4db85 Remove lombok.
Original Pull Request #1735 
Closes #1734
2021-03-21 18:36:38 +01:00
Peter-Josef Meisch ebac4c097c Polishing. 2021-03-17 22:43:09 +01:00
Sascha Woo 31b488d08f Allow multiple date formats for date fields.
Original Pull Request #1728 
Closes #1727
2021-03-17 22:39:12 +01:00
Mark Paluch db39b9e27c After release cleanups.
See #1709
2021-03-17 11:30:31 +01:00
Mark Paluch ff5a6043f1 Prepare next development iteration.
See #1709
2021-03-17 11:30:29 +01:00
Mark Paluch 399820680d Release version 4.2 M5 (2021.0.0).
See #1709
2021-03-17 11:17:50 +01:00
Mark Paluch a89fd89d12 Prepare 4.2 M5 (2021.0.0).
See #1709
2021-03-17 11:17:27 +01:00
Mark Paluch 28fe9ee25b Updated changelog.
See #1709
2021-03-17 11:17:25 +01:00
Mark Paluch 6e3579d1fe Updated changelog.
See #1702
2021-03-17 11:03:41 +01:00
Mark Paluch 83314880e4 Updated changelog.
See #1697
2021-03-17 10:35:14 +01:00
Peter-Josef Meisch 98a8d1a5ac Polishing 2021-03-16 22:36:57 +01:00
Lukáš Vasek 005d6a4d6f Added SearchTemplate support for reactive client
Original Pull Request #1726
Closes #1725
2021-03-16 21:37:55 +01:00
Peter-Josef Meisch 120eed02ee Polishing. 2021-03-13 17:50:33 +01:00
peermuellerxw b289d5f974 Add Rescore functionality.
Original Pull Request #1688
Closes #1686
2021-03-13 15:52:14 +01:00
Peter-Josef Meisch eb816cce87 Polishing. 2021-03-11 19:13:34 +01:00
Matt Gilene 4dc8b2589a Add matched_queries field to SearchHit.
Original Pull Request #1722 
Closes #1514
2021-03-11 18:32:37 +01:00
Peter-Josef Meisch 3f39f5d5b7 Use correct classes in reactive operations.
Original Pull Request #1724 
Closes #1721
2021-03-07 13:28:21 +01:00
Peter-Josef Meisch 2f5773a5ff Create index with mapping in one step.
Original Pull Request #1723 
Closes #1718
2021-03-06 18:42:57 +01:00
Peter-Josef Meisch e4c7b968e1 Add the type hint _class attribute to the index mapping.
Original Pull Request #1717 
Closes #1711
2021-03-04 23:56:29 +01:00
Peter-Josef Meisch 6634d0075a DefaultReactiveElasticsearchClient handle 5xx error with empty body
Original Pull Request #1713 
Closes #1712
2021-03-03 06:25:06 +01:00
Peter-Josef Meisch f08c34ec5d Improve multiget return.
Original Pull Request #1710 
Closes #1678
2021-02-27 18:16:54 +01:00
Peter-Josef Meisch dd3d01eab6 Polishing 2021-02-26 08:28:45 +01:00
Morgan 3f2ab4b06a Add support for dense_vector type
Original Pull Request  #1708
Closes #1700
2021-02-26 08:25:27 +01:00
Peter-Josef Meisch 8da718e41a Upgrade to Elasticsearch 7.11.1.
Original Pull Request ##1707
Closes #1687
2021-02-24 22:36:48 +01:00
Peter-Josef Meisch 17a25cb0ad Polishing 2021-02-24 21:16:52 +01:00
Farid Faoudi 3bc01a4e5f ReactiveElasticsearchClient should use the same request parameters as non reactive code.
Original Pull Request #1703
Closes #1658
2021-02-24 21:14:37 +01:00
Farid Faoudi 1c549b739b Add SearchFailure field in ByQueryResponse.
Original Pull Request #1705
Closes #1704
2021-02-22 18:30:27 +01:00
Peter-Josef Meisch 863ac2f3f5 Polishing. 2021-02-21 16:24:43 +01:00
gpopides 929d97f255 Add function to get index information
Original Pull Request #1693
Closes #1646
2021-02-20 18:01:12 +01:00
Christoph Strobl 43b3035ab7 After release cleanups.
See #1701
2021-02-18 11:35:22 +01:00
Christoph Strobl 0367246512 Prepare next development iteration.
See #1701
2021-02-18 11:35:21 +01:00
Christoph Strobl 36b3d0965e Release version 4.2 M4 (2021.0.0).
See #1701
2021-02-18 11:25:13 +01:00
Christoph Strobl 89125ae628 Prepare 4.2 M4 (2021.0.0).
See #1701
2021-02-18 11:24:46 +01:00
Christoph Strobl 2f2ab7cd89 Updated changelog.
See #1701
2021-02-18 11:24:45 +01:00
Christoph Strobl 9b55afc64b Updated changelog.
See #1698
2021-02-18 11:18:30 +01:00
Christoph Strobl 6193f075a5 After release cleanups.
See #1643
2021-02-17 14:17:49 +01:00
Christoph Strobl a4bc815c68 Prepare next development iteration.
See #1643
2021-02-17 14:17:48 +01:00
Christoph Strobl d49513531f Release version 4.2 M3 (2021.0.0).
See #1643
2021-02-17 14:00:09 +01:00
Christoph Strobl 69cfd57c78 Prepare 4.2 M3 (2021.0.0).
See #1643
2021-02-17 13:59:43 +01:00
Christoph Strobl 8d393f57bb Updated changelog.
See #1643
2021-02-17 13:59:42 +01:00
Christoph Strobl 53486ac85f Updated changelog.
See #1642
2021-02-17 13:49:21 +01:00
Christoph Strobl ced6144a81 Updated changelog.
See #1570
2021-02-17 11:34:26 +01:00
Christoph Strobl a2e525c6f0 Updated changelog.
See #1569
2021-02-17 10:58:26 +01:00
Peter-Josef Meisch 3869fd2ee8 Improve delete-by-query returned information.
Original Pull Request #1692
Closes #1679
2021-02-13 16:03:26 +01:00
Peter-Josef Meisch ffc2420bcd Add support for search_after.
Original Pull Request #1691
Closes #1143
2021-02-12 20:35:56 +01:00
peermuellerxw 154c50b3b7 Fix some anchor links in documentation.
Original Pull Request: #1690 
Closes #1689
2021-02-12 16:56:14 +01:00
Peter-Josef Meisch 87bf84d262 Fix remaining copyright years 2021-02-11 18:57:42 +01:00
Peter-Josef Meisch 719bcf4bfc Fix remaining copyright years 2021-02-11 18:55:57 +01:00
Peter-Josef Meisch fe8c4f12ed Add @CountQuery annotation.
Original Pull Request #1682 
Closes #1156
2021-02-07 20:21:02 +01:00
Peter-Josef Meisch 910ca7b665 Allow fields with id-property names (#1681)
Original Pull Request #1681 
Closes #1680
2021-02-05 23:06:19 +01:00
Mark Paluch 8fa261360f Add Map to ElasticsearchSimpleTypes.
See #1675.

(cherry picked from commit 27850e96f2)
2021-02-04 16:26:05 +01:00
Mark Paluch d811ff2d78 Polishing.
Fix PersistenceConstructor of Completion to accept the property type String[].

See #1675.

(cherry picked from commit bb3c006b92)
2021-02-04 16:25:29 +01:00
Mark Paluch a2baea7792 Refactor MappingElasticsearchConverter.
* Add support for SpEL expressions via @Value.
* Simplify readCollectionOrArray to consider properly nested lists and maps
* Simplify readMap to allow reading generic maps and entities in maps.
* Report a fallback TypeInformation in DefaultElasticsearchTypeMapper to properly convert nested maps.

We now no longer rely on isSimpleType when writing Maps. This is the preparation to consider Map as simple type.

Resolves #1676.
See #1675.

(cherry picked from commit 877de9c51c)
2021-02-04 16:24:57 +01:00
Peter-Josef Meisch 63eebdea88 Add query Explain Support.
Original Pull Request #1674
Closes #725
2021-01-30 19:50:32 +01:00
Peter-Josef Meisch ddc7246c42 Don't update indexed object if it is no persistent entity.
Original Pull Request  #1673
Closes #803
2021-01-30 14:16:22 +01:00
Peter-Josef Meisch dbd99a3880 Polishing. 2021-01-29 15:46:10 +01:00
slyoldfox e6c6d34948 Fix subCriteria's not being updated.
Original Pull Request  #1670
Closes #1668
2021-01-29 15:30:42 +01:00
Peter-Josef Meisch 0ac1b4af00 Allow CustomConversions for entities.
Original PullRequest #1672
Closes #1667
2021-01-28 22:51:02 +01:00
Peter-Josef Meisch e8edd606fb Cleanup deprecations from 4.0. (#1671)
Original Pull Request #1671 
Closes #1669
2021-01-28 08:14:20 +01:00
Peter-Josef Meisch 4829b07e53 ReactiveElasticsearchOperations indexName is encoded twice.
Original Pull Request #1666 
Closes #1665
2021-01-25 21:33:25 +01:00
Peter-Josef Meisch 1a02c1e05a Fix source filter setup in multiget requests.
Original Pull Request #1664
Closes #1659
2021-01-24 18:59:52 +01:00
Peter-Josef Meisch 1aabb42355 Documentation fix.
Original Pull Request #1663 
Closes #1662
2021-01-23 19:59:46 +01:00
Peter-Josef Meisch 9854c01ccb Polishing. 2021-01-23 16:20:26 +01:00
Farid Faoudi 0ee0164a58 Implement update by query.
Original Pull Request #1446 
Closes #1644
2021-01-23 11:31:15 +01:00
Peter-Josef Meisch 169015fb3b Fix assertions to assertj. 2021-01-21 21:09:18 +01:00
Peter-Josef Meisch 159520d001 GeoJson types can be lowercase in Elasticsearch.
Original Pull Request #1657 
Closes #1655
2021-01-19 20:25:38 +01:00
Peter-Josef Meisch 89d6ae7f49 Add routing parameter to ElasticsearchOperations.
Original Pull Request #562 
Closes #1218
2021-01-18 23:54:55 +01:00
Peter-Josef Meisch aba14c5e11 Add enabled mapping parameter.
Original PullRequest #1652 
Closes #1370
2021-01-17 23:54:35 +01:00
Peter-Josef Meisch b7a23ed7f1 Upgrade to Elasticsearch 7.10.2
Original Pull Request: #1651 
Closes #1649
2021-01-17 18:46:50 +01:00
Peter-Josef Meisch c6713fad5f Use own implementation of date formatters.
Original PR #1650 
Closes #1647
2021-01-17 16:36:38 +01:00
Peter-Josef Meisch e311df98c0 Use FieldNamingStrategy for property name matching.
Original PR #1648 
Closes #1565
2021-01-15 19:39:19 +01:00
Christoph Strobl ee30ef6635 After release cleanups.
See #1571
2021-01-13 15:47:00 +01:00
Christoph Strobl 7df60c9edf Prepare next development iteration.
See #1571
2021-01-13 15:46:59 +01:00
Christoph Strobl a5c4a87c66 Release version 4.2 M2 (2021.0.0).
See #1571
2021-01-13 15:34:04 +01:00
Christoph Strobl e84a883dfb Prepare 4.2 M2 (2021.0.0).
See #1571
2021-01-13 15:33:34 +01:00
Christoph Strobl 020a305f8e Updated changelog.
See #1571
2021-01-13 15:33:33 +01:00
Christoph Strobl dcadb74e96 Updated changelog.
See #1572
2021-01-13 15:16:25 +01:00
Farid Faoudi 3c6dd641d7 Add support for GetFieldMapping request in ReactiveElasticsearchClient.
Original Pull Request #1641
Closes #1640
2021-01-13 08:24:49 +01:00
Peter-Josef Meisch 5bf0c4b093 Upgrade to Elasticsearch 7.10.1. (#1639)
Original Pull Request #1639 
Closes #1638
2021-01-10 18:43:42 +01:00
Peter-Josef Meisch 00dcee0a5d Throw exception on index creation error.
Closes #1056 
Original Pull Request #1637
2021-01-10 12:23:50 +01:00
Peter-Josef Meisch 6913d8045b #1634 - Update Testcontainers dependency. (#1635)
Original Pull Request: #1635 
Closes #1634
2021-01-07 22:08:45 +01:00
Peter-Josef Meisch 36bbc20681 #1632 - Update copyright notice to 2021.
Original Pull request #1633
Closes #1632
2021-01-07 08:14:26 +01:00
Peter-Josef Meisch 51c59515ab #1629 - Update repository after GitHub issues migration.
Original Pull Request #1631 
Closes #1629
2021-01-02 18:04:44 +01:00
Peter-Josef Meisch f3dbaa0fe8 Add version of Spring dependency to docs.
Original Pull Request #1630
Closes: #1576
2020-12-31 15:03:45 +01:00
Peter-Josef Meisch 90c4a2a4d6 DATAES-982 - Improve refresh handling.
Original PR: #573.
2020-12-29 13:39:28 +01:00
Peter-Josef Meisch 6fd35b56da DATAES-1003 - Polishing. 2020-12-18 17:36:16 +01:00
simpleusr e950752e79 DATAES-1003 - add timeout to search query.
Original PR: #572
2020-12-18 16:57:40 +01:00
Greg L. Turnquist b49b053d06 DATAES-996 - Polishing. 2020-12-15 11:10:41 -06:00
Greg L. Turnquist a2d2a6119d DATAES-996 - Use Docker hub credentials for all CI jobs. 2020-12-15 11:09:24 -06:00
Peter-Josef Meisch fd975993d3 DATAES-946 - Support 'wildcard' field type.
Original PR: #571
2020-12-09 22:36:43 +01:00
Mark Paluch 80a50a83d0 DATAES-973 - Updated changelog. 2020-12-09 16:47:44 +01:00
Mark Paluch 9a987f213f DATAES-966 - After release cleanups. 2020-12-09 15:32:21 +01:00
Mark Paluch 4fec1ad00d DATAES-966 - Prepare next development iteration. 2020-12-09 15:32:17 +01:00
Mark Paluch 9b20e94acc DATAES-966 - Release version 4.2 M1 (2021.0.0). 2020-12-09 15:21:57 +01:00
Mark Paluch 33e479f0f5 DATAES-966 - Prepare 4.2 M1 (2021.0.0). 2020-12-09 15:21:30 +01:00
Mark Paluch bc50ac9779 DATAES-966 - Updated changelog. 2020-12-09 15:21:27 +01:00
Mark Paluch 8013b4b344 DATAES-964 - Updated changelog. 2020-12-09 12:42:28 +01:00
Mark Paluch 625d58b7dd DATAES-963 - Updated changelog. 2020-12-09 09:59:14 +01:00
Peter-Josef Meisch 585299cd74 DATAES-995 - Code Cleanup after DATACMNS-1838.
Original PR:  #570
2020-12-07 19:46:40 +01:00
Peter-Josef Meisch d25f7fe7b8 DATAES-985 - Add builder method for track_total_hits to NativeSearchQueryBuilder.
Original PR: #569
2020-12-06 13:05:33 +01:00
Peter-Josef Meisch fcb8a9b0ed DATAES-994 Add setup for mutation testing.
Original PR: #568
2020-12-06 12:08:42 +01:00
Peter-Josef Meisch e408067b49 DATAES-247 - Support OpType in IndexQuery.
Original PR: #567
2020-12-06 08:38:58 +01:00
Peter-Josef Meisch 7df6ffb5cd DATAES-362 - Polishing. 2020-12-05 23:20:40 +01:00
Peter-Josef Meisch a42de9b51b DATAES-362 - Add support for composable meta annotations.
Original PR: #566
2020-12-05 22:53:18 +01:00
Peter-Josef Meisch 6edb8353b5 DATAES-990 - Index creation fails with Authentication object cannot be null on startup.
Only do a SpEL resolution if there is a SpEL expressin in the index name; resolve ExpressionDependencies.

Original PR: #565
2020-12-05 12:10:39 +01:00
Peter-Josef Meisch 6a6ead5e1e DATAES-991 - Wrong value for TermVector(with_positions_offets_payloads).
Original PR: #564
2020-12-04 08:10:41 +01:00
Peter-Josef Meisch 8e59b18931 DATAES-989 - Improve deprecation warning for id properties without annotation.
Original PR: #563
2020-12-02 21:00:23 +01:00
Patrick Strawderman c66443ab5a DATAES-988 Allow specifying max results in NativeSearchQueryBuilder
Original PR: #561 

Add a withMaxResults method to NativeSearchQueryBuilder for specifying the maxResults
on the built Query. This is common for aggregation queries where search hits are not
needed.

Having the builder method for setting maxResults is a minor ergonomic improvement, e.g.

NativeSearchQuery searchQuery = NativeSearchQueryBuilder()
        .withQuery(matchAllQuery())
        .addAggregation(terms("examples").field("example"))
        .withMaxResults(0)
        .build();

versus what was required before:

NativeSearchQuery searchQuery = NativeSearchQueryBuilder()
        .withQuery(matchAllQuery())
        .addAggregation(terms("examples").field("example"))
        .build();
searchQuery.setMaxResults(0);
2020-11-30 18:54:30 +01:00
Peter-Josef Meisch 7912ae9779 DATAES-987 - IndexOperations getMapping fail when using index alias.
Original PR: #560
2020-11-26 06:54:20 +01:00
Mark Paluch 9bf6b6a984 DATAES-976 - Polishing.
Use deleteAllById(…) from deleteAll(…). Simplify implementation in SimpleReactiveElasticsearchRepository.

Original pull request: #554.
2020-11-25 13:44:10 +01:00
Jens Schauder 749270ba25 DATAES-976 - Implement CrudRepository and ReactiveCrudRepository.deleteAllById(Iterable<ID> ids).
Original pull request: #554.
2020-11-25 12:12:04 +01:00
Peter-Josef Meisch b17999f8fa DATAES-986 - Fix Javadoc.
Original PR: #559
2020-11-24 12:57:00 +01:00
Peter-Josef Meisch 8ef0970517 DATAES-983 - Test dependency hoverfly-java-junit5 leaks into compile scope.
Original PR: #558
2020-11-23 13:31:13 +01:00
Peter-Josef Meisch 54727229e1 DATAES-543 - Adjust configuration support classes so they do not require proxying.
Original PR: #557
2020-11-21 18:23:45 +01:00
Peter-Josef Meisch 04ceed2905 DATAES-978 - Accept DateFormat.none for a date property to enable custom Converters.
Original pR: #556
2020-11-19 23:12:26 +01:00
Peter-Josef Meisch 98043348f7 DATAES-972 - BeforeConvertCallback should be called before index query is built.
Originap PR: #555
2020-11-16 12:58:00 +01:00
Peter-Josef Meisch 6debccffbd DATAES-975 - Upgrade to Elasticsearch 7.10.0.
Original PR: #553
2020-11-12 19:06:59 +01:00
Peter-Josef Meisch 88a8b84e5c DATAES-974 - Remove usage of deprecated WebClient exchange() method.
Original PR: #552
2020-11-11 20:12:05 +01:00
Mark Paluch ce82ae07b9 DATAES-965 - Updated changelog. 2020-11-11 12:34:41 +01:00
Peter-Josef Meisch aa763efe7a DATAES-971 - Fix tests for using a proxy with reactive client
Original PR: #551
2020-11-09 23:34:27 +01:00
Peter-Josef Meisch 6db1aa6871 DATAES-588 - Add HttpClientConfigCallback for non-reactive setup.
Original PR: #548
2020-11-08 21:59:06 +01:00
Peter-Josef Meisch 6bfeade7a0 DATAES-970 - Take Testcontainers version from the Spring Data Build pom.
Original PR: #547
2020-11-08 08:45:48 +01:00
Peter-Josef Meisch d036693f05 DATAES-969 - Use ResultProcessor in ElasticsearchPartQuery to build PartTree.
Original PR: #546
2020-11-07 18:26:13 +01:00
Mark Paluch 1a354d8c51 DATAES-968 - Enable Maven caching for Jenkins jobs. 2020-10-30 08:35:56 +01:00
Mark Paluch 0a3facad91 DATAES-950 - After release cleanups. 2020-10-28 16:10:25 +01:00
Mark Paluch 40f6366daa DATAES-950 - Prepare next development iteration. 2020-10-28 16:10:22 +01:00
490 changed files with 20893 additions and 6887 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ Make sure that:
-->
- [ ] You have read the [Spring Data contribution guidelines](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc).
- [ ] There is a ticket in the bug tracker for the project in our [JIRA](https://jira.spring.io/browse/DATAES).
- [ ] There is a ticket in the bug tracker for the project in our [issue tracker](https://github.com/spring-projects/spring-data-elasticsearch/issues).
- [ ] You use the code formatters provided [here](https://github.com/spring-projects/spring-data-build/tree/master/etc/ide) and have them applied to your changes. Dont submit any formatting related changes.
- [ ] You submit test cases (unit or integration tests) that back your changes.
- [ ] You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).
+117
View File
@@ -0,0 +1,117 @@
/*
* Copyright 2007-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.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}
Vendored Executable → Regular
BIN
View File
Binary file not shown.
Vendored Executable → Regular
+3 -1
View File
@@ -1 +1,3 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
#Fri Sep 10 15:39:43 CEST 2021
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.8.2/apache-maven-3.8.2-bin.zip
+1 -1
View File
@@ -9,7 +9,7 @@ image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-elasticsearch%2
Since this pipeline is purely Docker-based, it's easy to:
* Debug what went wrong on your local machine.
* Test out a a tweak to your `test.sh` script before sending it out.
* Test out a a tweak to your `verify.sh` script before sending it out.
* Experiment against a new image before submitting your pull request.
All of these use cases are great reasons to essentially run what the CI server does on your local machine.
Vendored
+82 -64
View File
@@ -3,7 +3,7 @@ pipeline {
triggers {
pollSCM 'H/10 * * * *'
upstream(upstreamProjects: "spring-data-commons/master", threshold: hudson.model.Result.SUCCESS)
upstream(upstreamProjects: "spring-data-commons/2.5.x", threshold: hudson.model.Result.SUCCESS)
}
options {
@@ -15,71 +15,86 @@ pipeline {
stage("test: baseline (jdk8)") {
when {
anyOf {
branch 'master'
branch '4.2.x'
not { triggeredBy 'UpstreamCause' }
}
}
agent {
docker {
image 'adoptopenjdk/openjdk8:latest'
label 'data'
args '-v $HOME:/tmp/jenkins-home'
args '-u root -v /var/run/docker.sock:/var/run/docker.sock'
}
label 'data'
}
options { timeout(time: 30, unit: 'MINUTES') }
environment {
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
}
steps {
sh 'mkdir -p /tmp/jenkins-home'
sh 'chown -R 1001:1001 .'
sh 'rm -rf ?'
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list verify -Dsort -U -B'
sh 'chown -R 1001:1001 .'
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('adoptopenjdk/openjdk8:latest').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
sh 'PROFILE=none ci/verify.sh'
sh "ci/clean.sh"
}
}
}
}
}
stage("Test other configurations") {
when {
allOf {
branch 'master'
branch '4.2.x'
not { triggeredBy 'UpstreamCause' }
}
}
parallel {
stage("test: baseline (jdk11)") {
agent {
docker {
image 'adoptopenjdk/openjdk11:latest'
label 'data'
args '-v $HOME:/tmp/jenkins-home'
args '-u root -v /var/run/docker.sock:/var/run/docker.sock'
}
label 'data'
}
options { timeout(time: 30, unit: 'MINUTES') }
environment {
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
}
steps {
sh 'mkdir -p /tmp/jenkins-home'
sh 'chown -R 1001:1001 .'
sh 'rm -rf ?'
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list verify -Dsort -U -B'
sh 'chown -R 1001:1001 .'
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('adoptopenjdk/openjdk11:latest').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
sh 'PROFILE=java11 ci/verify.sh'
sh "ci/clean.sh"
}
}
}
}
}
stage("test: baseline (jdk15)") {
stage("test: baseline (jdk16)") {
agent {
docker {
image 'adoptopenjdk/openjdk15:latest'
label 'data'
args '-v $HOME:/tmp/jenkins-home'
args '-u root -v /var/run/docker.sock:/var/run/docker.sock'
}
label 'data'
}
options { timeout(time: 30, unit: 'MINUTES') }
environment {
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
}
steps {
sh 'mkdir -p /tmp/jenkins-home'
sh 'chown -R 1001:1001 .'
sh 'rm -rf ?'
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list verify -Dsort -U -B'
sh 'chown -R 1001:1001 .'
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('adoptopenjdk/openjdk16:latest').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
sh 'PROFILE=java11 ci/verify.sh'
sh "ci/clean.sh"
}
}
}
}
}
}
@@ -88,16 +103,12 @@ pipeline {
stage('Release to artifactory') {
when {
anyOf {
branch 'master'
branch '4.2.x'
not { triggeredBy 'UpstreamCause' }
}
}
agent {
docker {
image 'adoptopenjdk/openjdk8:latest'
label 'data'
args '-v $HOME:/tmp/jenkins-home'
}
label 'data'
}
options { timeout(time: 20, unit: 'MINUTES') }
@@ -106,27 +117,28 @@ pipeline {
}
steps {
sh 'rm -rf ?'
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,artifactory ' +
'-Dartifactory.server=https://repo.spring.io ' +
"-Dartifactory.username=${ARTIFACTORY_USR} " +
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
"-Dartifactory.staging-repository=libs-snapshot-local " +
"-Dartifactory.build-name=spring-data-elasticsearch " +
"-Dartifactory.build-number=${BUILD_NUMBER} " +
'-Dmaven.test.skip=true clean deploy -U -B'
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
'-Dartifactory.server=https://repo.spring.io ' +
"-Dartifactory.username=${ARTIFACTORY_USR} " +
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
"-Dartifactory.staging-repository=libs-snapshot-local " +
"-Dartifactory.build-name=spring-data-elasticsearch " +
"-Dartifactory.build-number=${BUILD_NUMBER} " +
'-Dmaven.test.skip=true clean deploy -U -B'
}
}
}
}
}
stage('Publish documentation') {
when {
branch 'master'
branch '4.2.x'
}
agent {
docker {
image 'adoptopenjdk/openjdk8:latest'
label 'data'
args '-v $HOME:/tmp/jenkins-home'
}
label 'data'
}
options { timeout(time: 20, unit: 'MINUTES') }
@@ -135,12 +147,18 @@ pipeline {
}
steps {
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,distribute ' +
'-Dartifactory.server=https://repo.spring.io ' +
"-Dartifactory.username=${ARTIFACTORY_USR} " +
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
"-Dartifactory.distribution-repository=temp-private-local " +
'-Dmaven.test.skip=true clean deploy -U -B'
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,distribute -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
'-Dartifactory.server=https://repo.spring.io ' +
"-Dartifactory.username=${ARTIFACTORY_USR} " +
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
"-Dartifactory.distribution-repository=temp-private-local " +
'-Dmaven.test.skip=true clean deploy -U -B'
}
}
}
}
}
}
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.
+12 -9
View File
@@ -114,7 +114,7 @@ Add the Maven dependency:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>${version}.RELEASE</version>
<version>${version}</version>
</dependency>
----
@@ -149,7 +149,7 @@ If you'd rather like the latest snapshots of the upcoming major version, use our
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>${version}.BUILD-SNAPSHOT</version>
<version>${version}-SNAPSHOT</version>
</dependency>
<repository>
@@ -170,17 +170,17 @@ If you are just starting out with Spring, try one of the https://spring.io/guide
* If you are upgrading, check out the https://docs.spring.io/spring-data/elasticsearch/docs/current/changelog.txt[changelog] for "`new and noteworthy`" features.
* Ask a question - we monitor https://stackoverflow.com[stackoverflow.com] for questions tagged with https://stackoverflow.com/tags/spring-data[`spring-data-elasticsearch`].
You can also chat with the community on https://gitter.im/spring-projects/spring-data[Gitter].
* Report bugs with Spring Data for Elasticsearch at https://jira.spring.io/browse/DATAES[jira.spring.io/browse/DATAES].
* Report bugs with Spring Data for Elasticsearch at https://github.com/spring-projects/spring-data-elasticsearch/issues[https://github.com/spring-projects/spring-data-elasticsearch/issues].
== Reporting Issues
Spring Data uses JIRA as issue tracking system to record bugs and feature requests. If you want to raise an issue, please follow the recommendations below:
Spring Data uses GitHub as issue tracking system to record bugs and feature requests. If you want to raise an issue, please follow the recommendations below:
* Before you log a bug, please search the
https://jira.spring.io/browse/DATAES[issue tracker] to see if someone has already reported the problem.
* If the issue doesnt already exist, https://jira.spring.io/browse/DATAES[create a new issue].
* Please provide as much information as possible with the issue report, we like to know the version of Spring Data that you are using and JVM version.
* If you need to paste code, or include a stack trace use JIRA `{code}…{code}` escapes before and after your text.
https://github.com/spring-projects/spring-data-elasticsearch/issues[issue tracker] to see if someone has already reported the problem.
* If the issue doesnt already exist, https://github.com/spring-projects/spring-data-elasticsearch/issues/new[create a new issue].
* Please provide as much information as possible with the issue report, we like to know the version of Spring Data Elasticsearch that you are using and JVM version.
* If you need to paste code, or include a stack trace use Markdown +++```+++ escapes before and after your text.
* If possible try to create a test-case or project that replicates the issue. Attach a link to your code or a compressed file containing your code.
== Building from Source
@@ -197,7 +197,10 @@ If you want to build with the regular `mvn` command, you will need https://maven
_Also see link:CONTRIBUTING.adoc[CONTRIBUTING.adoc] if you wish to submit pull requests, and in particular please sign the https://cla.pivotal.io/sign/spring[Contributors Agreement] before submitting your first pull request._
IMPORTANT: When contributing, please make sure an issue exists in Jira and comment on this issue with how you want to address it. By this we not only know that someone is working on an issue, we can also align architectural questions and possible solutions before work is invested. We so can prevent that much work is put into Pull Requests that have little
IMPORTANT: When contributing, please make sure an issue exists in https://github.com/spring-projects/spring-data-elasticsearch/issues[issue tracker] and comment on this issue with how you want to address it. By this we not only know that someone is working on an issue, we can also align architectural questions and possible solutions before work is invested
. We
so
can prevent that much work is put into Pull Requests that have little
or no chances of being merged.
+41
View File
@@ -0,0 +1,41 @@
= Testing
== Unit tests
Unit tests in the project are run with
----
./mvnw test
----
== Integration tests
Integration tests are executed when
----
./mvnw verify
----
is run. There must be _docker_ running, as the integration tests use docker to start an Elasticsearch server.
Integration tests are tests that have the Junit5 Tag `@Tag("integration-test")` on the test class. Normally this should not be set explicitly, but the annotation `@SpringIntegrationTest` should be used. This not only marks the test as integration test, but integrates an automatic setup of an Elasticsearch Testcontainer and integrate this with Spring, so
that the required Beans can be automatically injected. Check _src/test/java/org/springframework/data/elasticsearch/JUnit5SampleRestClientBasedTests.java_ as a reference setup
== Mutation testing
The pom includes a plugin dependency to run mutation tests using [pitest](https://pitest.org/). These tests must be explicitly configured and run, they are not included in the normal build steps. Before pitest can run, a normal `./mvnw test` must be executed. The configuration excludes integration tests, only unit tests are considered.
pitest can be run directly from the commandline
----
./mvnw org.pitest:pitest-maven:mutationCoverage
----
This will output an html report to _target/pit-reports/YYYYMMDDHHMI_.
To speed-up repeated analysis of the same codebase set the withHistory parameter to true.
----
./mvnw -DwithHistory org.pitest:pitest-maven:mutationCoverage
----
The classes to test are defined either in the pom.xml or can be set on the commandline:
----
./mvnw -DwithHistory org.pitest:pitest-maven:mutationCoverage -DtargetClasses="org.springframework.data.elasticsearch.support.*"
----
Executable
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash -x
set -euo pipefail
MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" \
./mvnw -s settings.xml clean -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch
Executable
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash -x
set -euo pipefail
mkdir -p /tmp/jenkins-home/.m2/spring-data-elasticsearch
chown -R 1001:1001 .
MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" \
./mvnw -s settings.xml \
-P${PROFILE} clean dependency:list verify -Dsort -U -B -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch
Vendored
+30 -6
View File
@@ -8,7 +8,7 @@
# "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
# http://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
@@ -19,7 +19,7 @@
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
@@ -114,7 +114,6 @@ if $mingw ; then
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
@@ -212,7 +211,11 @@ else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
@@ -221,22 +224,38 @@ else
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
wget "$jarUrl" -O "$wrapperJarPath"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
curl -o "$wrapperJarPath" "$jarUrl"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
@@ -277,6 +296,11 @@ if $cygwin; then
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
Vendored Executable → Regular
+33 -12
View File
@@ -7,7 +7,7 @@
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@@ -18,7 +18,7 @@
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@@ -26,7 +26,7 @@
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@@ -37,7 +37,7 @@
@echo off
@REM set title of command window
title %0
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
@@ -120,23 +120,44 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
echo Found %WRAPPER_JAR%
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
echo Finished downloading %WRAPPER_JAR%
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
+87 -7
View File
@@ -5,12 +5,12 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.1.0</version>
<version>4.2.6</version>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.4.0</version>
<version>2.5.6</version>
</parent>
<name>Spring Data Elasticsearch</name>
@@ -19,11 +19,11 @@
<properties>
<commonslang>2.6</commonslang>
<elasticsearch>7.9.3</elasticsearch>
<elasticsearch>7.12.1</elasticsearch>
<log4j>2.13.3</log4j>
<netty>4.1.52.Final</netty>
<springdata.commons>2.4.0</springdata.commons>
<testcontainers>1.14.3</testcontainers>
<springdata.commons>2.5.6</springdata.commons>
<testcontainers>1.15.1</testcontainers>
<java-module-name>spring.data.elasticsearch</java-module-name>
</properties>
@@ -70,8 +70,8 @@
</ciManagement>
<issueManagement>
<system>JIRA</system>
<url>https://jira.spring.io/browse/DATAES</url>
<system>GitHub</system>
<url>https://github.com/spring-projects/spring-data-elasticsearch/issues</url>
</issueManagement>
<dependencyManagement>
@@ -173,6 +173,7 @@
</exclusions>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
@@ -198,6 +199,21 @@
</dependency>
<!-- CDI -->
<!-- Dependency order required to build against CDI 1.0 and test with CDI 2.0 -->
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jcdi_2.0_spec</artifactId>
<version>1.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
@@ -206,6 +222,20 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${javax-annotation-api}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-se</artifactId>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework</groupId>
@@ -226,6 +256,23 @@
<scope>test</scope>
</dependency>
<!--
we don't use lombok in Spring Data Elasticsearch anymore. But the dependency is set in the parent project, and so the
lombok compiler stuff is executed regardless of the fact that we don't need it.
On AdoptOpenJdk 16.0.0 this leads to an error, so the project does not build.
Therefore we replace lombok with a jar - that just contains an empty file - that lives in a local maven repository in
src/test/resources/local-maven-repo/
It was installed with
mvn deploy:deploy-file -DgroupId=org.projectlombok -DartifactId=lombok -Dversion=999999 -Durl=file:./src/test/resources/local-maven-repo/ -DrepositoryId=local-maven-repo -DupdateReleaseInfo=true -Dfile=path/to/empty.jar
-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>999999</version>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>org.apache.openwebbeans.test</groupId>
<artifactId>cditest-owb</artifactId>
@@ -242,6 +289,7 @@
</exclusion>
</exclusions>
</dependency>
-->
<dependency>
<groupId>org.skyscreamer</groupId>
@@ -268,6 +316,13 @@
</exclusions>
</dependency>
<dependency>
<groupId>io.specto</groupId>
<artifactId>hoverfly-java-junit5</artifactId>
<version>0.13.1</version>
<scope>test</scope>
</dependency>
<!-- Upgrade xbean to 4.5 to prevent incompatibilities due to ASM versions -->
<dependency>
<groupId>org.apache.xbean</groupId>
@@ -360,6 +415,26 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.5.2</version>
<dependencies>
<dependency>
<groupId>org.pitest</groupId>
<artifactId>pitest-junit5-plugin</artifactId>
<version>0.12</version>
</dependency>
</dependencies>
<configuration>
<excludedGroups>integration-test</excludedGroups>
<targetClasses>
<param>org.springframework.data.elasticsearch.core.geo.*</param>
</targetClasses>
<excludedMethods>toString</excludedMethods>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
@@ -408,6 +483,11 @@
<id>spring-libs-release</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
<repository>
<id>local-maven-repo</id>
<url>file:///${project.basedir}/src/test/resources/local-maven-repo</url>
</repository>
</repositories>
<pluginRepositories>
+29
View File
@@ -0,0 +1,29 @@
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>spring-plugins-release</id>
<username>${env.ARTIFACTORY_USR}</username>
<password>${env.ARTIFACTORY_PSW}</password>
</server>
<server>
<id>spring-libs-snapshot</id>
<username>${env.ARTIFACTORY_USR}</username>
<password>${env.ARTIFACTORY_PSW}</password>
</server>
<server>
<id>spring-libs-milestone</id>
<username>${env.ARTIFACTORY_USR}</username>
<password>${env.ARTIFACTORY_PSW}</password>
</server>
<server>
<id>spring-libs-release</id>
<username>${env.ARTIFACTORY_USR}</username>
<password>${env.ARTIFACTORY_PSW}</password>
</server>
</servers>
</settings>
+3 -1
View File
@@ -5,7 +5,7 @@ BioMed Central Development Team; Oliver Drotbohm; Greg Turnquist; Christoph Stro
ifdef::backend-epub3[:front-cover-image: image:epub-cover.png[Front Cover,1050,1600]]
:spring-data-commons-docs: ../../../../spring-data-commons/src/main/asciidoc
(C) 2013-2020 The original author(s).
(C) 2013-2021 The original author(s).
NOTE: Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
@@ -33,6 +33,8 @@ include::reference/elasticsearch-auditing.adoc[]
include::{spring-data-commons-docs}/entity-callbacks.adoc[]
include::reference/elasticsearch-entity-callbacks.adoc[leveloffset=+1]
include::reference/elasticsearch-join-types.adoc[]
include::reference/elasticsearch-routing.adoc[]
include::reference/elasticsearch-misc.adoc[]
:leveloffset: -1
+10 -9
View File
@@ -16,7 +16,7 @@ include::reference/elasticsearch-new.adoc[leveloffset=+1]
* Version Control - https://github.com/spring-projects/spring-data-elasticsearch
* API Documentation - https://docs.spring.io/spring-data/elasticsearch/docs/current/api/
* Bugtracker - https://jira.spring.io/browse/DATAES
* Bugtracker - https://github.com/spring-projects/spring-data-elasticsearch/issues
* Release repository - https://repo.spring.io/libs-release
* Milestone repository - https://repo.spring.io/libs-milestone
* Snapshot repository - https://repo.spring.io/libs-snapshot
@@ -31,15 +31,16 @@ Requires an installation of https://www.elastic.co/products/elasticsearch[Elasti
The following table shows the Elasticsearch versions that are used by Spring Data release trains and version of Spring Data Elasticsearch included in that, as well as the Spring Boot versions referring to that particular Spring Data release train:
[cols="^,^,^,^",options="header"]
[cols="^,^,^,^,^",options="header"]
|===
| Spring Data Release Train |Spring Data Elasticsearch |Elasticsearch | Spring Boot
| 2020.0.0footnote:cdv[Currently in development] |4.1.xfootnote:cdv[]|7.9.3 |2.3.xfootnote:cdv[]
| Neumann | 4.0.x | 7.6.2 |2.3.x
| Moore | 3.2.x |6.8.12 | 2.2.x
| Lovelace | 3.1.x | 6.2.2 |2.1.x
| Kayfootnote:oom[Out of maintenance] | 3.0.xfootnote:oom[] | 5.5.0 | 2.0.xfootnote:oom[]
| Ingallsfootnote:oom[] | 2.1.xfootnote:oom[] | 2.4.0 | 1.5.xfootnote:oom[]
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework | Spring Boot
| 2021.0 (Pascal) | 4.2.1 | 7.12.1 | 5.3.7 | 2.5.x
| 2020.0 (Ockham) | 4.1.x | 7.9.3 | 5.3.2 | 2.4.x
| Neumann | 4.0.x | 7.6.2 | 5.2.12 |2.3.x
| Moore | 3.2.x |6.8.12 | 5.2.12| 2.2.x
| Lovelacefootnote:oom[Out of maintenance] | 3.1.xfootnote:oom[] | 6.2.2 | 5.1.19 |2.1.x
| Kayfootnote:oom[] | 3.0.xfootnote:oom[] | 5.5.0 | 5.0.13 | 2.0.x
| Ingallsfootnote:oom[] | 2.1.xfootnote:oom[] | 2.4.0 | 4.3.25 | 1.5.x
|===
Support for upcoming versions of Elasticsearch is being tracked and general compatibility should be given assuming the usage of the <<elasticsearch.clients.rest,high-level REST client>>.
@@ -30,11 +30,15 @@ public class Person implements Persistable<Long> {
@Id private Long id;
private String lastName;
private String firstName;
@CreatedDate
@Field(type = FieldType.Date, format = DateFormat.basic_date_time)
private Instant createdDate;
@CreatedBy
private String createdBy
@Field(type = FieldType.Date, format = DateFormat.basic_date_time)
@LastModifiedDate
private Instant lastModifiedDate;
@LastModifiedBy
private String lastModifiedBy;
public Long getId() { // <.>
@@ -8,7 +8,7 @@ Spring Data Elasticsearch operates upon an Elasticsearch client that is connecte
[[elasticsearch.clients.transport]]
== Transport Client
WARNING: The well known `TransportClient` is deprecated as of Elasticsearch 7 and will be removed in Elasticsearch 8. (https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html[see the Elasticsearch documentation]). Spring Data Elasticsearch will support the `TransportClient` as long as it is available in the used
WARNING: The `TransportClient` is deprecated as of Elasticsearch 7 and will be removed in Elasticsearch 8. (https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html[see the Elasticsearch documentation]). Spring Data Elasticsearch will support the `TransportClient` as long as it is available in the used
Elasticsearch <<elasticsearch.versions,version>> but has deprecated the classes using it since version 4.0.
We strongly recommend to use the <<elasticsearch.clients.rest>> instead of the `TransportClient`.
@@ -22,28 +22,33 @@ public class TransportClientConfig extends ElasticsearchConfigurationSupport {
@Bean
public Client elasticsearchClient() throws UnknownHostException {
Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build(); <1>
Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build(); <.>
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); <2>
client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); <.>
return client;
}
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException {
return new ElasticsearchTemplate(elasticsearchClient());
ElasticsearchTemplate template = new ElasticsearchTemplate(elasticsearchClient, elasticsearchConverter);
template.setRefreshPolicy(refreshPolicy()); <.>
return template;
}
}
// ...
IndexRequest request = new IndexRequest("spring-data", "elasticsearch", randomID())
.source(someObject)
.setRefreshPolicy(IMMEDIATE);
IndexRequest request = new IndexRequest("spring-data")
.id(randomID())
.source(someObject);
IndexResponse response = client.index(request);
----
<1> The `TransportClient` must be configured with the cluster name.
<2> The host and port to connect the client to.
<.> The `TransportClient` must be configured with the cluster name.
<.> The host and port to connect the client to.
<.> the RefreshPolicy must be set in the `ElasticsearchTemplate` (override `refreshPolicy()` to not use the default)
====
[[elasticsearch.clients.rest]]
@@ -81,11 +86,12 @@ public class RestClientConfig extends AbstractElasticsearchConfiguration {
// ...
IndexRequest request = new IndexRequest("spring-data", "elasticsearch", randomID())
IndexRequest request = new IndexRequest("spring-data")
.id(randomID())
.source(singletonMap("feature", "high-level-rest-client"))
.setRefreshPolicy(IMMEDIATE);
IndexResponse response = highLevelClient.index(request);
IndexResponse response = highLevelClient.index(request,RequestOptions.DEFAULT);
----
<1> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
<2> Create the RestHighLevelClient.
@@ -103,39 +109,29 @@ Calls are directly operated on the reactive stack, **not** wrapping async (threa
====
[source,java]
----
static class Config {
@Configuration
public class ReactiveRestClientConfig extends AbstractReactiveElasticsearchConfiguration {
@Bean
ReactiveElasticsearchClient client() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder() <1>
.connectedTo("localhost:9200", "localhost:9291")
.withWebClientConfigurer(webClient -> { <2>
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs()
.maxInMemorySize(-1))
@Override
@Bean
public ReactiveElasticsearchClient reactiveElasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder() <.>
.connectedTo("localhost:9200") //
.build();
return webClient.mutate().exchangeStrategies(exchangeStrategies).build();
})
.build();
return ReactiveRestClients.create(clientConfiguration);
return ReactiveRestClients.create(clientConfiguration);
}
}
}
// ...
Mono<IndexResponse> response = client.index(request ->
request.index("spring-data")
.type("elasticsearch")
.id(randomID())
.source(singletonMap("feature", "reactive-client"))
.setRefreshPolicy(IMMEDIATE);
.source(singletonMap("feature", "reactive-client"));
);
----
<1> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
<2> when configuring a reactive client, the `withWebClientConfigurer` hook can be used to customize the WebClient.
<.> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
====
NOTE: The ReactiveClient response, especially for search operations, is bound to the `from` (offset) & `size` (limit) options of the request.
@@ -150,36 +146,46 @@ Client behaviour can be changed via the `ClientConfiguration` that allows to set
[source,java]
----
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("some-header", "on every request") <1>
httpHeaders.add("some-header", "on every request") <.>
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200", "localhost:9291") <2>
.useSsl() <3>
.withProxy("localhost:8888") <4>
.withPathPrefix("ela") <5>
.withConnectTimeout(Duration.ofSeconds(5)) <6>
.withSocketTimeout(Duration.ofSeconds(3)) <7>
.withDefaultHeaders(defaultHeaders) <8>
.withBasicAuth(username, password) <9>
.withHeaders(() -> { <10>
.connectedTo("localhost:9200", "localhost:9291") <.>
.usingSsl() <.>
.withProxy("localhost:8888") <.>
.withPathPrefix("ela") <.>
.withConnectTimeout(Duration.ofSeconds(5)) <.>
.withSocketTimeout(Duration.ofSeconds(3)) <.>
.withDefaultHeaders(defaultHeaders) <.>
.withBasicAuth(username, password) <.>
.withHeaders(() -> { <.>
HttpHeaders headers = new HttpHeaders();
headers.add("currentTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
return headers;
})
.withWebClientConfigurer(webClient -> { <.>
//...
return webClient;
})
.withHttpClientConfigurer(clientBuilder -> { <.>
//...
return clientBuilder;
})
. // ... other options
.build();
----
<1> Define default headers, if they need to be customized
<2> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
<3> Optionally enable SSL.
<4> Optionally set a proxy.
<5> Optionally set a path prefix, mostly used when different clusters a behind some reverse proxy.
<6> Set the connection timeout. Default is 10 sec.
<7> Set the socket timeout. Default is 5 sec.
<8> Optionally set headers.
<9> Add basic authentication.
<10> A `Supplier<Header>` function can be specified which is called every time before a request is sent to Elasticsearch - here, as an example, the current time is written in a header.
<.> 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.
<.> Optionally set a proxy.
<.> Optionally set a path prefix, mostly used when different clusters a behind some reverse proxy.
<.> Set the connection timeout. Default is 10 sec.
<.> Set the socket timeout. Default is 5 sec.
<.> Optionally set headers.
<.> Add basic authentication.
<.> A `Supplier<Header>` function can be specified which is called every time before a request is sent to Elasticsearch - here, as an example, the current time is written in a header.
<.> for reactive setup a function configuring the `WebClient`
<.> for non-reactive setup a function configuring the REST client
====
IMPORTANT: Adding a Header supplier as shown in above example allows to inject headers that may change over the time, like authentication JWT tokens. If this is used in the reactive setup, the supplier function *must not* block!
@@ -0,0 +1,229 @@
[[elasticsearch.jointype]]
= Join-Type implementation
Spring Data Elasticsearch supports the https://www.elastic.co/guide/en/elasticsearch/reference/current/parent-join.html[Join data type] for creating the corresponding index mappings and for storing the relevant information.
== Setting up the data
For an entity to be used in a parent child join relationship, it must have a property of type `JoinField` which must be annotated.
Let's assume a `Statement` entity where a statement may be a _question_, an _answer_, a _comment_ or a _vote_ (a _Builder_ is also shown in this example, it's not necessary, but later used in the sample code):
====
[source,java]
----
@Document(indexName = "statements")
@Routing("routing") <.>
public class Statement {
@Id
private String id;
@Field(type = FieldType.Text)
private String text;
@Field(type = FieldType.Keyword)
private String routing;
@JoinTypeRelations(
relations =
{
@JoinTypeRelation(parent = "question", children = {"answer", "comment"}), <.>
@JoinTypeRelation(parent = "answer", children = "vote") <.>
}
)
private JoinField<String> relation; <.>
private Statement() {
}
public static StatementBuilder builder() {
return new StatementBuilder();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getRouting() {
return routing;
}
public void setRouting(Routing routing) {
this.routing = routing;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public JoinField<String> getRelation() {
return relation;
}
public void setRelation(JoinField<String> relation) {
this.relation = relation;
}
public static final class StatementBuilder {
private String id;
private String text;
private String routing;
private JoinField<String> relation;
private StatementBuilder() {
}
public StatementBuilder withId(String id) {
this.id = id;
return this;
}
public StatementBuilder withRouting(String routing) {
this.routing = routing;
return this;
}
public StatementBuilder withText(String text) {
this.text = text;
return this;
}
public StatementBuilder withRelation(JoinField<String> relation) {
this.relation = relation;
return this;
}
public Statement build() {
Statement statement = new Statement();
statement.setId(id);
statement.setRouting(routing);
statement.setText(text);
statement.setRelation(relation);
return statement;
}
}
}
----
<.> for routing related info see <<elasticsearch.routing>>
<.> a question can have answers and comments
<.> an answer can have votes
<.> the `JoinField` property is used to combine the name (_question_, _answer_, _comment_ or _vote_) of the relation with the parent id.
The generic type must be the same as the `@Id` annotated property.
====
Spring Data Elasticsearch will build the following mapping for this class:
====
[source,json]
----
{
"statements": {
"mappings": {
"properties": {
"_class": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"routing": {
"type": "keyword"
},
"relation": {
"type": "join",
"eager_global_ordinals": true,
"relations": {
"question": [
"answer",
"comment"
],
"answer": "vote"
}
},
"text": {
"type": "text"
}
}
}
}
}
----
====
== Storing data
Given a repository for this class the following code inserts a question, two answers, a comment and a vote:
====
[source,java]
----
void init() {
repository.deleteAll();
Statement savedWeather = repository.save(
Statement.builder()
.withText("How is the weather?")
.withRelation(new JoinField<>("question")) <1>
.build());
Statement sunnyAnswer = repository.save(
Statement.builder()
.withText("sunny")
.withRelation(new JoinField<>("answer", savedWeather.getId())) <2>
.build());
repository.save(
Statement.builder()
.withText("rainy")
.withRelation(new JoinField<>("answer", savedWeather.getId())) <3>
.build());
repository.save(
Statement.builder()
.withText("I don't like the rain")
.withRelation(new JoinField<>("comment", savedWeather.getId())) <4>
.build());
repository.save(
Statement.builder()
.withText("+1 for the sun")
,withRouting(savedWeather.getId())
.withRelation(new JoinField<>("vote", sunnyAnswer.getId())) <5>
.build());
}
----
<1> create a question statement
<2> the first answer to the question
<3> the second answer
<4> a comment to the question
<5> a vote for the first answer, this needs to have the routing set to the weather document, see <<elasticsearch.routing>>.
====
== Retrieving data
Currently native search queries must be used to query the data, so there is no support from standard repository methods. <<repositories.custom-implementations>> can be used instead.
The following code shows as an example how to retrieve all entries that have a _vote_ (which must be _answers_, because only answers can have a vote) using an `ElasticsearchOperations` instance:
====
[source,java]
----
SearchHits<Statement> hasVotes() {
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(hasChildQuery("vote", matchAllQuery(), ScoreMode.None))
.build();
return operations.search(query, Statement.class);
}
----
====
@@ -0,0 +1,66 @@
[[elasticsearch-migration-guide-4.1-4.2]]
= Upgrading from 4.1.x to 4.2.x
This section describes breaking changes from version 4.1.x to 4.2.x and how removed features can be replaced by new introduced features.
[[elasticsearch-migration-guide-4.1-4.2.deprecations]]
== Deprecations
=== @Document parameters
The parameters of the `@Document` annotation that are relevant for the index settings (`useServerConfiguration`, `shards`. `replicas`, `refreshIntervall` and `indexStoretype`) have been moved to the `@Setting` annotation. Use in `@Document` is still possible but deprecated.
[[elasticsearch-migration-guide-4.1-4.2.removal]]
== Removals
The `@Score` annotation that was used to set the score return value in an entity was deprecated in version 4.0 and has been removed.
Scroe values are returned in the `SearchHit` instances that encapsulate the returned entities.
The `org.springframework.data.elasticsearch.ElasticsearchException` class has been removed.
The remaining usages have been replaced with `org.springframework.data.mapping.MappingException` and `org.springframework.dao.InvalidDataAccessApiUsageException`.
The deprecated `ScoredPage`, `ScrolledPage` `@AggregatedPage` and implementations has been removed.
The deprecated `GetQuery` and `DeleteQuery` have been removed.
The deprecated `find` methods from `ReactiveSearchOperations` and `ReactiveDocumentOperations` have been removed.
[[elasticsearch-migration-guide-4.1-4.2.breaking-changes]]
== Breaking Changes
=== RefreshPolicy
==== Enum package changed
It was possible in 4.1 to configure the refresh policy for the `ReactiveElasticsearchTemplate` by overriding the method `AbstractReactiveElasticsearchConfiguration.refreshPolicy()` in a custom configuration class.
The return value of this method was an instance of the class `org.elasticsearch.action.support.WriteRequest.RefreshPolicy`.
Now the configuration must return `org.springframework.data.elasticsearch.core.RefreshPolicy`.
This enum has the same values and triggers the same behaviour as before, so only the `import` statement has to be adjusted.
==== Refresh behaviour
`ElasticsearchOperations` and `ReactiveElasticsearchOperations` now explicitly use the `RefreshPolicy` set on the template for write requests if not null.
If the refresh policy is null, then nothing special is done, so the cluster defaults are used. `ElasticsearchOperations` was always using the cluster default before this version.
The provided implementations for `ElasticsearchRepository` and `ReactiveElasticsearchRepository` will do an explicit refresh when the refresh policy is null.
This is the same behaviour as in previous versions.
If a refresh policy is set, then it will be used by the repositories as well.
==== Refresh configuration
When configuring Spring Data Elasticsearch like described in <<elasticsearch.clients>> by using `ElasticsearchConfigurationSupport`, `AbstractElasticsearchConfiguration` or `AbstractReactiveElasticsearchConfiguration` the refresh policy will be initialized to `null`.
Previously the reactive code initialized this to `IMMEDIATE`, now reactive and non-reactive code show the same behaviour.
=== Method return types
==== delete methods that take a Query
The reactive methods previously returned a `Mono<Long>` with the number of deleted documents, the non reactive versions were void. They now return a `Mono<ByQueryResponse>` which contains much more detailed information about the deleted documents and errors that might have occurred.
==== multiget methods
The implementations of _multiget_ previousl only returned the found entities in a `List<T>` for non-reactive implementations and in a `Flux<T>` for reactive implementations. If the request contained ids that were not found, the information that these are missing was not available. The user needed to compare the returned ids to the requested ones to find
which ones were missing.
Now the `multiget` methods return a `MultiGetItem` for every requested id. This contains information about failures (like non existing indices) and the information if the item existed (then it is contained in the `MultiGetItem) or not.
@@ -1,7 +1,50 @@
[[elasticsearch.misc]]
= Miscellaneous Elasticsearch Operation Support
This chapter covers additional support for Elasticsearch operations that cannot be directly accessed via the repository interface. It is recommended to add those operations as custom implementation as described in <<repositories.custom-implementations>> .
This chapter covers additional support for Elasticsearch operations that cannot be directly accessed via the repository interface.
It is recommended to add those operations as custom implementation as described in <<repositories.custom-implementations>> .
[[elasticsearc.misc.index.settings]]
== Index settings
When creating Elasticsearch indices with Spring Data Elasticsearch different index settings can be defined by using the `@Setting` annotation. 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
* `shards` the number of shards to use, defaults to _1_
* `replicas` the number of replicas, defaults to _1_
* `refreshIntervall`, defaults to _"1s"_
* `indexStoreType`, defaults to _"fs"_
It is as well possible to define https://www.elastic.co/guide/en/elasticsearch/reference/7.11/index-modules-index-sorting.html[index sorting] (check the linked Elasticsearch documentation for the possible field types and values):
====
[source,java]
----
@Document(indexName = "entities")
@Setting(
sortFields = { "secondField", "firstField" }, <.>
sortModes = { Setting.SortMode.max, Setting.SortMode.min }, <.>
sortOrders = { Setting.SortOrder.desc, Setting.SortOrder.asc },
sortMissingValues = { Setting.SortMissing._last, Setting.SortMissing._first })
class Entity {
@Nullable
@Id private String id;
@Nullable
@Field(name = "first_field", type = FieldType.Keyword)
private String firstField;
@Nullable @Field(name = "second_field", type = FieldType.Keyword)
private String secondField;
// getter and setter...
}
----
<.> when defining sort fields, use the name of the Java property (_firstField_), not the name that might be defined for Elasticsearch (_first_field_)
<.> `sortModes`, `sortOrders` and `sortMissingValues` are optional, but if they are set, the number of entries must match the number of `sortFields` elements
====
[[elasticsearch.misc.filter]]
== Filter Builder
@@ -19,7 +62,7 @@ SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withFilter(boolFilter().must(termFilter("id", documentId)))
.build();
Page<SampleEntity> sampleEntities = operations.searchForPage(searchQuery, SampleEntity.class, index);
----
====
@@ -27,8 +70,10 @@ Page<SampleEntity> sampleEntities = operations.searchForPage(searchQuery, Sample
[[elasticsearch.scroll]]
== Using Scroll For Big Result Set
Elasticsearch has a scroll API for getting big result set in chunks. This is internally used by Spring Data Elasticsearch to provide the implementations of the `<T> SearchHitsIterator<T> SearchOperations.searchForStream(Query query, Class<T> clazz, IndexCoordinates index)` method.
Elasticsearch has a scroll API for getting big result set in chunks.
This is internally used by Spring Data Elasticsearch to provide the implementations of the `<T> SearchHitsIterator<T> SearchOperations.searchForStream(Query query, Class<T> clazz, IndexCoordinates index)` method.
====
[source,java]
----
IndexCoordinates index = IndexCoordinates.of("sample-index");
@@ -48,9 +93,11 @@ while (stream.hasNext()) {
stream.close();
----
====
There are no methods in the `SearchOperations` API to access the scroll id, if it should be necessary to access this, the following methods of the `ElasticsearchRestTemplate` can be used:
====
[source,java]
----
@@ -75,9 +122,12 @@ while (scroll.hasSearchHits()) {
}
template.searchScrollClear(scrollId);
----
====
To use the Scroll API with repository methods, the return type must defined as `Stream` in the Elasticsearch Repository. The implementation of the method will then use the scroll methods from the ElasticsearchTemplate.
To use the Scroll API with repository methods, the return type must defined as `Stream` in the Elasticsearch Repository.
The implementation of the method will then use the scroll methods from the ElasticsearchTemplate.
====
[source,java]
----
interface SampleEntityRepository extends Repository<SampleEntity, String> {
@@ -86,6 +136,7 @@ interface SampleEntityRepository extends Repository<SampleEntity, String> {
}
----
====
[[elasticsearch.misc.sorts]]
== Sort options
@@ -94,213 +145,9 @@ In addition to the default sort options described <<repositories.paging-and-sort
If the class to be retrieved has a `GeoPoint` property named _location_, the following `Sort` would sort the results by distance to the given point:
====
[source,java]
----
Sort.by(new GeoDistanceOrder("location", new GeoPoint(48.137154, 11.5761247)))
----
[[elasticsearch.misc.jointype]]
== Join-Type implementation
Spring Data Elasticsearch supports the https://www.elastic.co/guide/en/elasticsearch/reference/current/parent-join.html[Join data type] for creating the corresponding index mappings and for storing the relevant information.
=== Setting up the data
For an entity to be used in a parent child join relationship, it must have a property of type `JoinField` which must be annotated.
Let's assume a `Statement` entity where a statement may be a _question_, an _answer_, a _comment_ or a _vote_ (a _Builder_ is also shown in this example, it's not necessary, but later used in the sample code):
====
[source,java]
----
@Document(indexName = "statements")
public class Statement {
@Id
private String id;
@Field(type = FieldType.Text)
private String text;
@JoinTypeRelations(
relations =
{
@JoinTypeRelation(parent = "question", children = {"answer", "comment"}), <1>
@JoinTypeRelation(parent = "answer", children = "vote") <2>
}
)
private JoinField<String> relation; <3>
private Statement() {
}
public static StatementBuilder builder() {
return new StatementBuilder();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public JoinField<String> getRelation() {
return relation;
}
public void setRelation(JoinField<String> relation) {
this.relation = relation;
}
public static final class StatementBuilder {
private String id;
private String text;
private JoinField<String> relation;
private StatementBuilder() {
}
public StatementBuilder withId(String id) {
this.id = id;
return this;
}
public StatementBuilder withText(String text) {
this.text = text;
return this;
}
public StatementBuilder withRelation(JoinField<String> relation) {
this.relation = relation;
return this;
}
public Statement build() {
Statement statement = new Statement();
statement.setId(id);
statement.setText(text);
statement.setRelation(relation);
return statement;
}
}
}
----
<1> a question can have answers and comments
<2> an answer can have votes
<3> the `JoinField` property is used to combine the name (_question_, _answer_, _comment_ or _vote_) of the relation with the parent id. The generic type must be the same as the `@Id` annotated property.
====
Spring Data Elasticsearch will build the following mapping for this class:
====
[source,json]
----
{
"statements": {
"mappings": {
"properties": {
"_class": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"relation": {
"type": "join",
"eager_global_ordinals": true,
"relations": {
"question": [
"answer",
"comment"
],
"answer": "vote"
}
},
"text": {
"type": "text"
}
}
}
}
}
----
====
=== Storing data
Given a repository for this class the following code inserts a question, two answers, a comment and a vote:
====
[source,java]
----
void init() {
repository.deleteAll();
Statement savedWeather = repository.save(
Statement.builder()
.withText("How is the weather?")
.withRelation(new JoinField<>("question")) <1>
.build());
Statement sunnyAnswer = repository.save(
Statement.builder()
.withText("sunny")
.withRelation(new JoinField<>("answer", savedWeather.getId())) <2>
.build());
repository.save(
Statement.builder()
.withText("rainy")
.withRelation(new JoinField<>("answer", savedWeather.getId())) <3>
.build());
repository.save(
Statement.builder()
.withText("I don't like the rain")
.withRelation(new JoinField<>("comment", savedWeather.getId())) <4>
.build());
repository.save(
Statement.builder()
.withText("+1 for the sun")
.withRelation(new JoinField<>("vote", sunnyAnswer.getId())) <5>
.build());
}
----
<1> create a question statement
<2> the first answer to the question
<3> the second answer
<4> a comment to the question
<5> a vote for the first answer
====
=== Retrieving data
Currently native search queries must be used to query the data, so there is no support from standard repository methods. <<repositories.custom-implementations>> can be used instead.
The following code shows as an example how to retrieve all entries that have a _vote_ (which must be _answers_, because only answers can have a vote) using an `ElasticsearchOperations` instance:
====
[source,java]
----
SearchHits<Statement> hasVotes() {
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(hasChildQuery("vote", matchAllQuery(), ScoreMode.None))
.build();
return operations.search(query, Statement.class);
}
----
====
@@ -1,6 +1,12 @@
[[new-features]]
= What's new
[[new-features.4-2-0]]
== New in Spring Data Elasticsearch 4.2
* Upgrade to Elasticsearch 7.10.0.
* Support for custom routing values
[[new-features.4-1-0]]
== New in Spring Data Elasticsearch 4.1
@@ -36,14 +36,6 @@ The most important attributes are:
This can contain a SpEL template expression like `"log-#{T(java.time.LocalDate).now().toString()}"`
** `type`: [line-through]#the mapping type.
If not set, the lowercased simple name of the class is used.# (deprecated since version 4.0)
** `shards`: the number of shards for the index.
** `replicas`: the number of replicas for the index.
** `refreshIntervall`: Refresh interval for the index.
Used for index creation.
Default value is _"1s"_.
** `indexStoreType`: Index storage type for the index.
Used for index creation.
Default value is _"fs"_.
** `createIndex`: flag whether to create an index on repository bootstrapping.
Default value is _true_.
See <<elasticsearch.repositories.autocreation>>
@@ -56,19 +48,66 @@ Default value is _EXTERNAL_.
Constructor arguments are mapped by name to the key values in the retrieved Document.
* `@Field`: Applied at the field level and defines properties of the field, most of the attributes map to the respective https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html[Elasticsearch Mapping] definitions (the following list is not complete, check the annotation Javadoc for a complete reference):
** `name`: The name of the field as it will be represented in the Elasticsearch document, if not set, the Java field name is used.
** `type`: the field type, can be one of _Text, Keyword, Long, Integer, Short, Byte, Double, Float, Half_Float, Scaled_Float, Date, Date_Nanos, Boolean, Binary, Integer_Range, Float_Range, Long_Range, Double_Range, Date_Range, Ip_Range, Object, Nested, Ip, TokenCount, Percolator, Flattened, Search_As_You_Type_.
** `type`: The field type, can be one of _Text, Keyword, Long, Integer, Short, Byte, Double, Float, Half_Float, Scaled_Float, Date, Date_Nanos, Boolean, Binary, Integer_Range, Float_Range, Long_Range, Double_Range, Date_Range, Ip_Range, Object, Nested, Ip, TokenCount, Percolator, Flattened, Search_As_You_Type_.
See https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html[Elasticsearch Mapping Types]
** `format` and `pattern` definitions for the _Date_ type. `format` must be defined for date types.
** `format`: One or more built-in date formats, see the next section <<elasticsearch.mapping.meta-model.date-formats>>.
** `pattern`: One or more custom date formats, see the next section <<elasticsearch.mapping.meta-model.date-formats>>.
** `store`: Flag whether the original field value should be store in Elasticsearch, default value is _false_.
** `analyzer`, `searchAnalyzer`, `normalizer` for specifying custom analyzers and normalizer.
* `@GeoPoint`: marks a field as _geo_point_ datatype.
* `@GeoPoint`: Marks a field as _geo_point_ datatype.
Can be omitted if the field is an instance of the `GeoPoint` class.
NOTE: Properties that derive from `TemporalAccessor` must either have a `@Field` annotation of type `FieldType.Date` or a custom converter must be registered for this type. +
If you are using a custom date format, you need to use _uuuu_ for the year instead of _yyyy_.
The mapping metadata infrastructure is defined in a separate spring-data-commons project that is technology agnostic.
[[elasticsearch.mapping.meta-model.date-formats]]
==== Date format mapping
Properties that derive from `TemporalAccessor` or are of type `java.util.Date` must either have a `@Field` annotation
of type `FieldType.Date` or a custom converter must be registered for this type. This paragraph describes the use of
`FieldType.Date`.
There are two attributes of the `@Field` annotation that define which date format information is written to the
mapping (also see https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats[Elasticsearch Built In Formats] and https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#custom-date-formats[Elasticsearch Custom Date Formats])
The `format` attributes is used to define at least one of the predefined formats. If it is not defined, then a
default value of __date_optional_time_ and _epoch_millis_ is used.
The `pattern` attribute can be used to add additional custom format strings. If you want to use only custom date formats, you must set the `format` property to empty `{}`.
The following table shows the different attributes and the mapping created from their values:
[cols=2*,options=header]
|===
| annotation
| format string in Elasticsearch mapping
| @Field(type=FieldType.Date)
| "date_optional_time\|\|epoch_millis",
| @Field(type=FieldType.Date, format=DateFormat.basic_date)
| "basic_date"
| @Field(type=FieldType.Date, format={DateFormat.basic_date, DateFormat.basic_time})
| "basic_date\|\|basic_time"
| @Field(type=FieldType.Date, pattern="dd.MM.uuuu")
| "date_optional_time\|\|epoch_millis\|\|dd.MM.uuuu",
| @Field(type=FieldType.Date, format={}, pattern="dd.MM.uuuu")
| "dd.MM.uuuu"
|===
NOTE: If you are using a custom date format, you need to use _uuuu_ for the year instead of _yyyy_.
This is due to a https://www.elastic.co/guide/en/elasticsearch/reference/current/migrate-to-java-time.html#java-time-migration-incompatible-date-formats[change in Elasticsearch 7].
The mapping metadata infrastructure is defined in a separate spring-data-commons project that is technology agnostic.
==== Mapped field names
Without further configuration, Spring Data Elasticsearch will use the property name of an object as field name in Elasticsearch. This can be changed for individual field by using the `@Field` annotation on that property.
It is also possible to define a `FieldNamingStrategy` in the configuration of the client (<<elasticsearch.clients>>). If for example a `SnakeCaseFieldNamingStrategy` is configured, the property _sampleProperty_ of the object would be mapped to _sample_property_ in Elasticsearch. A `FieldNamingStrategy` applies to all entities; it can be overwritten by
setting a specific name with `@Field` on a property.
[[elasticsearch.mapping.meta-model.rules]]
=== Mapping Rules
@@ -21,7 +21,8 @@ The default implementations of the interfaces offer:
====
.Index management and automatic creation of indices and mappings.
The `IndexOperations` interface and the provided implementation which can be obtained from an `ElasticsearchOperations` instance - for example with a call to `operations.indexOps(clazz)`- give the user the ability to create indices, put mappings or store template and alias information in the Elasticsearch cluster.
The `IndexOperations` interface and the provided implementation which can be obtained from an `ElasticsearchOperations` instance - for example with a call to `operations.indexOps(clazz)`- give the user the ability to create indices, put mappings or store template and alias information in the Elasticsearch cluster. Details of the index that will be created
can be set by using the `@Setting` annotation, refer to <<elasticsearc.misc.index.settings>> for further information.
**None of these operations are done automatically** by the implementations of `IndexOperations` or `ElasticsearchOperations`. It is the user's responsibility to call the methods.
@@ -173,10 +174,12 @@ Returned by the low level scroll API functions in `ElasticsearchRestTemplate`, i
.SearchHitsIterator<T>
An Iterator returned by the streaming functions of the `SearchOperations` interface.
[[elasticsearch.operations.queries]]
== Queries
Almost all of the methods defined in the `SearchOperations` and `ReactiveSearchOperations` interface take a `Query` parameter that defines the query to execute for searching. `Query` is an interface and Spring Data Elasticsearch provides three implementations: `CriteriaQuery`, `StringQuery` and `NativeSearchQuery`.
[[elasticsearch.operations.criteriaquery]]
=== CriteriaQuery
`CriteriaQuery` based queries allow the creation of queries to search for data without knowing the syntax or basics of Elasticsearch queries. They allow the user to build queries by simply chaining and combining `Criteria` objects that specifiy the criteria the searched documents must fulfill.
@@ -241,6 +244,7 @@ Query query = new CriteriaQuery(criteria);
Please refer to the API documentation of the `Criteria` class for a complete overview of the different available operations.
[[elasticsearch.operations.stringquery]]
=== StringQuery
This class takes an Elasticsearch query as JSON String.
@@ -258,6 +262,7 @@ SearchHits<Person> searchHits = operations.search(query, Person.class);
Using `StringQuery` may be appropriate if you already have an Elasticsearch query to use.
[[elasticsearch.operations.nativesearchquery]]
=== NativeSearchQuery
`NativeSearchQuery` is the class to use when you have a complex query, or a query that cannot be expressed by using the `Criteria` API, for example when building queries and using aggregates.
@@ -31,7 +31,7 @@ class Book {
The `@Document` annotation has an argument `createIndex`. If this argument is set to true - which is the default value - Spring Data Elasticsearch will during bootstrapping the repository support on application startup check if the index defined by the `@Document` annotation exists.
If it does not exist, the index will be created and the mappings derived from the entity's annotations (see <<elasticsearch.mapping>>) will be written to the newly created index.
If it does not exist, the index will be created and the mappings derived from the entity's annotations (see <<elasticsearch.mapping>>) will be written to the newly created index. Details of the index that will be created can be set by using the `@Setting` annotation, refer to <<elasticsearc.misc.index.settings>> for further information.
include::elasticsearch-repository-queries.adoc[leveloffset=+1]
@@ -131,7 +131,7 @@ class ProductService {
public void setRepository(ProductRepository repository) {
this.repository = repository;
}
}
}
----
<1> Create a component by using the same calls as are used in the <<elasticsearch.operations>> chapter.
<2> Let the CDI framework inject the Repository into your class.
@@ -0,0 +1,106 @@
[[elasticsearch.routing]]
= Routing values
When Elasticsearch stores a document in an index that has multiple shards, it determines the shard to you use based on the _id_ of the document.
Sometimes it is necessary to predefine that multiple documents should be indexed on the same shard (join-types, faster search for related data).
For this Elasticsearch offers the possibility to define a routing, which is the value that should be used to calculate the shard from instead of the _id_.
Spring Data Elasticsearch supports routing definitions on storing and retrieving data in the following ways:
== Routing on join-types
When using join-types (see <<elasticsearch.jointype>>), Spring Data Elasticsearch will automatically use the `parent` property of the entity's `JoinField` property as the value for the routing.
This is correct for all the use-cases where the parent-child relationship has just one level.
If it is deeper, like a child-parent-grandparent relationship - like in the above example from _vote_ -> _answer_ -> _question_ - then the routing needs to explicitly specified by using the techniques described in the next section (the _vote_ needs the _question.id_ as routing value).
== Custom routing values
To define a custom routing for an entity, Spring Data Elasticsearch provides a `@Routing` annotation (reusing the `Statement` class from above):
====
[source,java]
----
@Document(indexName = "statements")
@Routing("routing") <.>
public class Statement {
@Id
private String id;
@Field(type = FieldType.Text)
private String text;
@JoinTypeRelations(
relations =
{
@JoinTypeRelation(parent = "question", children = {"answer", "comment"}),
@JoinTypeRelation(parent = "answer", children = "vote")
}
)
private JoinField<String> relation;
@Nullable
@Field(type = FieldType.Keyword)
private String routing; <.>
// getter/setter...
}
----
<.> This defines _"routing"_ as routing specification
<.> a property with the name _routing_
====
If the `routing` specification of the annotation is a plain string and not a SpEL expression, it is interpreted as the name of a property of the entity, in the example it's the _routing_ property.
The value of this property will then be used as the routing value for all requests that use the entity.
It is also possible to us a SpEL expression in the `@Document` annotation like this:
====
[source,java]
----
@Document(indexName = "statements")
@Routing("@myBean.getRouting(#entity)")
public class Statement{
// all the needed stuff
}
----
====
In this case the user needs to provide a bean with the name _myBean_ that has a method `String getRouting(Object)`. To reference the entity _"#entity"_ must be used in the SpEL expression, and the return value must be `null` or the routing value as a String.
If plain property's names and SpEL expressions are not enough to customize the routing definitions, it is possible to define provide an implementation of the `RoutingResolver` interface. This can then be set on the `ElasticOperations` instance:
====
[source,java]
----
RoutingResolver resolver = ...;
ElasticsearchOperations customOperations= operations.withRouting(resolver);
----
====
The `withRouting()` functions return a copy of the original `ElasticsearchOperations` instance with the customized routing set.
When a routing has been defined on an entity when it is stored in Elasticsearch, the same value must be provided when doing a _get_ or _delete_ operation. For methods that do not use an entity - like `get(ID)` or `delete(ID)` - the `ElasticsearchOperations.withRouting(RoutingResolver)` method can be used like this:
====
[source,java]
----
String id = "someId";
String routing = "theRoutingValue";
// get an entity
Statement s = operations
.withRouting(RoutingResolver.just(routing)) <.>
.get(id, Statement.class);
// delete an entity
operations.withRouting(RoutingResolver.just(routing)).delete(id);
----
<.> `RoutingResolver.just(s)` returns a resolver that will just return the given String.
====
@@ -6,4 +6,6 @@
include::elasticsearch-migration-guide-3.2-4.0.adoc[]
include::elasticsearch-migration-guide-4.0-4.1.adoc[]
include::elasticsearch-migration-guide-4.1-4.2.adoc[]
:leveloffset: -1
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,57 +0,0 @@
/*
* Copyright 2013-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch;
import java.util.Map;
import org.springframework.lang.Nullable;
/**
* ElasticsearchException
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Peter-Josef Meisch
* @deprecated since 4.0, use {@link UncategorizedElasticsearchException}
*/
@Deprecated
public class ElasticsearchException extends RuntimeException {
@Nullable private Map<String, String> failedDocuments;
public ElasticsearchException(String message) {
super(message);
}
public ElasticsearchException(String message, Throwable cause) {
super(message, cause);
}
public ElasticsearchException(String message, Throwable cause, Map<String, String> failedDocuments) {
super(message, cause);
this.failedDocuments = failedDocuments;
}
public ElasticsearchException(String message, Map<String, String> failedDocuments) {
super(message);
this.failedDocuments = failedDocuments;
}
@Nullable
public Map<String, String> getFailedDocuments() {
return failedDocuments;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 the original author or authors.
* Copyright 2019-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,30 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core.query;
package org.springframework.data.elasticsearch;
import org.springframework.core.NestedRuntimeException;
/**
* GetQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Peter-Josef Meisch
* @deprecated since 4.0
*/
@Deprecated
public class GetQuery {
public GetQuery(String id) {
this.id = id;
public class ResourceFailureException extends NestedRuntimeException {
public ResourceFailureException(String msg) {
super(msg);
}
private String id;
public String getId() {
return id;
}
public static GetQuery getById(String id) {
return new GetQuery(id);
public ResourceFailureException(String msg, Throwable cause) {
super(msg, cause);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -0,0 +1,39 @@
/*
* Copyright 2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
/**
* Alias for a @Query annotation with the count parameter set to true.
*
* @author Peter-Josef Meisch
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Documented
@Query(count = true)
public @interface CountQuery {
@AliasFor(annotation = Query.class)
String value() default "";
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,58 +16,85 @@
package org.springframework.data.elasticsearch.annotations;
/**
* Values based on reference doc - https://www.elastic.co/guide/reference/mapping/date-format/
*
* Values based on reference doc - https://www.elastic.co/guide/reference/mapping/date-format/. The patterns are taken
* from this documentation and slightly adapted so that a Java {@link java.time.format.DateTimeFormatter} produces the
* same values as the Elasticsearch formatter.
*
* @author Jakub Vavrik
* @author Tim te Beek
* @author Peter-Josef Meisch
* @author Sascha Woo
*/
public enum DateFormat {
none, //
custom, //
basic_date, //
basic_date_time, //
basic_date_time_no_millis, //
basic_ordinal_date, //
basic_ordinal_date_time, //
basic_ordinal_date_time_no_millis, //
basic_time, //
basic_time_no_millis, //
basic_t_time, //
basic_t_time_no_millis, //
basic_week_date, //
basic_week_date_time, //
basic_week_date_time_no_millis, //
date, //
date_hour, //
date_hour_minute, //
date_hour_minute_second, //
date_hour_minute_second_fraction, //
date_hour_minute_second_millis, //
date_optional_time, //
date_time, //
date_time_no_millis, //
epoch_millis, //
epoch_second, //
hour, //
hour_minute, //
hour_minute_second, //
hour_minute_second_fraction, //
hour_minute_second_millis, //
ordinal_date, //
ordinal_date_time, //
ordinal_date_time_no_millis, //
time, //
time_no_millis, //
t_time, //
t_time_no_millis, //
week_date, //
week_date_time, //
week_date_time_no_millis, //
weekyear, //
weekyear_week, //
weekyear_week_day, //
year, //
year_month, //
year_month_day //
/**
* @deprecated since 4.2, will be removed in a future version. Use <code>format = {}</code> to disable built-in date
* formats in the @Field annotation.
*/
@Deprecated
none(""), //
/**
* @deprecated since 4.2, will be removed in a future version.It is no longer required for using a custom date format
* pattern. If you want to use only a custom date format pattern, you must set the <code>format</code>
* property to empty <code>{}</code>.
*/
@Deprecated
custom(""), //
basic_date("uuuuMMdd"), //
basic_date_time("uuuuMMdd'T'HHmmss.SSSXXX"), //
basic_date_time_no_millis("uuuuMMdd'T'HHmmssXXX"), //
basic_ordinal_date("uuuuDDD"), //
basic_ordinal_date_time("yyyyDDD'T'HHmmss.SSSXXX"), //
basic_ordinal_date_time_no_millis("yyyyDDD'T'HHmmssXXX"), //
basic_time("HHmmss.SSSXXX"), //
basic_time_no_millis("HHmmssXXX"), //
basic_t_time("'T'HHmmss.SSSXXX"), //
basic_t_time_no_millis("'T'HHmmssXXX"), //
basic_week_date("YYYY'W'wwe"), // week-based-year!
basic_week_date_time("YYYY'W'wwe'T'HHmmss.SSSX"), // here Elasticsearch uses a different zone format
basic_week_date_time_no_millis("YYYY'W'wwe'T'HHmmssX"), //
date("uuuu-MM-dd"), //
date_hour("uuuu-MM-dd'T'HH"), //
date_hour_minute("uuuu-MM-dd'T'HH:mm"), //
date_hour_minute_second("uuuu-MM-dd'T'HH:mm:ss"), //
date_hour_minute_second_fraction("uuuu-MM-dd'T'HH:mm:ss.SSS"), //
date_hour_minute_second_millis("uuuu-MM-dd'T'HH:mm:ss.SSS"), //
date_optional_time("uuuu-MM-dd['T'HH:mm:ss.SSSXXX]"), //
date_time("uuuu-MM-dd'T'HH:mm:ss.SSSXXX"), //
date_time_no_millis("uuuu-MM-dd'T'HH:mm:ssVV"), // here Elasticsearch uses the zone-id in it's implementation
epoch_millis("epoch_millis"), //
epoch_second("epoch_second"), //
hour("HH"), //
hour_minute("HH:mm"), //
hour_minute_second("HH:mm:ss"), //
hour_minute_second_fraction("HH:mm:ss.SSS"), //
hour_minute_second_millis("HH:mm:ss.SSS"), //
ordinal_date("uuuu-DDD"), //
ordinal_date_time("uuuu-DDD'T'HH:mm:ss.SSSXXX"), //
ordinal_date_time_no_millis("uuuu-DDD'T'HH:mm:ssXXX"), //
time("HH:mm:ss.SSSXXX"), //
time_no_millis("HH:mm:ssXXX"), //
t_time("'T'HH:mm:ss.SSSXXX"), //
t_time_no_millis("'T'HH:mm:ssXXX"), //
week_date("YYYY-'W'ww-e"), //
week_date_time("YYYY-'W'ww-e'T'HH:mm:ss.SSSXXX"), //
week_date_time_no_millis("YYYY-'W'ww-e'T'HH:mm:ssXXX"), //
weekyear(""), // no TemporalAccessor available for these 3
weekyear_week(""), //
weekyear_week_day(""), //
year("uuuu"), //
year_month("uuuu-MM"), //
year_month_day("uuuu-MM-dd"); //
private final String pattern;
DateFormat(String pattern) {
this.pattern = pattern;
}
/**
* @since 4.2
*/
public String getPattern() {
return pattern;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,29 +55,45 @@ public @interface Document {
/**
* Use server-side settings when creating the index.
*
* @deprecated since 4.2, use the {@link Setting} annotation to configure settings
*/
@Deprecated
boolean useServerConfiguration() default false;
/**
* Number of shards for the index {@link #indexName()}. Used for index creation. <br/>
* With version 4.0, the default value is changed from 5 to 1 to reflect the change in the default settings of
* Elasticsearch which changed to 1 as well in Elasticsearch 7.0.
* ComposableAnnotationsUnitTest.documentAnnotationShouldBeComposable:60
*
* @deprecated since 4.2, use the {@link Setting} annotation to configure settings
*/
@Deprecated
short shards() default 1;
/**
* Number of replicas for the index {@link #indexName()}. Used for index creation.
*
* @deprecated since 4.2, use the {@link Setting} annotation to configure settings
*/
@Deprecated
short replicas() default 1;
/**
* Refresh interval for the index {@link #indexName()}. Used for index creation.
*
* @deprecated since 4.2, use the {@link Setting} annotation to configure settings
*/
@Deprecated
String refreshInterval() default "1s";
/**
* Index storage type for the index {@link #indexName()}. Used for index creation.
*
* @deprecated since 4.2, use the {@link Setting} annotation to configure settings
*/
@Deprecated
String indexStoreType() default "fs";
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 the original author or authors.
* Copyright 2019-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 the original author or authors.
* Copyright 2019-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,9 +34,12 @@ import org.springframework.core.annotation.AliasFor;
* @author Peter-Josef Meisch
* @author Xiao Yu
* @author Aleksei Arsenev
* @author Brian Kimmig
* @author Morgan Lutz
* @author Sascha Woo
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Documented
@Inherited
public @interface Field {
@@ -63,9 +66,9 @@ public @interface Field {
boolean index() default true;
DateFormat format() default DateFormat.none;
DateFormat[] format() default { DateFormat.date_optional_time, DateFormat.epoch_millis };
String pattern() default "";
String[] pattern() default {};
boolean store() default false;
@@ -157,14 +160,14 @@ public @interface Field {
/**
* if true, the field will be stored in Elasticsearch even if it has a null value
*
*
* @since 4.1
*/
boolean storeNullValue() default false;
/**
* to be used in combination with {@link FieldType#Rank_Feature}
*
*
* @since 4.1
*/
boolean positiveScoreImpact() default true;
@@ -185,4 +188,11 @@ public @interface Field {
* @since 4.1
*/
NullValueType nullValueType() default NullValueType.String;
/**
* to be used in combination with {@link FieldType#Dense_Vector}
*
* @since 4.2
*/
int dims() default -1;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@ package org.springframework.data.elasticsearch.annotations;
* @author Zeng Zetang
* @author Peter-Josef Meisch
* @author Aleksei Arsenev
* @author Brian Kimmig
* @author Morgan Lutz
*/
public enum FieldType {
Auto, //
@@ -55,5 +57,9 @@ public enum FieldType {
/** @since 4.1 */
Rank_Feature, //
/** @since 4.1 */
Rank_Features //
Rank_Features, //
/** since 4.2 */
Wildcard, //
/** @since 4.2 */
Dense_Vector //
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2020 the original author or authors.
* Copyright 2017-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 the original author or authors.
* Copyright 2019-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 the original author or authors.
* Copyright 2019-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,8 @@ import java.lang.annotation.Target;
* @author Xiao Yu
* @author Peter-Josef Meisch
* @author Aleksei Arsenev
* @author Brian Kimmig
* @author Morgan Lutz
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
@@ -38,9 +40,9 @@ public @interface InnerField {
boolean index() default true;
DateFormat format() default DateFormat.none;
DateFormat[] format() default { DateFormat.date_optional_time, DateFormat.epoch_millis };
String pattern() default "";
String[] pattern() default {};
boolean store() default false;
@@ -140,4 +142,11 @@ public @interface InnerField {
* @since 4.1
*/
NullValueType nullValueType() default NullValueType.String;
/**
* to be used in combination with {@link FieldType#Dense_Vector}
*
* @since 4.2
*/
int dims() default -1;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,12 @@
*/
package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.data.annotation.Persistent;
/**
@@ -26,9 +31,15 @@ import org.springframework.data.annotation.Persistent;
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
@Target({ ElementType.TYPE, ElementType.FIELD })
public @interface Mapping {
String mappingPath() default "";
/**
* whether mappings are enabled
*
* @since 4.2
*/
boolean enabled() default true;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,9 +27,10 @@ import java.lang.annotation.Target;
* @author Artur Konczak
* @author Jonathan Yan
* @author Xiao Yu
* @author Peter-Josef Meisch
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Documented
public @interface MultiField {
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,24 +22,32 @@ import java.lang.annotation.*;
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Peter-Josef Meisch
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Documented
public @interface Query {
/**
* Elasticsearch query to be used when executing query. May contain placeholders eg. ?0
*
* @return
* @return Elasticsearch query to be used when executing query. May contain placeholders eg. ?0
*/
String value() default "";
/**
* Named Query Named looked up by repository.
*
* @return
* @deprecated since 4.2, not implemented and used anywhere
*/
String name() default "";
/**
* Returns whether the query defined should be executed as count projection.
*
* @return {@literal false} by default.
* @since 4.2
*/
boolean count() default false;
}
@@ -0,0 +1,43 @@
/*
* Copyright2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.data.annotation.Persistent;
/**
* Annotation to enable custom routing values for an entity.
*
* @author Peter-Josef Meisch
* @since 4.2
*/
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface Routing {
/**
* defines how the routing is determined. Can be either the name of a property or a SpEL expression. See the reference
* documentation for examples how to use this annotation.
*/
String value();
}
@@ -1,28 +0,0 @@
package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.elasticsearch.core.SearchHit;
/**
* Specifies that this field is used for storing the document score.
*
* @author Sascha Woo
* @author Peter-Josef Meisch
* @since 3.1
* @deprecated since 4.0, use {@link SearchHit#getScore()} instead
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
@ReadOnlyProperty
@Deprecated
public @interface Score {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,11 @@
*/
package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.data.annotation.Persistent;
@@ -23,14 +27,84 @@ import org.springframework.data.annotation.Persistent;
* Elasticsearch Setting
*
* @author Mohsin Husen
* @author Peter-Josef Meisch
*/
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Target({ ElementType.TYPE })
public @interface Setting {
/**
* Resource path for a settings configuration
*/
String settingPath() default "";
/**
* Use server-side settings when creating the index.
*/
boolean useServerConfiguration() default false;
/**
* Number of shards for the index. Used for index creation. <br/>
* With version 4.0, the default value is changed from 5 to 1 to reflect the change in the default settings of
* Elasticsearch which changed to 1 as well in Elasticsearch 7.0.
*/
short shards() default 1;
/**
* Number of replicas for the index. Used for index creation.
*/
short replicas() default 1;
/**
* Refresh interval for the index. Used for index creation.
*/
String refreshInterval() default "1s";
/**
* Index storage type for the index. Used for index creation.
*/
String indexStoreType() default "fs";
/**
* fields to define an index sorting
*
* @since 4.2
*/
String[] sortFields() default {};
/**
* defines the order for {@link #sortFields()}. If present, it must have the same number of elements
*
* @since 4.2
*/
SortOrder[] sortOrders() default {};
/**
* defines the mode for {@link #sortFields()}. If present, it must have the same number of elements
*
* @since 4.2
*/
SortMode[] sortModes() default {};
/**
* defines the missing value for {@link #sortFields()}. If present, it must have the same number of elements
*
* @since 4.2
*/
SortMissing[] sortMissingValues() default {};
enum SortOrder {
asc, desc
}
enum SortMode {
min, max
}
enum SortMissing {
_last, _first
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 the original author or authors.
* Copyright 2019-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 the original author or authors.
* Copyright 2019-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,5 +20,5 @@ package org.springframework.data.elasticsearch.annotations;
* @since 4.0
*/
public enum TermVector {
none, no, yes, with_positions, with_offsets, with_positions_offsets, with_positions_payloads, with_positions_offets_payloads
none, no, yes, with_positions, with_offsets, with_positions_offsets, with_positions_payloads, with_positions_offsets_payloads
}
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import java.util.function.Supplier;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.function.client.WebClient;
@@ -171,6 +172,12 @@ public interface ClientConfiguration {
*/
Function<WebClient, WebClient> getWebClientConfigurer();
/**
* @return the client configuration callback.
* @since 4.2
*/
HttpClientConfigCallback getHttpClientConfigurer();
/**
* @return the supplier for custom headers.
*/
@@ -341,13 +348,22 @@ public interface ClientConfiguration {
*/
TerminalClientConfigurationBuilder withWebClientConfigurer(Function<WebClient, WebClient> webClientConfigurer);
/**
* Register a {HttpClientConfigCallback} to configure the non-reactive REST client.
*
* @param httpClientConfigurer configuration callback, must not be null.
* @return the {@link TerminalClientConfigurationBuilder}.
* @since 4.2
*/
TerminalClientConfigurationBuilder withHttpClientConfigurer(HttpClientConfigCallback httpClientConfigurer);
/**
* set a supplier for custom headers. This is invoked for every HTTP request to Elasticsearch to retrieve headers
* that should be sent with the request. A common use case is passing in authentication headers that may change.
* <br/>
* Note: When used in a reactive environment, the calling of {@link Supplier#get()} function must not do any
* blocking operations. It may return {@literal null}.
*
*
* @param headers supplier function for headers, must not be {@literal null}
* @return the {@link TerminalClientConfigurationBuilder}.
* @since 4.0
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import java.util.stream.Collectors;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationBuilderWithRequiredEndpoint;
import org.springframework.data.elasticsearch.client.ClientConfiguration.MaybeSecureClientConfigurationBuilder;
import org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder;
@@ -61,6 +62,7 @@ class ClientConfigurationBuilder
private @Nullable String proxy;
private Function<WebClient, WebClient> webClientConfigurer = Function.identity();
private Supplier<HttpHeaders> headersSupplier = () -> HttpHeaders.EMPTY;
private HttpClientConfigCallback httpClientConfigurer = httpClientBuilder -> httpClientBuilder;
/*
* (non-Javadoc)
@@ -207,6 +209,15 @@ class ClientConfigurationBuilder
return this;
}
@Override
public TerminalClientConfigurationBuilder withHttpClientConfigurer(HttpClientConfigCallback httpClientConfigurer) {
Assert.notNull(httpClientConfigurer, "httpClientConfigurer must not be null");
this.httpClientConfigurer = httpClientConfigurer;
return this;
}
@Override
public TerminalClientConfigurationBuilder withHeaders(Supplier<HttpHeaders> headers) {
@@ -231,7 +242,7 @@ class ClientConfigurationBuilder
}
return new DefaultClientConfiguration(hosts, headers, useSsl, sslContext, soTimeout, connectTimeout, pathPrefix,
hostnameVerifier, proxy, webClientConfigurer, headersSupplier);
hostnameVerifier, proxy, webClientConfigurer, httpClientConfigurer, headersSupplier);
}
private static InetSocketAddress parse(String hostAndPort) {
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import java.util.function.Supplier;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.function.client.WebClient;
@@ -52,12 +53,14 @@ class DefaultClientConfiguration implements ClientConfiguration {
private final @Nullable HostnameVerifier hostnameVerifier;
private final @Nullable String proxy;
private final Function<WebClient, WebClient> webClientConfigurer;
private final HttpClientConfigCallback httpClientConfigurer;
private final Supplier<HttpHeaders> headersSupplier;
DefaultClientConfiguration(List<InetSocketAddress> hosts, HttpHeaders headers, boolean useSsl,
@Nullable SSLContext sslContext, Duration soTimeout, Duration connectTimeout, @Nullable String pathPrefix,
@Nullable HostnameVerifier hostnameVerifier, @Nullable String proxy,
Function<WebClient, WebClient> webClientConfigurer, Supplier<HttpHeaders> headersSupplier) {
Function<WebClient, WebClient> webClientConfigurer, HttpClientConfigCallback httpClientConfigurer,
Supplier<HttpHeaders> headersSupplier) {
this.hosts = Collections.unmodifiableList(new ArrayList<>(hosts));
this.headers = new HttpHeaders(headers);
@@ -69,6 +72,7 @@ class DefaultClientConfiguration implements ClientConfiguration {
this.hostnameVerifier = hostnameVerifier;
this.proxy = proxy;
this.webClientConfigurer = webClientConfigurer;
this.httpClientConfigurer = httpClientConfigurer;
this.headersSupplier = headersSupplier;
}
@@ -123,6 +127,11 @@ class DefaultClientConfiguration implements ClientConfiguration {
return webClientConfigurer;
}
@Override
public HttpClientConfigCallback getHttpClientConfigurer() {
return httpClientConfigurer;
}
@Override
public Supplier<HttpHeaders> getHeadersSupplier() {
return headersSupplier;
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 the original author or authors.
* Copyright 2015-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,6 +54,7 @@ import org.springframework.util.Assert;
* @author Huw Ayling-Miller
* @author Henrique Amaral
* @author Peter-Josef Meisch
* @author Nic Hines
* @since 3.2
*/
public final class RestClients {
@@ -104,21 +105,22 @@ public final class RestClients {
Duration connectTimeout = clientConfiguration.getConnectTimeout();
if (!connectTimeout.isNegative()) {
requestConfigBuilder.setConnectTimeout(Math.toIntExact(connectTimeout.toMillis()));
requestConfigBuilder.setConnectionRequestTimeout(Math.toIntExact(connectTimeout.toMillis()));
}
Duration timeout = clientConfiguration.getSocketTimeout();
Duration socketTimeout = clientConfiguration.getSocketTimeout();
if (!timeout.isNegative()) {
requestConfigBuilder.setSocketTimeout(Math.toIntExact(timeout.toMillis()));
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);
clientBuilder = clientConfiguration.getHttpClientConfigurer().customizeHttpClient(clientBuilder);
return clientBuilder;
});
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,17 +45,14 @@ import javax.net.ssl.SSLContext;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
import org.elasticsearch.action.admin.indices.flush.FlushResponse;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
@@ -68,6 +65,7 @@ import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequest;
@@ -84,10 +82,7 @@ import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesResponse;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.client.indices.*;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.DeprecationHandler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
@@ -96,8 +91,11 @@ import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.script.mustache.SearchTemplateRequest;
import org.elasticsearch.script.mustache.SearchTemplateResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
@@ -109,9 +107,11 @@ import org.springframework.data.elasticsearch.client.ClientLogger;
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
import org.springframework.data.elasticsearch.client.NoReachableHostException;
import org.springframework.data.elasticsearch.client.reactive.HostProvider.Verification;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient.Cluster;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient.Indices;
import org.springframework.data.elasticsearch.client.util.NamedXContents;
import org.springframework.data.elasticsearch.client.util.ScrollState;
import org.springframework.data.elasticsearch.core.query.ByQueryResponse;
import org.springframework.data.util.Lazy;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -139,13 +139,15 @@ import org.springframework.web.reactive.function.client.WebClient.RequestBodySpe
* @author Russell Parry
* @author Thomas Geese
* @author Brian Clozel
* @author Farid Faoudi
* @author George Popides
* @since 3.2
* @see ClientConfiguration
* @see ReactiveRestClients
*/
public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearchClient, Indices {
public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearchClient, Indices, Cluster {
private final HostProvider hostProvider;
private final HostProvider<?> hostProvider;
private final RequestCreator requestCreator;
private Supplier<HttpHeaders> headersSupplier = () -> HttpHeaders.EMPTY;
@@ -155,7 +157,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
*
* @param hostProvider must not be {@literal null}.
*/
public DefaultReactiveElasticsearchClient(HostProvider hostProvider) {
public DefaultReactiveElasticsearchClient(HostProvider<?> hostProvider) {
this(hostProvider, new DefaultRequestCreator());
}
@@ -166,7 +168,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
* @param hostProvider must not be {@literal null}.
* @param requestCreator must not be {@literal null}.
*/
public DefaultReactiveElasticsearchClient(HostProvider hostProvider, RequestCreator requestCreator) {
public DefaultReactiveElasticsearchClient(HostProvider<?> hostProvider, RequestCreator requestCreator) {
Assert.notNull(hostProvider, "HostProvider must not be null");
Assert.notNull(requestCreator, "RequestCreator must not be null");
@@ -224,7 +226,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
WebClientProvider provider = getWebClientProvider(clientConfiguration);
HostProvider hostProvider = HostProvider.provider(provider, clientConfiguration.getHeadersSupplier(),
HostProvider<?> hostProvider = HostProvider.provider(provider, clientConfiguration.getHeadersSupplier(),
clientConfiguration.getEndpoints().toArray(new InetSocketAddress[0]));
DefaultReactiveElasticsearchClient client = new DefaultReactiveElasticsearchClient(hostProvider, requestCreator);
@@ -279,15 +281,23 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
scheme = "https";
}
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
WebClientProvider provider = WebClientProvider.create(scheme, connector);
WebClientProvider provider = WebClientProvider.create(scheme, new ReactorClientHttpConnector(httpClient));
if (clientConfiguration.getPathPrefix() != null) {
provider = provider.withPathPrefix(clientConfiguration.getPathPrefix());
}
provider = provider.withDefaultHeaders(clientConfiguration.getDefaultHeaders()) //
.withWebClientConfigurer(clientConfiguration.getWebClientConfigurer());
provider = provider //
.withDefaultHeaders(clientConfiguration.getDefaultHeaders()) //
.withWebClientConfigurer(clientConfiguration.getWebClientConfigurer()) //
.withRequestConfigurer(requestHeadersSpec -> requestHeadersSpec.headers(httpHeaders -> {
HttpHeaders suppliedHeaders = clientConfiguration.getHeadersSupplier().get();
if (suppliedHeaders != null && suppliedHeaders != HttpHeaders.EMPTY) {
httpHeaders.addAll(suppliedHeaders);
}
}));
return provider;
}
@@ -298,10 +308,6 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
this.headersSupplier = headersSupplier;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#ping(org.springframework.http.HttpHeaders)
*/
@Override
public Mono<Boolean> ping(HttpHeaders headers) {
@@ -310,10 +316,6 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.onErrorResume(NoReachableHostException.class, error -> Mono.just(false)).next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#info(org.springframework.http.HttpHeaders)
*/
@Override
public Mono<MainResponse> info(HttpHeaders headers) {
@@ -321,10 +323,6 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#get(org.springframework.http.HttpHeaders, org.elasticsearch.action.get.GetRequest)
*/
@Override
public Mono<GetResult> get(HttpHeaders headers, GetRequest getRequest) {
@@ -334,24 +332,14 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#multiGet(org.springframework.http.HttpHeaders, org.elasticsearch.action.get.MultiGetRequest)
*/
@Override
public Flux<GetResult> multiGet(HttpHeaders headers, MultiGetRequest multiGetRequest) {
public Flux<MultiGetItemResponse> multiGet(HttpHeaders headers, MultiGetRequest multiGetRequest) {
return sendRequest(multiGetRequest, requestCreator.multiGet(), MultiGetResponse.class, headers)
.map(MultiGetResponse::getResponses) //
.flatMap(Flux::fromArray) //
.filter(it -> !it.isFailed() && it.getResponse().isExists()) //
.map(it -> DefaultReactiveElasticsearchClient.getResponseToGetResult(it.getResponse()));
.flatMap(Flux::fromArray); //
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#exists(org.springframework.http.HttpHeaders, org.elasticsearch.action.get.GetRequest)
*/
@Override
public Mono<Boolean> exists(HttpHeaders headers, GetRequest getRequest) {
@@ -360,37 +348,26 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#ping(org.springframework.http.HttpHeaders, org.elasticsearch.action.index.IndexRequest)
*/
@Override
public Mono<IndexResponse> index(HttpHeaders headers, IndexRequest indexRequest) {
return sendRequest(indexRequest, requestCreator.index(), IndexResponse.class, headers).next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#indices()
*/
@Override
public Indices indices() {
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#ping(org.springframework.http.HttpHeaders, org.elasticsearch.action.update.UpdateRequest)
*/
@Override
public Cluster cluster() {
return this;
}
@Override
public Mono<UpdateResponse> update(HttpHeaders headers, UpdateRequest updateRequest) {
return sendRequest(updateRequest, requestCreator.update(), UpdateResponse.class, headers).next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#ping(org.springframework.http.HttpHeaders, org.elasticsearch.action.delete.DeleteRequest)
*/
@Override
public Mono<DeleteResponse> delete(HttpHeaders headers, DeleteRequest deleteRequest) {
@@ -398,10 +375,6 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#count(org.springframework.http.HttpHeaders, org.elasticsearch.action.search.SearchRequest)
*/
@Override
public Mono<Long> count(HttpHeaders headers, SearchRequest searchRequest) {
searchRequest.source().trackTotalHits(true);
@@ -413,10 +386,12 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#ping(org.springframework.http.HttpHeaders, org.elasticsearch.action.search.SearchRequest)
*/
@Override
public Flux<SearchHit> searchTemplate(HttpHeaders headers, SearchTemplateRequest searchTemplateRequest) {
return sendRequest(searchTemplateRequest, requestCreator.searchTemplate(), SearchTemplateResponse.class, headers)
.map(response -> response.getResponse().getHits()).flatMap(Flux::fromIterable);
}
@Override
public Flux<SearchHit> search(HttpHeaders headers, SearchRequest searchRequest) {
@@ -436,10 +411,6 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.map(SearchResponse::getSuggest);
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#aggregate(org.springframework.http.HttpHeaders, org.elasticsearch.action.search.SearchRequest)
*/
@Override
public Flux<Aggregation> aggregate(HttpHeaders headers, SearchRequest searchRequest) {
@@ -454,10 +425,6 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.flatMap(Flux::fromIterable);
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#scroll(org.springframework.http.HttpHeaders, org.elasticsearch.action.search.SearchRequest)
*/
@Override
public Flux<SearchHit> scroll(HttpHeaders headers, SearchRequest searchRequest) {
@@ -507,10 +474,6 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
return sendRequest(clearScrollRequest, requestCreator.clearScroll(), ClearScrollResponse.class, headers);
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#ping(org.springframework.http.HttpHeaders, org.elasticsearch.index.reindex.DeleteByQueryRequest)
*/
@Override
public Mono<BulkByScrollResponse> deleteBy(HttpHeaders headers, DeleteByQueryRequest deleteRequest) {
@@ -518,10 +481,13 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#bulk(org.springframework.http.HttpHeaders, org.elasticsearch.action.bulk.BulkRequest)
*/
@Override
public Mono<ByQueryResponse> updateBy(HttpHeaders headers, UpdateByQueryRequest updateRequest) {
return sendRequest(updateRequest, requestCreator.updateByQuery(), BulkByScrollResponse.class, headers) //
.next() //
.map(ByQueryResponse::of);
}
@Override
public Mono<BulkResponse> bulk(HttpHeaders headers, BulkRequest bulkRequest) {
return sendRequest(bulkRequest, requestCreator.bulk(), BulkResponse.class, headers) //
@@ -535,8 +501,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.flatMap(callback::doWithClient) //
.onErrorResume(throwable -> {
if (throwable instanceof ConnectException) {
if (isCausedByConnectionException(throwable)) {
return hostProvider.getActive(Verification.ACTIVE) //
.flatMap(callback::doWithClient);
}
@@ -545,6 +510,27 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
});
}
/**
* checks if the given throwable is a {@link ConnectException} or has one in it's cause chain
*
* @param throwable the throwable to check
* @return true if throwable is caused by a {@link ConnectException}
*/
private boolean isCausedByConnectionException(Throwable throwable) {
Throwable t = throwable;
do {
if (t instanceof ConnectException) {
return true;
}
t = t.getCause();
} while (t != null);
return false;
}
@Override
public Mono<Status> status() {
@@ -606,12 +592,6 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
request.getOptions().getHeaders().forEach(it -> theHeaders.add(it.getName(), it.getValue()));
}
}
// plus the ones from the supplier
HttpHeaders suppliedHeaders = headersSupplier.get();
if (suppliedHeaders != null && suppliedHeaders != HttpHeaders.EMPTY) {
theHeaders.addAll(suppliedHeaders);
}
});
if (request.getEntity() != null) {
@@ -621,8 +601,8 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
ClientLogger.logRequest(logId, request.getMethod().toUpperCase(), request.getEndpoint(), request.getParameters(),
body::get);
requestBodySpec.contentType(MediaType.valueOf(request.getEntity().getContentType().getValue()));
requestBodySpec.body(Mono.fromSupplier(body), String.class);
requestBodySpec.contentType(MediaType.valueOf(request.getEntity().getContentType().getValue()))
.body(Mono.fromSupplier(body), String.class);
} else {
ClientLogger.logRequest(logId, request.getMethod().toUpperCase(), request.getEndpoint(), request.getParameters());
}
@@ -632,13 +612,22 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
// region indices operations
@Override
public Mono<Boolean> createIndex(HttpHeaders headers, CreateIndexRequest createIndexRequest) {
public Mono<Boolean> createIndex(HttpHeaders headers,
org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest) {
return sendRequest(createIndexRequest, requestCreator.indexCreate(), AcknowledgedResponse.class, headers) //
.map(AcknowledgedResponse::isAcknowledged) //
.next();
}
@Override
public Mono<Boolean> createIndex(HttpHeaders headers, CreateIndexRequest createIndexRequest) {
return sendRequest(createIndexRequest, requestCreator.createIndexRequest(), AcknowledgedResponse.class, headers) //
.map(AcknowledgedResponse::isAcknowledged) //
.next();
}
@Override
public Mono<Void> closeIndex(HttpHeaders headers, CloseIndexRequest closeIndexRequest) {
@@ -647,13 +636,21 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
}
@Override
public Mono<Boolean> existsIndex(HttpHeaders headers, GetIndexRequest request) {
public Mono<Boolean> existsIndex(HttpHeaders headers,
org.elasticsearch.action.admin.indices.get.GetIndexRequest request) {
return sendRequest(request, requestCreator.indexExists(), RawActionResponse.class, headers) //
.flatMap(response -> response.releaseBody().thenReturn(response.statusCode().is2xxSuccessful())) //
.next();
}
@Override
public Mono<Boolean> existsIndex(HttpHeaders headers, GetIndexRequest request) {
return sendRequest(request, requestCreator.indexExistsRequest(), RawActionResponse.class, headers) //
.flatMap(response -> response.releaseBody().thenReturn(response.statusCode().is2xxSuccessful())) //
.next();
}
@Override
public Mono<Boolean> deleteIndex(HttpHeaders headers, DeleteIndexRequest request) {
@@ -669,9 +666,25 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.then();
}
@Override
@Deprecated
public Mono<org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse> getMapping(HttpHeaders headers,
org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest) {
return sendRequest(getMappingsRequest, requestCreator.getMapping(),
org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse.class, headers).next();
}
@Override
public Mono<GetMappingsResponse> getMapping(HttpHeaders headers, GetMappingsRequest getMappingsRequest) {
return sendRequest(getMappingsRequest, requestCreator.getMapping(), GetMappingsResponse.class, headers).next();
return sendRequest(getMappingsRequest, requestCreator.getMappingRequest(), GetMappingsResponse.class, headers) //
.next();
}
@Override
public Mono<GetFieldMappingsResponse> getFieldMapping(HttpHeaders headers,
GetFieldMappingsRequest getFieldMappingsRequest) {
return sendRequest(getFieldMappingsRequest, requestCreator.getFieldMapping(), GetFieldMappingsResponse.class,
headers).next();
}
@Override
@@ -680,13 +693,21 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
}
@Override
public Mono<Boolean> putMapping(HttpHeaders headers, PutMappingRequest putMappingRequest) {
public Mono<Boolean> putMapping(HttpHeaders headers,
org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) {
return sendRequest(putMappingRequest, requestCreator.putMapping(), AcknowledgedResponse.class, headers) //
.map(AcknowledgedResponse::isAcknowledged) //
.next();
}
@Override
public Mono<Boolean> putMapping(HttpHeaders headers, PutMappingRequest putMappingRequest) {
return sendRequest(putMappingRequest, requestCreator.putMappingRequest(), AcknowledgedResponse.class, headers) //
.map(AcknowledgedResponse::isAcknowledged) //
.next();
}
@Override
public Mono<Void> openIndex(HttpHeaders headers, OpenIndexRequest request) {
@@ -738,6 +759,19 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
.map(AcknowledgedResponse::isAcknowledged).next();
}
@Override
public Mono<GetIndexResponse> getIndex(HttpHeaders headers, GetIndexRequest getIndexRequest) {
return sendRequest(getIndexRequest, requestCreator.getIndex(), GetIndexResponse.class, headers).next();
}
// endregion
// region cluster operations
@Override
public Mono<ClusterHealthResponse> health(HttpHeaders headers, ClusterHealthRequest clusterHealthRequest) {
return sendRequest(clusterHealthRequest, requestCreator.clusterHealth(), ClusterHealthResponse.class, headers)
.next();
}
// endregion
// region helper functions
@@ -823,6 +857,9 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
String mediaType = response.headers().contentType().map(MediaType::toString).orElse(XContentType.JSON.mediaType());
return response.body(BodyExtractors.toMono(byte[].class)) //
.switchIfEmpty(Mono.error(
new ElasticsearchStatusException(String.format("%s request to %s returned error code %s and no body.",
request.getMethod(), request.getEndpoint(), statusCode), status)))
.map(bytes -> new String(bytes, StandardCharsets.UTF_8)) //
.flatMap(content -> contentOrError(content, mediaType, status))
.flatMap(unused -> Mono
@@ -890,7 +927,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
} while (token == XContentParser.Token.FIELD_NAME);
return null;
} catch (IOException e) {
} catch (Exception e) {
return new ElasticsearchStatusException(content, status);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.Builder;
import org.springframework.web.util.DefaultUriBuilderFactory;
/**
* Default {@link WebClientProvider} that uses cached {@link WebClient} instances per {@code hostAndPort}.
@@ -45,8 +46,9 @@ class DefaultWebClientProvider implements WebClientProvider {
private final @Nullable ClientHttpConnector connector;
private final Consumer<Throwable> errorListener;
private final HttpHeaders headers;
private final String pathPrefix;
private final @Nullable String pathPrefix;
private final Function<WebClient, WebClient> webClientConfigurer;
private final Consumer<WebClient.RequestHeadersSpec<?>> requestConfigurer;
/**
* Create new {@link DefaultWebClientProvider} with empty {@link HttpHeaders} and no-op {@literal error listener}.
@@ -55,28 +57,31 @@ class DefaultWebClientProvider implements WebClientProvider {
* @param connector can be {@literal null}.
*/
DefaultWebClientProvider(String scheme, @Nullable ClientHttpConnector connector) {
this(scheme, connector, e -> {}, HttpHeaders.EMPTY, null, Function.identity());
this(scheme, connector, e -> {}, HttpHeaders.EMPTY, null, Function.identity(), requestHeadersSpec -> {});
}
/**
* Create new {@link DefaultWebClientProvider} with empty {@link HttpHeaders} and no-op {@literal error listener}.
*
* @param pathPrefix can be {@literal null}
* @param scheme must not be {@literal null}.
* @param connector can be {@literal null}.
* @param errorListener must not be {@literal null}.
* @param headers must not be {@literal null}.
* @param pathPrefix can be {@literal null}.
* @param webClientConfigurer must not be {@literal null}.
* @param requestConfigurer must not be {@literal null}.
*/
private DefaultWebClientProvider(String scheme, @Nullable ClientHttpConnector connector,
Consumer<Throwable> errorListener, HttpHeaders headers, @Nullable String pathPrefix,
Function<WebClient, WebClient> webClientConfigurer) {
Function<WebClient, WebClient> webClientConfigurer, Consumer<WebClient.RequestHeadersSpec<?>> requestConfigurer) {
Assert.notNull(scheme, "Scheme must not be null! A common scheme would be 'http'.");
Assert.notNull(errorListener, "errorListener must not be null! You may want use a no-op one 'e -> {}' instead.");
Assert.notNull(headers, "headers must not be null! Think about using 'HttpHeaders.EMPTY' as an alternative.");
Assert.notNull(webClientConfigurer,
"webClientConfigurer must not be null! You may want use a no-op one 'Function.identity()' instead.");
Assert.notNull(requestConfigurer,
"requestConfigurer must not be null! You may want use a no-op one 'r -> {}' instead.\"");
this.cachedClients = new ConcurrentHashMap<>();
this.scheme = scheme;
@@ -85,6 +90,7 @@ class DefaultWebClientProvider implements WebClientProvider {
this.headers = headers;
this.pathPrefix = pathPrefix;
this.webClientConfigurer = webClientConfigurer;
this.requestConfigurer = requestConfigurer;
}
@Override
@@ -105,6 +111,7 @@ class DefaultWebClientProvider implements WebClientProvider {
return this.errorListener;
}
@Nullable
@Override
public String getPathPrefix() {
return pathPrefix;
@@ -119,7 +126,17 @@ class DefaultWebClientProvider implements WebClientProvider {
merged.addAll(this.headers);
merged.addAll(headers);
return new DefaultWebClientProvider(scheme, connector, errorListener, merged, pathPrefix, webClientConfigurer);
return new DefaultWebClientProvider(scheme, connector, errorListener, merged, pathPrefix, webClientConfigurer,
requestConfigurer);
}
@Override
public WebClientProvider withRequestConfigurer(Consumer<WebClient.RequestHeadersSpec<?>> requestConfigurer) {
Assert.notNull(requestConfigurer, "requestConfigurer must not be null.");
return new DefaultWebClientProvider(scheme, connector, errorListener, headers, pathPrefix, webClientConfigurer,
requestConfigurer);
}
@Override
@@ -128,7 +145,8 @@ class DefaultWebClientProvider implements WebClientProvider {
Assert.notNull(errorListener, "Error listener must not be null.");
Consumer<Throwable> listener = this.errorListener.andThen(errorListener);
return new DefaultWebClientProvider(scheme, this.connector, listener, headers, pathPrefix, webClientConfigurer);
return new DefaultWebClientProvider(scheme, this.connector, listener, headers, pathPrefix, webClientConfigurer,
requestConfigurer);
}
@Override
@@ -136,19 +154,21 @@ class DefaultWebClientProvider implements WebClientProvider {
Assert.notNull(pathPrefix, "pathPrefix must not be null.");
return new DefaultWebClientProvider(this.scheme, this.connector, this.errorListener, this.headers, pathPrefix,
webClientConfigurer);
webClientConfigurer, requestConfigurer);
}
@Override
public WebClientProvider withWebClientConfigurer(Function<WebClient, WebClient> webClientConfigurer) {
return new DefaultWebClientProvider(scheme, connector, errorListener, headers, pathPrefix, webClientConfigurer);
return new DefaultWebClientProvider(scheme, connector, errorListener, headers, pathPrefix, webClientConfigurer,
requestConfigurer);
}
protected WebClient createWebClientForSocketAddress(InetSocketAddress socketAddress) {
Builder builder = WebClient.builder().defaultHeaders(it -> it.addAll(getDefaultHeaders()));
Builder builder = WebClient.builder() //
.defaultHeaders(it -> it.addAll(getDefaultHeaders())) //
.defaultRequest(requestConfigurer);
if (connector != null) {
builder = builder.clientConnector(connector);
@@ -156,7 +176,16 @@ class DefaultWebClientProvider implements WebClientProvider {
String baseUrl = String.format("%s://%s:%d%s", this.scheme, socketAddress.getHostString(), socketAddress.getPort(),
pathPrefix == null ? "" : '/' + pathPrefix);
WebClient webClient = builder.baseUrl(baseUrl).filter((request, next) -> next.exchange(request).doOnError(errorListener)).build();
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);
// the template will already be encoded by the RequestConverters methods
uriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
builder.uriBuilderFactory(uriBuilderFactory); //
WebClient webClient = builder //
.filter((request, next) -> next.exchange(request) //
.doOnError(errorListener)) //
.build(); //
return webClientConfigurer.apply(webClient);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,28 +34,29 @@ import org.springframework.web.reactive.function.client.WebClient;
*
* @author Christoph Strobl
* @author Mark Paluch
* @author Peter-Josef Meisch
* @since 3.2
*/
public interface HostProvider {
public interface HostProvider<T extends HostProvider<T>> {
/**
* Create a new {@link HostProvider} best suited for the given {@link WebClientProvider} and number of hosts.
*
* @param clientProvider must not be {@literal null} .
* @param headersSupplier to supply custom headers, must not be {@literal null}
* @param headersSupplier to supply custom headers, must not be {@literal null}
* @param endpoints must not be {@literal null} nor empty.
* @return new instance of {@link HostProvider}.
*/
static HostProvider provider(WebClientProvider clientProvider, Supplier<HttpHeaders> headersSupplier,
static HostProvider<?> provider(WebClientProvider clientProvider, Supplier<HttpHeaders> headersSupplier,
InetSocketAddress... endpoints) {
Assert.notNull(clientProvider, "WebClientProvider must not be null");
Assert.notEmpty(endpoints, "Please provide at least one endpoint to connect to.");
if (endpoints.length == 1) {
return new SingleNodeHostProvider(clientProvider, headersSupplier, endpoints[0]);
return new SingleNodeHostProvider(clientProvider, endpoints[0]);
} else {
return new MultiNodeHostProvider(clientProvider,headersSupplier, endpoints);
return new MultiNodeHostProvider(clientProvider, endpoints);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -27,12 +28,12 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
import org.springframework.data.elasticsearch.client.ElasticsearchHost.State;
import org.springframework.data.elasticsearch.client.NoReachableHostException;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
@@ -42,22 +43,25 @@ import org.springframework.web.reactive.function.client.WebClient;
*
* @author Christoph Strobl
* @author Mark Paluch
* @author Peter-Josef Meisch
* @since 3.2
*/
class MultiNodeHostProvider implements HostProvider {
class MultiNodeHostProvider implements HostProvider<MultiNodeHostProvider> {
private final static Logger LOG = LoggerFactory.getLogger(MultiNodeHostProvider.class);
private final WebClientProvider clientProvider;
private final Supplier<HttpHeaders> headersSupplier;
private final Map<InetSocketAddress, ElasticsearchHost> hosts;
MultiNodeHostProvider(WebClientProvider clientProvider, Supplier<HttpHeaders> headersSupplier, InetSocketAddress... endpoints) {
MultiNodeHostProvider(WebClientProvider clientProvider, InetSocketAddress... endpoints) {
this.clientProvider = clientProvider;
this.headersSupplier = headersSupplier;
this.hosts = new ConcurrentHashMap<>();
for (InetSocketAddress endpoint : endpoints) {
this.hosts.put(endpoint, new ElasticsearchHost(endpoint, State.UNKNOWN));
}
LOG.debug("initialized with " + hosts);
}
/*
@@ -66,7 +70,7 @@ class MultiNodeHostProvider implements HostProvider {
*/
@Override
public Mono<ClusterInformation> clusterInfo() {
return nodes(null).map(this::updateNodeState).buffer(hosts.size())
return checkNodes(null).map(this::updateNodeState).buffer(hosts.size())
.then(Mono.just(new ClusterInformation(new LinkedHashSet<>(this.hosts.values()))));
}
@@ -86,14 +90,19 @@ class MultiNodeHostProvider implements HostProvider {
@Override
public Mono<InetSocketAddress> lookupActiveHost(Verification verification) {
LOG.trace("lookupActiveHost " + verification + " from " + hosts());
if (Verification.LAZY.equals(verification)) {
for (ElasticsearchHost entry : hosts()) {
if (entry.isOnline()) {
LOG.trace("lookupActiveHost returning " + entry);
return Mono.just(entry.getEndpoint());
}
}
LOG.trace("no online host found with LAZY");
}
LOG.trace("searching for active host");
return findActiveHostInKnownActives() //
.switchIfEmpty(findActiveHostInUnresolved()) //
.switchIfEmpty(findActiveHostInDead()) //
@@ -105,20 +114,30 @@ class MultiNodeHostProvider implements HostProvider {
}
private Mono<InetSocketAddress> findActiveHostInKnownActives() {
return findActiveForSate(State.ONLINE);
return findActiveForState(State.ONLINE);
}
private Mono<InetSocketAddress> findActiveHostInUnresolved() {
return findActiveForSate(State.UNKNOWN);
return findActiveForState(State.UNKNOWN);
}
private Mono<InetSocketAddress> findActiveHostInDead() {
return findActiveForSate(State.OFFLINE);
return findActiveForState(State.OFFLINE);
}
private Mono<InetSocketAddress> findActiveForSate(State state) {
return nodes(state).map(this::updateNodeState).filter(ElasticsearchHost::isOnline)
.map(ElasticsearchHost::getEndpoint).next();
private Mono<InetSocketAddress> findActiveForState(State state) {
LOG.trace("findActiveForState state " + state + ", current hosts: " + hosts);
return checkNodes(state) //
.map(this::updateNodeState) //
.filter(ElasticsearchHost::isOnline) //
.map(elasticsearchHost -> {
LOG.trace("findActiveForState returning host " + elasticsearchHost);
return elasticsearchHost;
}).map(ElasticsearchHost::getEndpoint) //
.takeLast(1) //
.next();
}
private ElasticsearchHost updateNodeState(Tuple2<InetSocketAddress, State> tuple2) {
@@ -129,25 +148,35 @@ class MultiNodeHostProvider implements HostProvider {
return elasticsearchHost;
}
private Flux<Tuple2<InetSocketAddress, State>> nodes(@Nullable State state) {
private Flux<Tuple2<InetSocketAddress, State>> checkNodes(@Nullable State state) {
LOG.trace("checkNodes() with state " + state);
return Flux.fromIterable(hosts()) //
.filter(entry -> state == null || entry.getState().equals(state)) //
.map(ElasticsearchHost::getEndpoint) //
.flatMap(host -> {
.concatMap(host -> {
Mono<ClientResponse> exchange = createWebClient(host) //
LOG.trace("checking host " + host);
Mono<ClientResponse> clientResponseMono = createWebClient(host) //
.head().uri("/") //
.headers(httpHeaders -> httpHeaders.addAll(headersSupplier.get())) //
.exchange().doOnError(throwable -> {
.exchangeToMono(Mono::just) //
.timeout(Duration.ofSeconds(1)) //
.doOnError(throwable -> {
LOG.trace("error checking host " + host + ", " + throwable.getMessage());
hosts.put(host, new ElasticsearchHost(host, State.OFFLINE));
clientProvider.getErrorListener().accept(throwable);
});
return Mono.just(host).zipWith(exchange
.flatMap(it -> it.releaseBody().thenReturn(it.statusCode().isError() ? State.OFFLINE : State.ONLINE)));
return Mono.just(host) //
.zipWith(clientResponseMono.flatMap(it -> it.releaseBody() //
.thenReturn(it.statusCode().isError() ? State.OFFLINE : State.ONLINE)));
}) //
.onErrorContinue((throwable, o) -> clientProvider.getErrorListener().accept(throwable));
.map(tuple -> {
LOG.trace("check result " + tuple);
return tuple;
}).onErrorContinue((throwable, o) -> clientProvider.getErrorListener().accept(throwable));
}
private List<ElasticsearchHost> hosts() {
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,16 +22,13 @@ import java.net.ConnectException;
import java.util.Collection;
import java.util.function.Consumer;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
@@ -42,6 +39,7 @@ import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
@@ -51,18 +49,18 @@ import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesResponse;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.client.indices.*;
import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.script.mustache.SearchTemplateRequest;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.suggest.Suggest;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
import org.springframework.data.elasticsearch.core.query.ByQueryResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@@ -77,6 +75,7 @@ import org.springframework.web.reactive.function.client.WebClient;
* @author Peter-Josef Meisch
* @author Henrique Amaral
* @author Thomas Geese
* @author Farid Faoudi
* @since 3.2
* @see ClientConfiguration
* @see ReactiveRestClients
@@ -161,9 +160,9 @@ public interface ReactiveElasticsearchClient {
* @param consumer never {@literal null}.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html">Multi Get API on
* elastic.co</a>
* @return the {@link Flux} emitting the {@link GetResult result}.
* @return the {@link Flux} emitting the {@link MultiGetItemResponse result}.
*/
default Flux<GetResult> multiGet(Consumer<MultiGetRequest> consumer) {
default Flux<MultiGetItemResponse> multiGet(Consumer<MultiGetRequest> consumer) {
MultiGetRequest request = new MultiGetRequest();
consumer.accept(request);
@@ -177,9 +176,9 @@ public interface ReactiveElasticsearchClient {
* @param multiGetRequest must not be {@literal null}.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html">Multi Get API on
* elastic.co</a>
* @return the {@link Flux} emitting the {@link GetResult result}.
* @return the {@link Flux} emitting the {@link MultiGetItemResponse result}.
*/
default Flux<GetResult> multiGet(MultiGetRequest multiGetRequest) {
default Flux<MultiGetItemResponse> multiGet(MultiGetRequest multiGetRequest) {
return multiGet(HttpHeaders.EMPTY, multiGetRequest);
}
@@ -191,9 +190,9 @@ public interface ReactiveElasticsearchClient {
* @param multiGetRequest must not be {@literal null}.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html">Multi Get API on
* elastic.co</a>
* @return the {@link Flux} emitting the {@link GetResult result}.
* @return the {@link Flux} emitting the {@link MultiGetItemResponse result}.
*/
Flux<GetResult> multiGet(HttpHeaders headers, MultiGetRequest multiGetRequest);
Flux<MultiGetItemResponse> multiGet(HttpHeaders headers, MultiGetRequest multiGetRequest);
/**
* Checks for the existence of a document. Emits {@literal true} if it exists, {@literal false} otherwise.
@@ -272,6 +271,14 @@ public interface ReactiveElasticsearchClient {
*/
Indices indices();
/**
* Gain Access to cluster related commands.
*
* @return Cluster implementations
* @since 4.2
*/
Cluster cluster();
/**
* Execute an {@link UpdateRequest} against the {@literal update} API to alter a document.
*
@@ -389,6 +396,43 @@ public interface ReactiveElasticsearchClient {
*/
Mono<Long> count(HttpHeaders headers, SearchRequest searchRequest);
/**
* Executes a {@link SearchTemplateRequest} against the {@literal search template} API.
*
* @param consumer must not be {@literal null}.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html">Search Template
* API on elastic.co</a>
* @return the {@link Flux} emitting {@link SearchHit hits} one by one.
*/
default Flux<SearchHit> searchTemplate(Consumer<SearchTemplateRequest> consumer) {
SearchTemplateRequest request = new SearchTemplateRequest();
consumer.accept(request);
return searchTemplate(request);
}
/**
* Executes a {@link SearchTemplateRequest} against the {@literal search template} API.
*
* @param searchTemplateRequest must not be {@literal null}.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html">Search Template
* API on elastic.co</a>
* @return the {@link Flux} emitting {@link SearchHit hits} one by one.
*/
default Flux<SearchHit> searchTemplate(SearchTemplateRequest searchTemplateRequest) {
return searchTemplate(HttpHeaders.EMPTY, searchTemplateRequest);
}
/**
* Executes a {@link SearchTemplateRequest} against the {@literal search template} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param searchTemplateRequest must not be {@literal null}.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html">Search Template
* API on elastic.co</a>
* @return the {@link Flux} emitting {@link SearchHit hits} one by one.
*/
Flux<SearchHit> searchTemplate(HttpHeaders headers, SearchTemplateRequest searchTemplateRequest);
/**
* Execute a {@link SearchRequest} against the {@literal search} API.
*
@@ -593,6 +637,44 @@ public interface ReactiveElasticsearchClient {
*/
Mono<BulkByScrollResponse> deleteBy(HttpHeaders headers, DeleteByQueryRequest deleteRequest);
/**
* Execute a {@link UpdateByQueryRequest} against the {@literal update by query} API.
*
* @param consumer must not be {@literal null}.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html">Update By
* * Query API on elastic.co</a>
* @return a {@link Mono} emitting operation response.
*/
default Mono<ByQueryResponse> updateBy(Consumer<UpdateByQueryRequest> consumer) {
final UpdateByQueryRequest request = new UpdateByQueryRequest();
consumer.accept(request);
return updateBy(request);
}
/**
* Execute a {@link UpdateByQueryRequest} against the {@literal update by query} API.
*
* @param updateRequest must not be {@literal null}.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html">Update By
* * Query API on elastic.co</a>
* @return a {@link Mono} emitting operation response.
*/
default Mono<ByQueryResponse> updateBy(UpdateByQueryRequest updateRequest) {
return updateBy(HttpHeaders.EMPTY, updateRequest);
}
/**
* Execute a {@link UpdateByQueryRequest} against the {@literal update by query} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param updateRequest must not be {@literal null}.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html">Update By
* * Query API on elastic.co</a>
* @return a {@link Mono} emitting operation response.
*/
Mono<ByQueryResponse> updateBy(HttpHeaders headers, UpdateByQueryRequest updateRequest);
/**
* Execute a {@link BulkRequest} against the {@literal bulk} API.
*
@@ -704,20 +786,53 @@ public interface ReactiveElasticsearchClient {
interface Indices {
/**
* Execute the given {@link GetIndexRequest} against the {@literal indices} API.
* Execute the given {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} against the
* {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html"> Indices
* Exists API on elastic.co</a>
* @deprecated since 4.2
*/
default Mono<Boolean> existsIndex(Consumer<GetIndexRequest> consumer) {
@Deprecated
default Mono<Boolean> existsIndex(Consumer<org.elasticsearch.action.admin.indices.get.GetIndexRequest> consumer) {
GetIndexRequest request = new GetIndexRequest();
org.elasticsearch.action.admin.indices.get.GetIndexRequest request = new org.elasticsearch.action.admin.indices.get.GetIndexRequest();
consumer.accept(request);
return existsIndex(request);
}
/**
* Execute the given {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} against the
* {@literal indices} API.
*
* @param getIndexRequest must not be {@literal null}.
* @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html"> Indices
* Exists API on elastic.co</a>
* @deprecated since 4.2, use {@link #existsIndex(GetIndexRequest)}
*/
@Deprecated
default Mono<Boolean> existsIndex(org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest) {
return existsIndex(HttpHeaders.EMPTY, getIndexRequest);
}
/**
* Execute the given {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} against the
* {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param getIndexRequest must not be {@literal null}.
* @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html"> Indices
* Exists API on elastic.co</a>
* @deprecated since 4.2, use {@link #existsIndex(HttpHeaders, GetIndexRequest)}
*/
@Deprecated
Mono<Boolean> existsIndex(HttpHeaders headers,
org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest);
/**
* Execute the given {@link GetIndexRequest} against the {@literal indices} API.
*
@@ -725,6 +840,7 @@ public interface ReactiveElasticsearchClient {
* @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html"> Indices
* Exists API on elastic.co</a>
* @since 4.2
*/
default Mono<Boolean> existsIndex(GetIndexRequest getIndexRequest) {
return existsIndex(HttpHeaders.EMPTY, getIndexRequest);
@@ -738,6 +854,7 @@ public interface ReactiveElasticsearchClient {
* @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html"> Indices
* Exists API on elastic.co</a>
* @since 4.2
*/
Mono<Boolean> existsIndex(HttpHeaders headers, GetIndexRequest getIndexRequest);
@@ -783,21 +900,58 @@ public interface ReactiveElasticsearchClient {
Mono<Boolean> deleteIndex(HttpHeaders headers, DeleteIndexRequest deleteIndexRequest);
/**
* Execute the given {@link CreateIndexRequest} against the {@literal indices} API.
* Execute the given {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequest} against the
* {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if
* eg. the index already exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html"> Indices
* Create API on elastic.co</a>
* @deprecated since 4.2
*/
default Mono<Boolean> createIndex(Consumer<CreateIndexRequest> consumer) {
@Deprecated
default Mono<Boolean> createIndex(
Consumer<org.elasticsearch.action.admin.indices.create.CreateIndexRequest> consumer) {
CreateIndexRequest request = new CreateIndexRequest();
org.elasticsearch.action.admin.indices.create.CreateIndexRequest request = new org.elasticsearch.action.admin.indices.create.CreateIndexRequest();
consumer.accept(request);
return createIndex(request);
}
/**
* Execute the given {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequest} against the
* {@literal indices} API.
*
* @param createIndexRequest must not be {@literal null}.
* @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if
* eg. the index already exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html"> Indices
* Create API on elastic.co</a>
* @deprecated since 4.2, use {@link #createIndex(CreateIndexRequest)}
*/
@Deprecated
default Mono<Boolean> createIndex(
org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest) {
return createIndex(HttpHeaders.EMPTY, createIndexRequest);
}
/**
* Execute the given {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequest} against the
* {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param createIndexRequest must not be {@literal null}.
* @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if
* eg. the index already exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html"> Indices
* Create API on elastic.co</a>
* @deprecated since 4.2, use {@link #createIndex(HttpHeaders, CreateIndexRequest)}
*/
@Deprecated
Mono<Boolean> createIndex(HttpHeaders headers,
org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest);
/**
* Execute the given {@link CreateIndexRequest} against the {@literal indices} API.
*
@@ -806,6 +960,7 @@ public interface ReactiveElasticsearchClient {
* eg. the index already exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html"> Indices
* Create API on elastic.co</a>
* @since 4.2
*/
default Mono<Boolean> createIndex(CreateIndexRequest createIndexRequest) {
return createIndex(HttpHeaders.EMPTY, createIndexRequest);
@@ -820,6 +975,7 @@ public interface ReactiveElasticsearchClient {
* eg. the index already exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html"> Indices
* Create API on elastic.co</a>
* @since 4.2
*/
Mono<Boolean> createIndex(HttpHeaders headers, CreateIndexRequest createIndexRequest);
@@ -947,7 +1103,8 @@ public interface ReactiveElasticsearchClient {
Mono<Void> refreshIndex(HttpHeaders headers, RefreshRequest refreshRequest);
/**
* Execute the given {@link PutMappingRequest} against the {@literal indices} API.
* Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the
* {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
@@ -957,12 +1114,14 @@ public interface ReactiveElasticsearchClient {
* @deprecated since 4.1, use {@link #putMapping(Consumer)}
*/
@Deprecated
default Mono<Boolean> updateMapping(Consumer<PutMappingRequest> consumer) {
default Mono<Boolean> updateMapping(
Consumer<org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest> consumer) {
return putMapping(consumer);
}
/**
* Execute the given {@link PutMappingRequest} against the {@literal indices} API.
* Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the
* {@literal indices} API.
*
* @param putMappingRequest must not be {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
@@ -972,12 +1131,14 @@ public interface ReactiveElasticsearchClient {
* @deprecated since 4.1, use {@link #putMapping(PutMappingRequest)}
*/
@Deprecated
default Mono<Boolean> updateMapping(PutMappingRequest putMappingRequest) {
default Mono<Boolean> updateMapping(
org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) {
return putMapping(putMappingRequest);
}
/**
* Execute the given {@link PutMappingRequest} against the {@literal indices} API.
* Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the
* {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param putMappingRequest must not be {@literal null}.
@@ -988,26 +1149,64 @@ public interface ReactiveElasticsearchClient {
* @deprecated since 4.1, use {@link #putMapping(HttpHeaders, PutMappingRequest)}
*/
@Deprecated
default Mono<Boolean> updateMapping(HttpHeaders headers, PutMappingRequest putMappingRequest) {
default Mono<Boolean> updateMapping(HttpHeaders headers,
org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) {
return putMapping(headers, putMappingRequest);
}
/**
* Execute the given {@link PutMappingRequest} against the {@literal indices} API.
* Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the
* {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
* Put Mapping API on elastic.co</a>
* @deprecated since 4.2
*/
default Mono<Boolean> putMapping(Consumer<PutMappingRequest> consumer) {
@Deprecated
default Mono<Boolean> putMapping(
Consumer<org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest> consumer) {
PutMappingRequest request = new PutMappingRequest();
org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest request = new org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest();
consumer.accept(request);
return putMapping(request);
}
/**
* Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the
* {@literal indices} API.
*
* @param putMappingRequest must not be {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
* Put Mapping API on elastic.co</a>
* @deprecated since 4.2, use {@link #putMapping(PutMappingRequest)}
*/
@Deprecated
default Mono<Boolean> putMapping(
org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) {
return putMapping(HttpHeaders.EMPTY, putMappingRequest);
}
/**
* Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the
* {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param putMappingRequest must not be {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
* Put Mapping API on elastic.co</a>
* @deprecated since 4.2, use {@link #putMapping(HttpHeaders, PutMappingRequest)}
*/
@Deprecated
Mono<Boolean> putMapping(HttpHeaders headers,
org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest);
/**
* Execute the given {@link PutMappingRequest} against the {@literal indices} API.
*
@@ -1016,6 +1215,7 @@ public interface ReactiveElasticsearchClient {
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
* Put Mapping API on elastic.co</a>
* @since 4.2
*/
default Mono<Boolean> putMapping(PutMappingRequest putMappingRequest) {
return putMapping(HttpHeaders.EMPTY, putMappingRequest);
@@ -1030,6 +1230,7 @@ public interface ReactiveElasticsearchClient {
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
* Put Mapping API on elastic.co</a>
* @since 4.2
*/
Mono<Boolean> putMapping(HttpHeaders headers, PutMappingRequest putMappingRequest);
@@ -1119,7 +1320,8 @@ public interface ReactiveElasticsearchClient {
Mono<GetSettingsResponse> getSettings(HttpHeaders headers, GetSettingsRequest getSettingsRequest);
/**
* Execute the given {@link GetMappingsRequest} against the {@literal indices} API.
* Execute the given {@link org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest} against the
* {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
@@ -1127,14 +1329,52 @@ public interface ReactiveElasticsearchClient {
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html"> Indices
* Flush API on elastic.co</a>
* @since 4.1
* @deprecated since 4.2
*/
default Mono<GetMappingsResponse> getMapping(Consumer<GetMappingsRequest> consumer) {
@Deprecated
default Mono<org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse> getMapping(
Consumer<org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest> consumer) {
GetMappingsRequest request = new GetMappingsRequest();
org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest request = new org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest();
consumer.accept(request);
return getMapping(request);
}
/**
* Execute the given {@link org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest} against the
* {@literal indices} API.
*
* @param getMappingsRequest must not be {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html"> Indices
* Flush API on elastic.co</a>
* @since 4.1
* @deprecated since 4.2, use {@link #getMapping(GetMappingsRequest)}
*/
@Deprecated
default Mono<org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse> getMapping(
org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest) {
return getMapping(HttpHeaders.EMPTY, getMappingsRequest);
}
/**
* Execute the given {@link org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest} against the
* {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param getMappingsRequest must not be {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html"> Indices
* Flush API on elastic.co</a>
* @since 4.1
* @deprecated since 4.2, use {@link #getMapping(HttpHeaders, GetMappingsRequest)}
*/
@Deprecated
Mono<org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse> getMapping(HttpHeaders headers,
org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest);
/**
* Execute the given {@link GetMappingsRequest} against the {@literal indices} API.
*
@@ -1142,8 +1382,8 @@ public interface ReactiveElasticsearchClient {
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html"> Indices
* Flush API on elastic.co</a>
* @since 4.1
* Get mapping API on elastic.co</a>
* @since 4.2
*/
default Mono<GetMappingsResponse> getMapping(GetMappingsRequest getMappingsRequest) {
return getMapping(HttpHeaders.EMPTY, getMappingsRequest);
@@ -1157,14 +1397,59 @@ public interface ReactiveElasticsearchClient {
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html"> Indices
* Flush API on elastic.co</a>
* @since 4.1
* Get mapping API on elastic.co</a>
* @since 4.2
*/
Mono<GetMappingsResponse> getMapping(HttpHeaders headers, GetMappingsRequest getMappingsRequest);
/**
* Execute the given {@link GetFieldMappingsRequest} against the {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html">
* Indices Flush API on elastic.co</a>
* @since 4.2
*/
default Mono<GetFieldMappingsResponse> getFieldMapping(Consumer<GetFieldMappingsRequest> consumer) {
GetFieldMappingsRequest request = new GetFieldMappingsRequest();
consumer.accept(request);
return getFieldMapping(request);
}
/**
* Execute the given {@link GetFieldMappingsRequest} against the {@literal indices} API.
*
* @param getFieldMappingsRequest must not be {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html">
* Indices Flush API on elastic.co</a>
* @since 4.2
*/
default Mono<GetFieldMappingsResponse> getFieldMapping(GetFieldMappingsRequest getFieldMappingsRequest) {
return getFieldMapping(HttpHeaders.EMPTY, getFieldMappingsRequest);
}
/**
* Execute the given {@link GetFieldMappingsRequest} against the {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param getFieldMappingsRequest must not be {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html">
* Indices Flush API on elastic.co</a>
* @since 4.2
*/
Mono<GetFieldMappingsResponse> getFieldMapping(HttpHeaders headers,
GetFieldMappingsRequest getFieldMappingsRequest);
/**
* Execute the given {@link IndicesAliasesRequest} against the {@literal indices} API.
*
*
* @param consumer never {@literal null}.
* @return a {@link Mono} signalling operation completion.
* @since 4.1
@@ -1177,7 +1462,7 @@ public interface ReactiveElasticsearchClient {
/**
* Execute the given {@link IndicesAliasesRequest} against the {@literal indices} API.
*
*
* @param indicesAliasesRequest must not be {@literal null}
* @return a {@link Mono} signalling operation completion.
* @since 4.1
@@ -1188,7 +1473,7 @@ public interface ReactiveElasticsearchClient {
/**
* Execute the given {@link IndicesAliasesRequest} against the {@literal indices} API.
*
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param indicesAliasesRequest must not be {@literal null}
* @return a {@link Mono} signalling operation completion.
@@ -1368,5 +1653,80 @@ public interface ReactiveElasticsearchClient {
* @since 4.1
*/
Mono<Boolean> deleteTemplate(HttpHeaders headers, DeleteIndexTemplateRequest deleteIndexTemplateRequest);
/**
* Execute the given {@link GetIndexRequest} against the {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return the {@link Mono} emitting the response
* @since 4.2
*/
default Mono<GetIndexResponse> getIndex(Consumer<GetIndexRequest> consumer) {
GetIndexRequest getIndexRequest = new GetIndexRequest();
consumer.accept(getIndexRequest);
return getIndex(getIndexRequest);
}
/**
* Execute the given {@link GetIndexRequest} against the {@literal indices} API.
*
* @param getIndexRequest must not be {@literal null}
* @return the {@link Mono} emitting the response
* @since 4.2
*/
default Mono<GetIndexResponse> getIndex(GetIndexRequest getIndexRequest) {
return getIndex(HttpHeaders.EMPTY, getIndexRequest);
}
/**
* Execute the given {@link GetIndexRequest} against the {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param getIndexRequest must not be {@literal null}
* @return the {@link Mono} emitting the response
* @since 4.2
*/
Mono<GetIndexResponse> getIndex(HttpHeaders headers, GetIndexRequest getIndexRequest);
}
/**
* Encapsulation of methods for accessing the Cluster API.
*
* @author Peter-Josef Meisch
* @since 4.2
*/
interface Cluster {
/**
* Execute the given {{@link ClusterHealthRequest}} against the {@literal cluster} API.
*
* @param consumer never {@literal null}.
* @return Mono emitting the {@link ClusterHealthResponse}.
*/
default Mono<ClusterHealthResponse> health(Consumer<ClusterHealthRequest> consumer) {
ClusterHealthRequest clusterHealthRequest = new ClusterHealthRequest();
consumer.accept(clusterHealthRequest);
return health(clusterHealthRequest);
}
/**
* Execute the given {{@link ClusterHealthRequest}} against the {@literal cluster} API.
*
* @param clusterHealthRequest must not be {@literal null} // * @return Mono emitting the
* {@link ClusterHealthResponse}.
*/
default Mono<ClusterHealthResponse> health(ClusterHealthRequest clusterHealthRequest) {
return health(HttpHeaders.EMPTY, clusterHealthRequest);
}
/**
* Execute the given {{@link ClusterHealthRequest}} against the {@literal cluster} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param clusterHealthRequest must not be {@literal null} // * @return Mono emitting the
* {@link ClusterHealthResponse}.
*/
Mono<ClusterHealthResponse> health(HttpHeaders headers, ClusterHealthRequest clusterHealthRequest);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -3,15 +3,12 @@ package org.springframework.data.elasticsearch.client.reactive;
import java.io.IOException;
import java.util.function.Function;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
@@ -28,15 +25,24 @@ import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetFieldMappingsRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.GetMappingsRequest;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.client.indices.PutMappingRequest;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.script.mustache.SearchTemplateRequest;
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
import org.springframework.data.elasticsearch.client.util.RequestConverters;
/**
* @author Roman Puchkovskiy
* @author Farid Faoudi
* @author George Popides
* @since 4.0
*/
public interface RequestCreator {
@@ -45,6 +51,10 @@ public interface RequestCreator {
return RequestConverters::search;
}
default Function<SearchTemplateRequest, Request> searchTemplate() {
return RequestConverters::searchTemplate;
}
default Function<SearchScrollRequest, Request> scroll() {
return RequestConverters::searchScroll;
}
@@ -89,6 +99,13 @@ public interface RequestCreator {
return RequestConverters::deleteByQuery;
}
/**
* @since 4.2
*/
default Function<UpdateByQueryRequest, Request> updateByQuery() {
return RequestConverters::updateByQuery;
}
default Function<BulkRequest, Request> bulk() {
return request -> {
@@ -103,7 +120,18 @@ public interface RequestCreator {
// --> INDICES
default Function<GetIndexRequest, Request> indexExists() {
/**
* @deprecated since 4.2
*/
@Deprecated
default Function<org.elasticsearch.action.admin.indices.get.GetIndexRequest, Request> indexExists() {
return RequestConverters::indexExists;
}
/**
* @since 4.2
*/
default Function<GetIndexRequest, Request> indexExistsRequest() {
return RequestConverters::indexExists;
}
@@ -111,7 +139,18 @@ public interface RequestCreator {
return RequestConverters::indexDelete;
}
default Function<CreateIndexRequest, Request> indexCreate() {
/**
* @deprecated since 4.2
*/
@Deprecated
default Function<org.elasticsearch.action.admin.indices.create.CreateIndexRequest, Request> indexCreate() {
return RequestConverters::indexCreate;
}
/**
* @since 4.2
*/
default Function<CreateIndexRequest, Request> createIndexRequest() {
return RequestConverters::indexCreate;
}
@@ -127,7 +166,18 @@ public interface RequestCreator {
return RequestConverters::indexRefresh;
}
default Function<PutMappingRequest, Request> putMapping() {
/**
* @deprecated since 4.2
*/
@Deprecated
default Function<org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest, Request> putMapping() {
return RequestConverters::putMapping;
}
/**
* @since 4.2
*/
default Function<PutMappingRequest, Request> putMappingRequest() {
return RequestConverters::putMapping;
}
@@ -148,8 +198,17 @@ public interface RequestCreator {
/**
* @since 4.1
* @deprecated since 4.2
*/
default Function<GetMappingsRequest, Request> getMapping() {
@Deprecated
default Function<org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest, Request> getMapping() {
return RequestConverters::getMapping;
}
/**
* @since 4.2
*/
default Function<GetMappingsRequest, Request> getMappingRequest() {
return RequestConverters::getMapping;
}
@@ -194,4 +253,25 @@ public interface RequestCreator {
default Function<DeleteIndexTemplateRequest, Request> deleteTemplate() {
return RequestConverters::deleteTemplate;
}
/**
* @since 4.2
*/
default Function<GetFieldMappingsRequest, Request> getFieldMapping() {
return RequestConverters::getFieldMapping;
}
/**
* @since 4.2
*/
default Function<GetIndexRequest, Request> getIndex() {
return RequestConverters::getIndex;
}
/**
* @since 4.2
*/
default Function<ClusterHealthRequest, Request> clusterHealth() {
return RequestConverters::clusterHealth;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,12 +19,10 @@ import reactor.core.publisher.Mono;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.function.Supplier;
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
import org.springframework.data.elasticsearch.client.ElasticsearchHost.State;
import org.springframework.data.elasticsearch.client.NoReachableHostException;
import org.springframework.http.HttpHeaders;
import org.springframework.web.reactive.function.client.WebClient;
/**
@@ -32,19 +30,18 @@ import org.springframework.web.reactive.function.client.WebClient;
*
* @author Christoph Strobl
* @author Mark Paluch
* @author Peter-Josef Meisch
* @since 3.2
*/
class SingleNodeHostProvider implements HostProvider {
class SingleNodeHostProvider implements HostProvider<SingleNodeHostProvider> {
private final WebClientProvider clientProvider;
private final Supplier<HttpHeaders> headersSupplier;
private final InetSocketAddress endpoint;
private volatile ElasticsearchHost state;
SingleNodeHostProvider(WebClientProvider clientProvider, Supplier<HttpHeaders> headersSupplier, InetSocketAddress endpoint) {
SingleNodeHostProvider(WebClientProvider clientProvider, InetSocketAddress endpoint) {
this.clientProvider = clientProvider;
this.headersSupplier = headersSupplier;
this.endpoint = endpoint;
this.state = new ElasticsearchHost(this.endpoint, State.UNKNOWN);
}
@@ -57,23 +54,19 @@ class SingleNodeHostProvider implements HostProvider {
public Mono<ClusterInformation> clusterInfo() {
return createWebClient(endpoint) //
.head().uri("/")
.headers(httpHeaders -> httpHeaders.addAll(headersSupplier.get())) //
.exchange() //
.flatMap(it -> {
.head().uri("/") //
.exchangeToMono(it -> {
if (it.statusCode().isError()) {
state = ElasticsearchHost.offline(endpoint);
} else {
state = ElasticsearchHost.online(endpoint);
}
return it.releaseBody().thenReturn(state);
return Mono.just(state);
}).onErrorResume(throwable -> {
state = ElasticsearchHost.offline(endpoint);
clientProvider.getErrorListener().accept(throwable);
return Mono.just(state);
}) //
.map(it -> new ClusterInformation(Collections.singleton(it)));
}).map(elasticsearchHost -> new ClusterInformation(Collections.singleton(elasticsearchHost)));
}
/*
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -101,7 +101,7 @@ public interface WebClientProvider {
/**
* Obtain the {@link String pathPrefix} to be used.
*
*
* @return the pathPrefix if set.
* @since 4.0
*/
@@ -126,7 +126,7 @@ public interface WebClientProvider {
/**
* Create a new instance of {@link WebClientProvider} where HTTP requests are called with the given path prefix.
*
*
* @param pathPrefix Path prefix to add to requests
* @return new instance of {@link WebClientProvider}
* @since 4.0
@@ -136,10 +136,20 @@ public interface WebClientProvider {
/**
* Create a new instance of {@link WebClientProvider} calling the given {@link Function} to configure the
* {@link WebClient}.
*
*
* @param webClientConfigurer configuration function
* @return new instance of {@link WebClientProvider}
* @since 4.0
*/
WebClientProvider withWebClientConfigurer(Function<WebClient, WebClient> webClientConfigurer);
/**
* Create a new instance of {@link WebClientProvider} calling the given {@link Consumer} to configure the requests of
* this {@link WebClient}.
*
* @param requestConfigurer request configuration callback
* @return new instance of {@link WebClientProvider}
* @since 4.3
*/
WebClientProvider withRequestConfigurer(Consumer<WebClient.RequestHeadersSpec<?>> requestConfigurer);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,12 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.elasticsearch.client.analytics.InferencePipelineAggregationBuilder;
import org.elasticsearch.client.analytics.ParsedInference;
import org.elasticsearch.client.analytics.ParsedStringStats;
import org.elasticsearch.client.analytics.ParsedTopMetrics;
import org.elasticsearch.client.analytics.StringStatsAggregationBuilder;
import org.elasticsearch.client.analytics.TopMetricsAggregationBuilder;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.ContextParser;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
@@ -44,6 +50,8 @@ import org.elasticsearch.search.aggregations.bucket.histogram.HistogramAggregati
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedAutoDateHistogram;
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedDateHistogram;
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedHistogram;
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedVariableWidthHistogram;
import org.elasticsearch.search.aggregations.bucket.histogram.VariableWidthHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.missing.MissingAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.missing.ParsedMissing;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
@@ -60,12 +68,7 @@ import org.elasticsearch.search.aggregations.bucket.range.ParsedRange;
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.sampler.InternalSampler;
import org.elasticsearch.search.aggregations.bucket.sampler.ParsedSampler;
import org.elasticsearch.search.aggregations.bucket.terms.DoubleTerms;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedDoubleTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.*;
import org.elasticsearch.search.aggregations.metrics.*;
import org.elasticsearch.search.aggregations.pipeline.*;
import org.elasticsearch.search.suggest.Suggest;
@@ -81,7 +84,7 @@ import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsea
* <p>
* Original implementation source {@link org.elasticsearch.client.RestHighLevelClient#getDefaultNamedXContents()} by
* {@literal Elasticsearch} (<a href="https://www.elastic.co">https://www.elastic.co</a>) licensed under the Apache
* License, Version 2.0.
* License, Version 2.0. The latest version used from Elasticsearch is 7.10.2.
* </p>
* Modified for usage with {@link ReactiveElasticsearchClient}.
* <p>
@@ -126,9 +129,13 @@ public class NamedXContents {
map.put(HistogramAggregationBuilder.NAME, (p, c) -> ParsedHistogram.fromXContent(p, (String) c));
map.put(DateHistogramAggregationBuilder.NAME, (p, c) -> ParsedDateHistogram.fromXContent(p, (String) c));
map.put(AutoDateHistogramAggregationBuilder.NAME, (p, c) -> ParsedAutoDateHistogram.fromXContent(p, (String) c));
map.put(VariableWidthHistogramAggregationBuilder.NAME,
(p, c) -> ParsedVariableWidthHistogram.fromXContent(p, (String) c));
map.put(StringTerms.NAME, (p, c) -> ParsedStringTerms.fromXContent(p, (String) c));
map.put(LongTerms.NAME, (p, c) -> ParsedLongTerms.fromXContent(p, (String) c));
map.put(DoubleTerms.NAME, (p, c) -> ParsedDoubleTerms.fromXContent(p, (String) c));
map.put(LongRareTerms.NAME, (p, c) -> ParsedLongRareTerms.fromXContent(p, (String) c));
map.put(StringRareTerms.NAME, (p, c) -> ParsedStringRareTerms.fromXContent(p, (String) c));
map.put(MissingAggregationBuilder.NAME, (p, c) -> ParsedMissing.fromXContent(p, (String) c));
map.put(NestedAggregationBuilder.NAME, (p, c) -> ParsedNested.fromXContent(p, (String) c));
map.put(ReverseNestedAggregationBuilder.NAME, (p, c) -> ParsedReverseNested.fromXContent(p, (String) c));
@@ -142,10 +149,15 @@ public class NamedXContents {
map.put(GeoDistanceAggregationBuilder.NAME, (p, c) -> ParsedGeoDistance.fromXContent(p, (String) c));
map.put(FiltersAggregationBuilder.NAME, (p, c) -> ParsedFilters.fromXContent(p, (String) c));
map.put(AdjacencyMatrixAggregationBuilder.NAME, (p, c) -> ParsedAdjacencyMatrix.fromXContent(p, (String) c));
map.put(SignificantLongTerms.NAME, (p, c) -> ParsedSignificantLongTerms.fromXContent(p, (String) c));
map.put(SignificantStringTerms.NAME, (p, c) -> ParsedSignificantStringTerms.fromXContent(p, (String) c));
map.put(ScriptedMetricAggregationBuilder.NAME, (p, c) -> ParsedScriptedMetric.fromXContent(p, (String) c));
map.put(IpRangeAggregationBuilder.NAME, (p, c) -> ParsedBinaryRange.fromXContent(p, (String) c));
map.put(TopHitsAggregationBuilder.NAME, (p, c) -> ParsedTopHits.fromXContent(p, (String) c));
map.put(CompositeAggregationBuilder.NAME, (p, c) -> ParsedComposite.fromXContent(p, (String) c));
map.put(StringStatsAggregationBuilder.NAME, (p, c) -> ParsedStringStats.PARSER.parse(p, (String) c));
map.put(TopMetricsAggregationBuilder.NAME, (p, c) -> ParsedTopMetrics.PARSER.parse(p, (String) c));
map.put(InferencePipelineAggregationBuilder.NAME, (p, c) -> ParsedInference.fromXContent(p, (String) (c)));
List<NamedXContentRegistry.Entry> entries = map.entrySet().stream().map(
entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue()))
.collect(Collectors.toList());
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,6 +71,7 @@ import org.elasticsearch.client.Requests;
import org.elasticsearch.client.RethrottleRequest;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.indices.AnalyzeRequest;
import org.elasticsearch.client.indices.GetFieldMappingsRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
@@ -97,6 +98,7 @@ import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.index.reindex.ReindexRequest;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.index.seqno.SequenceNumbers;
import org.elasticsearch.script.mustache.SearchTemplateRequest;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.tasks.TaskId;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
@@ -105,8 +107,9 @@ import org.springframework.lang.Nullable;
/**
* <p>
* Original implementation source {@link org.elasticsearch.client.RequestConverters} and
* {@link org.elasticsearch.client.IndicesRequestConverters} by {@literal Elasticsearch}
* Original implementation source {@link org.elasticsearch.client.RequestConverters},
* {@link org.elasticsearch.client.IndicesRequestConverters} and
* {@link org.elasticsearch.client.ClusterRequestConverters} by {@literal Elasticsearch}
* (<a href="https://www.elastic.co">https://www.elastic.co</a>) licensed under the Apache License, Version 2.0.
* </p>
* Modified for usage with {@link ReactiveElasticsearchClient}.
@@ -115,6 +118,7 @@ import org.springframework.lang.Nullable;
*
* @author Christoph Strobl
* @author Peter-Josef Meisch
* @author Farid Faoudi
* @since 3.2
*/
@SuppressWarnings("JavadocReference")
@@ -409,9 +413,24 @@ public class RequestConverters {
return request;
}
public static Request searchTemplate(SearchTemplateRequest templateRequest) {
SearchRequest searchRequest = templateRequest.getRequest();
String endpoint = new EndpointBuilder().addCommaSeparatedPathParts(templateRequest.getRequest().indices())
.addPathPart("_search").addPathPart("template").build();
Request request = new Request(HttpMethod.GET.name(), endpoint);
Params params = new Params(request);
addSearchRequestParams(params, searchRequest);
request.setEntity(createEntity(templateRequest, REQUEST_BODY_CONTENT_TYPE));
return request;
}
/**
* Creates a count request.
*
*
* @param countRequest the search defining the data to be counted
* @return Elasticsearch count request
* @since 4.0
@@ -536,26 +555,32 @@ public class RequestConverters {
}
public static Request updateByQuery(UpdateByQueryRequest updateByQueryRequest) {
String endpoint = endpoint(updateByQueryRequest.indices(), updateByQueryRequest.getDocTypes(), "_update_by_query");
String endpoint = endpoint(updateByQueryRequest.indices(), "_update_by_query");
Request request = new Request(HttpMethod.POST.name(), endpoint);
Params params = new Params(request).withRouting(updateByQueryRequest.getRouting())
.withPipeline(updateByQueryRequest.getPipeline()).withRefresh(updateByQueryRequest.isRefresh())
.withTimeout(updateByQueryRequest.getTimeout())
.withWaitForActiveShards(updateByQueryRequest.getWaitForActiveShards())
.withRequestsPerSecond(updateByQueryRequest.getRequestsPerSecond())
.withIndicesOptions(updateByQueryRequest.indicesOptions());
Params params = new Params(request).withRouting(updateByQueryRequest.getRouting()) //
.withPipeline(updateByQueryRequest.getPipeline()) //
.withRefresh(updateByQueryRequest.isRefresh()) //
.withTimeout(updateByQueryRequest.getTimeout()) //
.withWaitForActiveShards(updateByQueryRequest.getWaitForActiveShards()) //
.withRequestsPerSecond(updateByQueryRequest.getRequestsPerSecond()) //
.withIndicesOptions(updateByQueryRequest.indicesOptions()); //
if (!updateByQueryRequest.isAbortOnVersionConflict()) {
params.putParam("conflicts", "proceed");
}
if (updateByQueryRequest.getBatchSize() != AbstractBulkByScrollRequest.DEFAULT_SCROLL_SIZE) {
params.putParam("scroll_size", Integer.toString(updateByQueryRequest.getBatchSize()));
}
if (updateByQueryRequest.getScrollTime() != AbstractBulkByScrollRequest.DEFAULT_SCROLL_TIMEOUT) {
params.putParam("scroll", updateByQueryRequest.getScrollTime());
}
if (updateByQueryRequest.getSize() > 0) {
params.putParam("size", Integer.toString(updateByQueryRequest.getSize()));
if (updateByQueryRequest.getMaxDocs() > 0) {
params.putParam("max_docs", Integer.toString(updateByQueryRequest.getMaxDocs()));
}
request.setEntity(createEntity(updateByQueryRequest, REQUEST_BODY_CONTENT_TYPE));
return request;
}
@@ -684,6 +709,22 @@ public class RequestConverters {
return request;
}
public static Request getIndex(org.elasticsearch.client.indices.GetIndexRequest getIndexRequest) {
String[] indices = getIndexRequest.indices() == null ? Strings.EMPTY_ARRAY : getIndexRequest.indices();
String endpoint = endpoint(indices);
Request request = new Request(HttpMethod.GET.name(), endpoint);
Params params = new Params(request);
params.withIndicesOptions(getIndexRequest.indicesOptions());
params.withLocal(getIndexRequest.local());
params.withIncludeDefaults(getIndexRequest.includeDefaults());
params.withHuman(getIndexRequest.humanReadable());
params.withMasterTimeout(getIndexRequest.masterNodeTimeout());
return request;
}
public static Request indexDelete(DeleteIndexRequest deleteIndexRequest) {
String endpoint = RequestConverters.endpoint(deleteIndexRequest.indices());
Request request = new Request(HttpMethod.DELETE.name(), endpoint);
@@ -711,6 +752,22 @@ public class RequestConverters {
return request;
}
public static Request indexExists(org.elasticsearch.client.indices.GetIndexRequest getIndexRequest) {
// this can be called with no indices as argument by transport client, not via REST though
if (getIndexRequest.indices() == null || getIndexRequest.indices().length == 0) {
throw new IllegalArgumentException("indices are mandatory");
}
String endpoint = endpoint(getIndexRequest.indices(), "");
Request request = new Request(HttpMethod.HEAD.name(), endpoint);
Params params = new Params(request);
params.withLocal(getIndexRequest.local());
params.withHuman(getIndexRequest.humanReadable());
params.withIndicesOptions(getIndexRequest.indicesOptions());
params.withIncludeDefaults(getIndexRequest.includeDefaults());
return request;
}
public static Request indexOpen(OpenIndexRequest openIndexRequest) {
String endpoint = RequestConverters.endpoint(openIndexRequest.indices(), "_open");
Request request = new Request(HttpMethod.POST.name(), endpoint);
@@ -747,6 +804,19 @@ public class RequestConverters {
return request;
}
public static Request indexCreate(org.elasticsearch.client.indices.CreateIndexRequest createIndexRequest) {
String endpoint = RequestConverters.endpoint(new String[] { createIndexRequest.index() });
Request request = new Request(HttpMethod.PUT.name(), endpoint);
Params parameters = new Params(request);
parameters.withTimeout(createIndexRequest.timeout());
parameters.withMasterTimeout(createIndexRequest.masterNodeTimeout());
parameters.withWaitForActiveShards(createIndexRequest.waitForActiveShards(), ActiveShardCount.DEFAULT);
request.setEntity(createEntity(createIndexRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
return request;
}
public static Request indexRefresh(RefreshRequest refreshRequest) {
String[] indices = refreshRequest.indices() == null ? Strings.EMPTY_ARRAY : refreshRequest.indices();
@@ -759,6 +829,7 @@ public class RequestConverters {
return request;
}
@Deprecated
public static Request putMapping(PutMappingRequest putMappingRequest) {
// The concreteIndex is an internal concept, not applicable to requests made over the REST API.
if (putMappingRequest.getConcreteIndex() != null) {
@@ -776,6 +847,18 @@ public class RequestConverters {
return request;
}
public static Request putMapping(org.elasticsearch.client.indices.PutMappingRequest putMappingRequest) {
Request request = new Request(HttpMethod.PUT.name(),
RequestConverters.endpoint(putMappingRequest.indices(), "_mapping"));
new RequestConverters.Params(request) //
.withTimeout(putMappingRequest.timeout()) //
.withMasterTimeout(putMappingRequest.masterNodeTimeout()) //
.withIncludeTypeName(false);
request.setEntity(RequestConverters.createEntity(putMappingRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
return request;
}
public static Request flushIndex(FlushRequest flushRequest) {
String[] indices = flushRequest.indices() == null ? Strings.EMPTY_ARRAY : flushRequest.indices();
Request request = new Request(HttpMethod.POST.name(), RequestConverters.endpoint(indices, "_flush"));
@@ -801,6 +884,19 @@ public class RequestConverters {
return request;
}
public static Request getMapping(org.elasticsearch.client.indices.GetMappingsRequest getMappingsRequest) {
String[] indices = getMappingsRequest.indices() == null ? Strings.EMPTY_ARRAY : getMappingsRequest.indices();
Request request = new Request(HttpMethod.GET.name(), RequestConverters.endpoint(indices, "_mapping"));
RequestConverters.Params parameters = new RequestConverters.Params(request);
parameters.withMasterTimeout(getMappingsRequest.masterNodeTimeout());
parameters.withIndicesOptions(getMappingsRequest.indicesOptions());
parameters.withLocal(getMappingsRequest.local());
parameters.withIncludeTypeName(false);
return request;
}
public static Request getSettings(GetSettingsRequest getSettingsRequest) {
String[] indices = getSettingsRequest.indices() == null ? Strings.EMPTY_ARRAY : getSettingsRequest.indices();
String[] names = getSettingsRequest.names() == null ? Strings.EMPTY_ARRAY : getSettingsRequest.names();
@@ -891,6 +987,43 @@ public class RequestConverters {
return request;
}
public static Request getFieldMapping(GetFieldMappingsRequest getFieldMappingsRequest) {
String[] indices = getFieldMappingsRequest.indices() == null ? Strings.EMPTY_ARRAY
: getFieldMappingsRequest.indices();
String[] fields = getFieldMappingsRequest.fields() == null ? Strings.EMPTY_ARRAY : getFieldMappingsRequest.fields();
final String endpoint = new EndpointBuilder().addCommaSeparatedPathParts(indices).addPathPartAsIs("_mapping")
.addPathPartAsIs("field").addCommaSeparatedPathParts(fields).build();
Request request = new Request(HttpMethod.GET.name(), endpoint);
RequestConverters.Params parameters = new Params(request);
parameters.withIndicesOptions(getFieldMappingsRequest.indicesOptions());
parameters.withIncludeDefaults(getFieldMappingsRequest.includeDefaults());
parameters.withIncludeTypeName(false);
return request;
}
public static Request clusterHealth(ClusterHealthRequest healthRequest) {
String[] indices = healthRequest.indices() == null ? Strings.EMPTY_ARRAY : healthRequest.indices();
String endpoint = new EndpointBuilder().addPathPartAsIs(new String[] { "_cluster/health" })
.addCommaSeparatedPathParts(indices).build();
Request request = new Request("GET", endpoint);
RequestConverters.Params parameters = new Params(request);
parameters.withWaitForStatus(healthRequest.waitForStatus());
parameters.withWaitForNoRelocatingShards(healthRequest.waitForNoRelocatingShards());
parameters.withWaitForNoInitializingShards(healthRequest.waitForNoInitializingShards());
parameters.withWaitForActiveShards(healthRequest.waitForActiveShards(), ActiveShardCount.NONE);
parameters.withWaitForNodes(healthRequest.waitForNodes());
parameters.withWaitForEvents(healthRequest.waitForEvents());
parameters.withTimeout(healthRequest.timeout());
parameters.withMasterTimeout(healthRequest.masterNodeTimeout());
parameters.withLocal(healthRequest.local()).withLevel(healthRequest.level());
return request;
}
static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) {
try {
@@ -1319,7 +1452,8 @@ public class RequestConverters {
// encode each part (e.g. index, type and id) separately before merging them into the path
// we prepend "/" to the path part to make this path absolute, otherwise there can be issues with
// paths that start with `-` or contain `:`
URI uri = new URI(null, null, null, -1, '/' + pathPart, null, null);
// the authority must be an empty string and not null, else paths that being with slashes could have them
URI uri = new URI((String) null, "", "/" + pathPart, (String) null, (String) null);
// manually encode any slash that each part may contain
return uri.getRawPath().substring(1).replaceAll("/", "%2F");
} catch (URISyntaxException e) {
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,11 +31,10 @@ public abstract class AbstractElasticsearchConfiguration extends ElasticsearchCo
/**
* Return the {@link RestHighLevelClient} instance used to connect to the cluster. <br />
* Annotate with {@link Bean} in case you want to expose a {@link RestHighLevelClient} instance to the
* {@link org.springframework.context.ApplicationContext}.
*
* @return never {@literal null}.
*/
@Bean
public abstract RestHighLevelClient elasticsearchClient();
/**
@@ -44,7 +43,12 @@ public abstract class AbstractElasticsearchConfiguration extends ElasticsearchCo
* @return never {@literal null}.
*/
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter) {
return new ElasticsearchRestTemplate(elasticsearchClient(), elasticsearchConverter);
public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter,
RestHighLevelClient elasticsearchClient) {
ElasticsearchRestTemplate template = new ElasticsearchRestTemplate(elasticsearchClient, elasticsearchConverter);
template.setRefreshPolicy(refreshPolicy());
return template;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,12 +16,11 @@
package org.springframework.data.elasticsearch.config;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.RefreshPolicy;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.lang.Nullable;
@@ -31,16 +30,14 @@ import org.springframework.lang.Nullable;
* @since 3.2
* @see ElasticsearchConfigurationSupport
*/
@Configuration
public abstract class AbstractReactiveElasticsearchConfiguration extends ElasticsearchConfigurationSupport {
/**
* Return the {@link ReactiveElasticsearchClient} instance used to connect to the cluster. <br />
* Annotate with {@link Bean} in case you want to expose a {@link ReactiveElasticsearchClient} instance to the
* {@link org.springframework.context.ApplicationContext}.
*
* @return never {@literal null}.
*/
@Bean
public abstract ReactiveElasticsearchClient reactiveElasticsearchClient();
/**
@@ -49,9 +46,10 @@ public abstract class AbstractReactiveElasticsearchConfiguration extends Elastic
* @return never {@literal null}.
*/
@Bean
public ReactiveElasticsearchOperations reactiveElasticsearchTemplate(ElasticsearchConverter elasticsearchConverter) {
public ReactiveElasticsearchOperations reactiveElasticsearchTemplate(ElasticsearchConverter elasticsearchConverter,
ReactiveElasticsearchClient reactiveElasticsearchClient) {
ReactiveElasticsearchTemplate template = new ReactiveElasticsearchTemplate(reactiveElasticsearchClient(),
ReactiveElasticsearchTemplate template = new ReactiveElasticsearchTemplate(reactiveElasticsearchClient,
elasticsearchConverter);
template.setIndicesOptions(indicesOptions());
template.setRefreshPolicy(refreshPolicy());
@@ -60,13 +58,13 @@ public abstract class AbstractReactiveElasticsearchConfiguration extends Elastic
}
/**
* Set up the write {@link RefreshPolicy}. Default is set to {@link RefreshPolicy#IMMEDIATE}.
* Set up the write {@link RefreshPolicy}. Default is set to null to use the cluster defaults..
*
* @return {@literal null} to use the server defaults.
*/
@Nullable
protected RefreshPolicy refreshPolicy() {
return RefreshPolicy.IMMEDIATE;
return null;
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,10 +28,14 @@ import org.springframework.core.convert.converter.Converter;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.RefreshPolicy;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -40,15 +44,16 @@ import org.springframework.util.StringUtils;
* @author Peter-Josef Meisch
* @since 3.2
*/
@Configuration
@Configuration(proxyBeanMethods = false)
public class ElasticsearchConfigurationSupport {
@Bean
public ElasticsearchConverter elasticsearchEntityMapper(
SimpleElasticsearchMappingContext elasticsearchMappingContext) {
public ElasticsearchConverter elasticsearchEntityMapper(SimpleElasticsearchMappingContext elasticsearchMappingContext,
ElasticsearchCustomConversions elasticsearchCustomConversions) {
MappingElasticsearchConverter elasticsearchConverter = new MappingElasticsearchConverter(
elasticsearchMappingContext);
elasticsearchConverter.setConversions(elasticsearchCustomConversions());
elasticsearchConverter.setConversions(elasticsearchCustomConversions);
return elasticsearchConverter;
}
@@ -60,11 +65,13 @@ public class ElasticsearchConfigurationSupport {
* @return never {@literal null}.
*/
@Bean
public SimpleElasticsearchMappingContext elasticsearchMappingContext() {
public SimpleElasticsearchMappingContext elasticsearchMappingContext(
ElasticsearchCustomConversions elasticsearchCustomConversions) {
SimpleElasticsearchMappingContext mappingContext = new SimpleElasticsearchMappingContext();
mappingContext.setInitialEntitySet(getInitialEntitySet());
mappingContext.setSimpleTypeHolder(elasticsearchCustomConversions().getSimpleTypeHolder());
mappingContext.setSimpleTypeHolder(elasticsearchCustomConversions.getSimpleTypeHolder());
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
return mappingContext;
}
@@ -113,8 +120,7 @@ public class ElasticsearchConfigurationSupport {
}
/**
* Scans the given base package for entities, i.e. Elasticsearch specific types annotated with {@link Document} and
* {@link Persistent}.
* Scans the given base package for entities, i.e. Elasticsearch specific types annotated with {@link Document}.
*
* @param basePackage must not be {@literal null}.
* @return never {@literal null}.
@@ -130,7 +136,6 @@ public class ElasticsearchConfigurationSupport {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
@@ -146,4 +151,24 @@ public class ElasticsearchConfigurationSupport {
return initialEntitySet;
}
/**
* Set up the write {@link RefreshPolicy}. Default is set to null to use the cluster defaults..
*
* @return {@literal null} to use the server defaults.
*/
@Nullable
protected RefreshPolicy refreshPolicy() {
return null;
}
/**
* Configures a {@link FieldNamingStrategy} on the {@link SimpleElasticsearchMappingContext} instance created.
*
* @return the {@link FieldNamingStrategy} to use
* @since 4.2
*/
protected FieldNamingStrategy fieldNamingStrategy() {
return PropertyNameFieldNamingStrategy.INSTANCE;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 the original author or authors.
* Copyright 2015-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@ import org.springframework.data.mapping.context.PersistentEntities;
* @author Peter-Josef Meisch
* @since 4.1
*/
class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> {
public class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> {
private final MappingElasticsearchConverter converter;
@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 the original author or authors.
* Copyright 2018-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Some files were not shown because too many files have changed in this diff Show More