├── .github ├── dependabot.yml └── workflows │ ├── maven.yml │ └── pr.yml ├── .gitignore ├── .mergify.yml ├── .mvn ├── jvm.config └── maven.config ├── LICENSE ├── NOTICE ├── README.md ├── pom.xml └── src ├── main ├── java │ └── fr │ │ └── pilato │ │ └── spring │ │ └── elasticsearch │ │ ├── ElasticsearchClientFactoryBean.java │ │ ├── SSLUtils.java │ │ └── Tuple.java └── resources │ └── org │ └── apache │ └── maven │ └── plugin │ └── announcement │ └── announcement.vm └── test ├── java └── fr │ └── pilato │ └── spring │ └── elasticsearch │ ├── it │ ├── BaseTest.java │ └── annotation │ │ ├── AbstractAnnotationContextModel.java │ │ └── rest │ │ ├── AbstractRestAnnotationContextModel.java │ │ ├── RestAppConfig.java │ │ ├── aliases │ │ ├── AliasesTest.java │ │ └── AppConfig.java │ │ ├── badclasspath │ │ ├── AppConfig.java │ │ └── BadClasspath7Test.java │ │ ├── configuration │ │ ├── AppConfig.java │ │ └── ConfigurationTest.java │ │ ├── customanalyzers │ │ ├── AppConfig.java │ │ └── CustomAnalyzers12Test.java │ │ ├── indextemplates │ │ ├── AppConfig.java │ │ └── IndexTemplatesTest.java │ │ ├── indicesalreadyexist │ │ ├── AppConfig.java │ │ └── IndicesAlreadyExistTest.java │ │ ├── lifecycles │ │ ├── AppConfig.java │ │ └── LifecyclesTest.java │ │ ├── manualsettings │ │ ├── AppConfig.java │ │ └── ManualSettingsTest.java │ │ ├── mapping │ │ ├── AppConfig.java │ │ └── MappingTest.java │ │ ├── mappingconvention │ │ ├── AppConfig.java │ │ └── MappingConventionTest.java │ │ ├── mappingfailed │ │ ├── AppConfig.java │ │ └── MappingFailedTest.java │ │ ├── multipleclients │ │ ├── AppConfig.java │ │ └── MultipleClientsTest.java │ │ ├── pipelines │ │ ├── AppConfig.java │ │ └── PipelinesTest.java │ │ ├── settings13 │ │ ├── AppConfig.java │ │ └── Settings13Test.java │ │ ├── settingsfailed │ │ ├── AppConfig.java │ │ └── SettingsFailedTest.java │ │ ├── settingsnomapping21 │ │ ├── AppConfig.java │ │ └── SettingsNoMapping21Test.java │ │ ├── shards │ │ └── AppConfig.java │ │ ├── updatesettingsdisabled31 │ │ ├── AppConfig.java │ │ └── UpdateSettingsDisabled31Test.java │ │ └── updatesettingsenabled31 │ │ ├── AppConfig.java │ │ └── UpdateSettings31Test.java │ └── unit │ └── ClassPathReaderTest.java └── resources ├── classpath-reader-test.txt ├── es └── twitter │ └── _settings.json ├── log4j2.xml └── models └── root ├── aliases ├── _aliases.json ├── test_1 │ └── _settings.json ├── test_2 │ └── _settings.json └── twitter │ └── _settings.json ├── custom-analyzers-12 └── client │ └── twitter │ └── _settings.json ├── index-templates └── client │ ├── _component_templates │ ├── component1.json │ └── component2.json │ └── _index_templates │ └── template_1.json ├── index-with-type └── client │ └── twitter │ └── _doc.json ├── indices-already-exist-86 └── client │ ├── badindex │ └── _settings.json │ └── twitter │ └── _settings.json ├── lifecycles ├── _index_lifecycles │ └── policy1.json └── twitter │ └── _settings.json ├── manual-settings ├── _aliases.json ├── _component_templates │ ├── component1.json │ └── component2.json ├── _index_templates │ ├── template_1.json │ └── template_2.json ├── _pipelines │ ├── pipeline1.json │ └── pipeline2.json └── foobar │ └── _settings.json ├── mapping-failed ├── client1 │ └── twitter │ │ └── _settings.json └── client2 │ └── twitter │ └── _update_settings.json ├── mapping ├── client1 │ └── twitter │ │ └── _settings.json └── client2 │ └── twitter │ └── _settings.json ├── multiple-clients ├── client1 │ └── twitter │ │ └── _settings.json └── client2 │ └── twitter │ └── _settings.json ├── no-namespace └── client │ ├── rss │ └── _settings.json │ └── twitter │ └── _settings.json ├── pipelines └── _pipelines │ └── pipeline1.json ├── plugins └── client │ └── twitter │ ├── _doc.json │ └── _settings.json ├── rest-client-namespace └── client │ └── twitter │ └── _settings.json ├── settings-13 └── client │ ├── rss │ └── _settings.json │ └── twitter │ └── _settings.json ├── settings-failed ├── client1 │ └── twitter │ │ └── _settings.json └── client2 │ └── twitter │ └── _update_settings.json ├── settings-no-mapping-21 └── client │ └── twitter │ └── _settings.json ├── shards └── client │ └── twitter │ └── _settings.json ├── update-settings-31 ├── client1 │ └── twitter │ │ └── _settings.json └── client2 │ └── twitter │ └── _update_settings.json └── update-settings-disabled-31 ├── client1 └── twitter │ └── _settings.json └── client2 └── twitter └── _update_settings.json /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 99 9 | reviewers: 10 | - dadoonet 11 | assignees: 12 | - dadoonet 13 | labels: 14 | - update 15 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Build and Deploy the master branch 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up JDK 17 and Maven Central Repository 18 | uses: actions/setup-java@v2 19 | with: 20 | java-version: '17' 21 | distribution: 'adopt' 22 | - name: Cache Maven packages 23 | uses: actions/cache@v2 24 | with: 25 | path: ~/.m2 26 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 27 | restore-keys: ${{ runner.os }}-m2 28 | - name: Build with Maven 29 | run: mvn --batch-mode --update-snapshots verify 30 | 31 | deploy: 32 | needs: build 33 | runs-on: ubuntu-latest 34 | 35 | steps: 36 | - uses: actions/checkout@v2 37 | - name: Cache Maven packages 38 | uses: actions/cache@v2 39 | with: 40 | path: ~/.m2 41 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 42 | restore-keys: ${{ runner.os }}-m2 43 | - name: Set up JDK 14 and Maven Central Repository 44 | uses: actions/setup-java@v2 45 | with: 46 | java-version: '17' 47 | distribution: 'adopt' 48 | server-id: sonatype-nexus-snapshots 49 | server-username: MAVEN_USERNAME 50 | server-password: MAVEN_PASSWORD 51 | - name: Deploy with Maven 52 | run: mvn deploy -DskipTests 53 | env: 54 | MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} 55 | MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} 56 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Build Pull Requests 5 | 6 | on: [pull_request] 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Set up JDK 17 and Maven Central Repository 16 | uses: actions/setup-java@v2 17 | with: 18 | java-version: '17' 19 | distribution: 'adopt' 20 | - name: Cache Maven packages 21 | uses: actions/cache@v2 22 | with: 23 | path: ~/.m2 24 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 25 | restore-keys: ${{ runner.os }}-m2 26 | - name: Build with Maven 27 | run: mvn --batch-mode --update-snapshots verify 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /.classpath 3 | /.settings 4 | /target 5 | *.iml 6 | *.idea 7 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: automatic merge on CI success and review 3 | conditions: 4 | - check-success=build 5 | - "#approved-reviews-by>=1" 6 | actions: 7 | merge: 8 | method: merge 9 | -------------------------------------------------------------------------------- /.mvn/jvm.config: -------------------------------------------------------------------------------- 1 | -Xmx1024m -Xms1024m -Djava.awt.headless=true 2 | 3 | -------------------------------------------------------------------------------- /.mvn/maven.config: -------------------------------------------------------------------------------- 1 | -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright (c) David Pilato - 2012 2 | 3 | This product includes software developed by The Apache Software 4 | Foundation (http://www.apache.org/). 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring factories for Elasticsearch 2 | 3 | Welcome to the Spring factories for [Elasticsearch](https://www.elastic.co/elasticsearch/) project. 4 | 5 | The factory provides a [Java Rest Client for Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/) 6 | and automatically create index settings and templates based on what is found in the classpath: 7 | 8 | * `/es/_index_lifecycles/` for [index lifecycles policies](#index-lifecycles-policies) 9 | * `/es/INDEXNAME/_settings.json` for [index settings and mappings](#indices) for a given index `INDEXNAME` 10 | * `/es/INDEXNAME/_update_settings.json` to [update existing index settings and mappings](#indices) for a given index `INDEXNAME` 11 | * `/es/_component_templates/` for [component templates](#component-templates) 12 | * `/es/_index_templates/` for [index templates](#index-templates) 13 | * `/es/_pipelines/` for [ingest pipelines](#ingest-pipelines) 14 | * `/es/_aliases.json` for [aliases](#aliases) 15 | 16 | ## Documentation 17 | 18 | * For 8.x elasticsearch versions, you are reading the latest documentation. 19 | * For 7.x elasticsearch versions, look at [es-7.x branch](https://github.com/dadoonet/spring-elasticsearch/tree/es-7.x). 20 | * For 6.x elasticsearch versions, look at [es-6.x branch](https://github.com/dadoonet/spring-elasticsearch/tree/es-6.x). 21 | * For 5.x elasticsearch versions, look at [es-5.x branch](https://github.com/dadoonet/spring-elasticsearch/tree/es-5.x). 22 | * For 2.x elasticsearch versions, look at [es-2.x branch](https://github.com/dadoonet/spring-elasticsearch/tree/es-2.x). 23 | * For 1.x elasticsearch versions, look at [es-1.4 branch](https://github.com/dadoonet/spring-elasticsearch/tree/es-1.4). 24 | * For 0.x elasticsearch versions, look at [0.x branch](https://github.com/dadoonet/spring-elasticsearch/tree/0.x). 25 | 26 | | spring-elasticsearch | elasticsearch | Spring | Release date | 27 | |:--------------------:|:-------------:|:------:|:------------:| 28 | | 8.7-SNAPSHOT | 8.x | 6.0.7 | | 29 | | 7.1 | 7.0 - 7.x | 5.3.15 | 2022-01-13 | 30 | | 7.0 | 7.0 - 7.x | 5.3.8 | 2021-06-21 | 31 | | 6.7 | 6.7 - 6.x | 5.1.3 | 2019-04-13 | 32 | | 6.2 | 6.0 - 6.x | 5.1.3 | 2019-01-08 | 33 | | 6.1 | 6.0 - 6.x | 5.0.7 | 2018-07-22 | 34 | | 6.0 | 6.0 - 6.x | 5.0.3 | 2018-02-08 | 35 | | 5.0 | 5.0 - 5.x | 4.3.10 | 2018-02-04 | 36 | | 2.2.0 | 2.0 - 2.4 | 4.2.3 | 2017-03-09 | 37 | | 2.1.0 | 2.0, 2.1 | 4.2.3 | 2015-11-25 | 38 | | 2.0.0 | 2.0 | 4.1.4 | 2015-10-25 | 39 | | 1.4.2 | < 2.0 | 4.1.4 | 2015-03-03 | 40 | | 1.4.1 | 1.4 | 4.1.4 | 2015-02-28 | 41 | | 1.4.0 | 1.4 | 4.1.4 | 2015-01-03 | 42 | | 1.3.0 | 1.3 | 4.0.6 | 2014-09-01 | 43 | | 1.0.0 | 1.0 | 3.2.2 | 2014-02-14 | 44 | 45 | ## Build Status 46 | 47 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/fr.pilato.spring/spring-elasticsearch/badge.svg?style=flat-square)](https://maven-badges.herokuapp.com/maven-central/fr.pilato.spring/spring-elasticsearch/) 48 | [![Build Status](https://github.com/dadoonet/spring-elasticsearch/actions/workflows/maven.yml/badge.svg)](https://github.com/dadoonet/spring-elasticsearch/actions/workflows/maven.yml) 49 | 50 | ## Release notes 51 | 52 | ### Changes in 8.7 53 | 54 | * Update to Spring 6.0.7 55 | * Update to Java 17 (needed by Spring 6) 56 | * Update to Beyonder 8.6 57 | * Provides now the new official [Java Rest Client for Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/) 58 | * Removed deprecated templates 59 | * Removed deprecated XML support 60 | * As a side effect of a previous removal (TransportClient), async initialization of the client has been removed. 61 | * Deprecated `setProperties(Properties)` method. 62 | * Add a wait for yellow health when creating a new index 63 | 64 | ### Changes in 7.1 65 | 66 | * Update to Beyonder 7.16 which brings in support for index lifecycles. 67 | You can add your index lifecycles policies in the `_index_lifecycles` dir. 68 | 69 | ### Major (breaking) changes in 7.0 70 | 71 | * The `TransportClient` has been removed. 72 | 73 | * As in Elasticsearch 7.x, only one single type is supported, you need to provide the mapping within 74 | the index settings ( `_settings.json` file). As a consequence: 75 | * `forceMapping` setting has been replaced by `forceIndex`. 76 | * `mappings` setting has been replaced by `indices`. 77 | * `mergeMapping` setting has been removed. 78 | 79 | * `forceTemplate` setting has been removed. A template should be always updated. 80 | 81 | * `_template` dir has been deprecated by `_templates` dir. 82 | 83 | ## Getting Started 84 | 85 | ### Maven dependency 86 | 87 | Import spring-elasticsearch in you project `pom.xml` file: 88 | 89 | ```xml 90 | 91 | fr.pilato.spring 92 | spring-elasticsearch 93 | 8.7 94 | 95 | ``` 96 | 97 | If you want to set a specific version of the Elasticsearch Java client, add it to your `pom.xml` file: 98 | 99 | ```xml 100 | 101 | 102 | co.elastic.clients 103 | elasticsearch-java 104 | ${elasticsearch.version} 105 | 106 | 107 | org.elasticsearch.client 108 | elasticsearch-rest-client 109 | ${elasticsearch.version} 110 | 111 | 112 | ``` 113 | 114 | If you want to try out the most recent SNAPSHOT version [deployed on Sonatype](https://oss.sonatype.org/content/repositories/snapshots/fr/pilato/spring/spring-elasticsearch/): 115 | 116 | ```xml 117 | 118 | fr.pilato.spring 119 | spring-elasticsearch 120 | 8.8-SNAPSHOT 121 | 122 | ``` 123 | 124 | Don't forget to add if needed the following repository in your `pom.xml`: 125 | 126 | ```xml 127 | 128 | 129 | oss-snapshots 130 | Sonatype OSS Snapshots 131 | https://s01.oss.sonatype.org/content/repositories/snapshots/ 132 | false 133 | true 134 | 135 | 136 | ``` 137 | 138 | If you depend on an elasticsearch SNAPSHOT version, you need to add the following repository to your `pom.xml`: 139 | 140 | ```xml 141 | 142 | 143 | elastic-snapshots 144 | Elastic Snapshots 145 | http://snapshots.elastic.co/maven/ 146 | false 147 | true 148 | 149 | 150 | ``` 151 | 152 | ### Logger 153 | 154 | We are using [slf4j](http://www.slf4j.org/) for logging but you have to provide the logging implementation 155 | you want to use and bind it. 156 | 157 | For example for this project we are using for tests [log4j2](http://logging.apache.org/log4j/). 158 | If you want to do so, add to your `pom.xml`: 159 | 160 | ```xml 161 | 162 | 163 | org.apache.logging.log4j 164 | log4j-api 165 | 2.20.0 166 | 167 | 168 | org.apache.logging.log4j 169 | log4j-slf4j2-impl 170 | 2.20.0 171 | 172 | 173 | org.apache.logging.log4j 174 | log4j-core 175 | 2.20.0 176 | 177 | 178 | ``` 179 | 180 | ## Using Java Annotations 181 | 182 | Let's say you want to use Spring Java Annotations, here is a typical application you can build. 183 | 184 | `pom.xml`: 185 | 186 | ```xml 187 | 188 | 191 | 4.0.0 192 | 193 | fr.pilato.tests 194 | spring-elasticsearch-test 195 | 1.0-SNAPSHOT 196 | 197 | 198 | 199 | fr.pilato.spring 200 | spring-elasticsearch 201 | 8.7 202 | 203 | 204 | 205 | ``` 206 | 207 | `App.java`: 208 | 209 | ```java 210 | package fr.pilato.tests; 211 | 212 | import org.springframework.beans.factory.annotation.Autowired; 213 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 214 | import org.springframework.context.annotation.Bean; 215 | import org.springframework.context.annotation.Configuration; 216 | import org.springframework.stereotype.Component; 217 | 218 | import java.io.IOException; 219 | 220 | @Component 221 | public class RestApp { 222 | 223 | @Configuration 224 | public class AppConfig { 225 | @Bean 226 | public ElasticsearchClient esClient() { 227 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 228 | factory.setEsNodes(new String[]{"https://127.0.0.1:9200"}); 229 | factory.setUsername("elastic"); 230 | factory.setPassword("changeme"); 231 | factory.afterPropertiesSet(); 232 | return factory.getObject(); 233 | } 234 | } 235 | 236 | @Autowired 237 | private ElasticsearchClient client; 238 | 239 | public static void main(String[] args) { 240 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 241 | context.scan("fr.pilato.tests"); 242 | context.refresh(); 243 | 244 | RestApp p = context.getBean(RestApp.class); 245 | p.run(); 246 | 247 | context.close(); 248 | } 249 | 250 | private void run() { 251 | // Run an advanced request 252 | client.info(); 253 | 254 | // You still have access to the Low Level client 255 | client.getLowLevel().performRequest(new Request("GET", "/")); 256 | } 257 | } 258 | ``` 259 | 260 | ## Features 261 | 262 | The factory provides a [Java Rest Client for Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/) 263 | and automatically create index settings and templates based on what is found in the classpath: 264 | 265 | * `/es/INDEXNAME/_settings.json` for [index settings and mappings](#indices) for a given index `INDEXNAME` 266 | * `/es/INDEXNAME/_update_settings.json` to [update existing index settings and mappings](#indices) for a given index `INDEXNAME` 267 | * `/es/_component_templates/` for [component templates](#component-templates) 268 | * `/es/_index_templates/` for [index templates](#index-templates) 269 | * `/es/_pipelines/` for [ingest pipelines](#ingest-pipelines) 270 | * `/es/_aliases.json` for [aliases](#aliases) 271 | * `/es/_index_lifecycles/` for [index lifecycles policies](#index-lifecycles-policies) 272 | 273 | ### Autoscan 274 | 275 | By default, the factory will scan the classpath inside the default `/es` directory. 276 | You can disable the autoscan and then provide manually every name for indices, templates... 277 | 278 | ```java 279 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 280 | factory.setAutoscan(false); 281 | factory.setIndices(new String[]{"twitter"}); 282 | ``` 283 | 284 | ### Default directory 285 | 286 | You can change the default directory from `/es` to something else. The factory will look into this 287 | directory to find the indices and the settings for the indices, templates... 288 | 289 | ```java 290 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 291 | factory.setClasspathRoot("/foo"); 292 | ``` 293 | 294 | ### Indices 295 | 296 | If you add in your classpath a file named `/es/twitter/_settings.json`, it will be automatically applied to define 297 | settings for your `twitter` index. 298 | 299 | For example, create the following file `src/main/resources/es/twitter/_settings.json` in your project: 300 | 301 | ```json 302 | { 303 | "settings" : { 304 | "number_of_shards" : 3, 305 | "number_of_replicas" : 2 306 | }, 307 | "mappings": { 308 | "properties" : { 309 | "message" : {"type" : "text", "store" : "yes"} 310 | } 311 | } 312 | } 313 | ``` 314 | 315 | If you need to update settings for an existing index, let say `twitter`, add a file named `/es/twitter/_update_settings.json` 316 | in your classpath. The factory will detect it and will try to update the settings: 317 | 318 | ```json 319 | { 320 | "index" : { 321 | "number_of_replicas" : 1 322 | } 323 | } 324 | ``` 325 | 326 | If you want to remove the existing indices every time the factory starts, you can use the `forceIndex` option: 327 | 328 | ```java 329 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 330 | // Be careful: IT WILL REMOVE ALL EXISTING DATA FOR THE MANAGED INDICES. 331 | factory.setForceIndex(true); 332 | ``` 333 | 334 | Be careful: **IT WILL REMOVE ALL EXISTING DATA** FOR THE MANAGED INDICES. 335 | 336 | 337 | ### Component templates 338 | 339 | This feature will call the [Component Templates APIs](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-component-template.html). 340 | It's very common to use it with [index templates](#index-templates). 341 | 342 | Let say you want to create a component template named `component1`. Just create a file named 343 | `/es/_component_templates/component1.json`: 344 | 345 | ```json 346 | { 347 | "template": { 348 | "mappings": { 349 | "properties": { 350 | "@timestamp": { 351 | "type": "date" 352 | } 353 | } 354 | } 355 | } 356 | } 357 | ``` 358 | 359 | Let say you want to create a component template named `component2`. Just create a file named 360 | `/es/_component_templates/component2.json`: 361 | 362 | ```json 363 | { 364 | "template": { 365 | "mappings": { 366 | "runtime": { 367 | "day_of_week": { 368 | "type": "keyword", 369 | "script": { 370 | "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))" 371 | } 372 | } 373 | } 374 | } 375 | } 376 | } 377 | ``` 378 | 379 | You can use then the 2 component templates in an index template as shown below. 380 | 381 | ### Index templates 382 | 383 | This feature will call the [Index Templates APIs](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-templates.html). 384 | It can be used with [component templates](#component-templates). 385 | 386 | Let say you want to create an index template named `template_1`. Just create a file named 387 | `/es/_index_templates/template_1.json`: 388 | 389 | ```json 390 | { 391 | "index_patterns": ["te*", "bar*"], 392 | "template": { 393 | "settings": { 394 | "number_of_shards": 1 395 | }, 396 | "mappings": { 397 | "_source": { 398 | "enabled": true 399 | }, 400 | "properties": { 401 | "host_name": { 402 | "type": "keyword" 403 | }, 404 | "created_at": { 405 | "type": "date", 406 | "format": "EEE MMM dd HH:mm:ss Z yyyy" 407 | } 408 | } 409 | }, 410 | "aliases": { 411 | "mydata": { } 412 | } 413 | }, 414 | "priority": 500, 415 | "composed_of": ["component1", "component2"], 416 | "version": 3, 417 | "_meta": { 418 | "description": "my custom" 419 | } 420 | } 421 | ``` 422 | 423 | Note that this index template is using the 2 component templates that have been defined in the previous section. 424 | 425 | ### Aliases 426 | 427 | An alias is helpful to define or remove an alias to a given index. You could also use an [index templates](#index-templates) 428 | to do that automatically when at index creation time, but you can also define a file `/es/_aliases.json`: 429 | 430 | ```json 431 | { 432 | "actions" : [ 433 | { "remove": { "index": "test_1", "alias": "test" } }, 434 | { "add": { "index": "test_2", "alias": "test" } } 435 | ] 436 | } 437 | ``` 438 | 439 | When the factory starts, it will automatically send the content to the [Aliases API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html) 440 | and move the alias `test` from index `test_1` to index `test_2`. 441 | 442 | ### Ingest Pipelines 443 | 444 | This feature will call the [Ingest Pipelines APIs](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest.html) 445 | 446 | Let say you want to create an ingest pipeline named `pipeline1`. Just create a file named 447 | `/es/_pipeline/pipeline1.json`: 448 | 449 | ```json 450 | { 451 | "description": "My optional pipeline description", 452 | "processors": [ 453 | { 454 | "set": { 455 | "description": "My optional processor description", 456 | "field": "my-long-field", 457 | "value": 10 458 | } 459 | }, 460 | { 461 | "set": { 462 | "description": "Set 'my-boolean-field' to true", 463 | "field": "my-boolean-field", 464 | "value": true 465 | } 466 | }, 467 | { 468 | "lowercase": { 469 | "field": "my-keyword-field" 470 | } 471 | } 472 | ] 473 | } 474 | ``` 475 | 476 | ### Index Lifecycles Policies 477 | 478 | This feature will call the [Index Lifecycle APIs](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-lifecycle-management.html). 479 | 480 | Let say you want to create a policy named `policy1`. Just create a file named 481 | `/es/_index_lifecycles/policy1.json`: 482 | 483 | ```json 484 | { 485 | "policy": { 486 | "phases": { 487 | "warm": { 488 | "min_age": "10d", 489 | "actions": { 490 | "forcemerge": { 491 | "max_num_segments": 1 492 | } 493 | } 494 | }, 495 | "delete": { 496 | "min_age": "30d", 497 | "actions": { 498 | "delete": {} 499 | } 500 | } 501 | } 502 | } 503 | } 504 | ``` 505 | 506 | It will be automatically loaded into elasticsearch when you start the factory. 507 | If you want to apply this policy to your index, you can define the following settings for the index in 508 | `/es/twitter/_settings.json`: 509 | 510 | ```json 511 | { 512 | "settings" : { 513 | "index.lifecycle.name": "policy1" 514 | } 515 | } 516 | ``` 517 | 518 | ### SSL certificates 519 | 520 | If you need to specify your own SSL certificates (self-signed certificates), you can use the `setSSLContext(SSLContext)` 521 | method to do this. 522 | You can refer to the Elasticsearch [Low Level client documentation](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/_encrypted_communication.html) 523 | to see some examples. Once you have created a SSLContext, you can use it in the factory: 524 | 525 | ```java 526 | Path trustStorePath = Paths.get("/path/to/truststore.p12"); 527 | KeyStore truststore = KeyStore.getInstance("pkcs12"); 528 | try (InputStream is = Files.newInputStream(trustStorePath)) { 529 | truststore.load(is, keyStorePass.toCharArray()); 530 | } 531 | SSLContextBuilder sslBuilder = SSLContexts.custom().loadTrustMaterial(truststore, null); 532 | final SSLContext sslContext = sslBuilder.build(); 533 | 534 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 535 | factory.setSslContext(sslContext); 536 | ``` 537 | 538 | # Thanks 539 | 540 | Special thanks to 541 | 542 | - [Nicolas Huray](https://github.com/nhuray) for his contribution about 543 | [templates](https://github.com/dadoonet/spring-elasticsearch/pull/4) 544 | - [Nicolas Labrot](https://github.com/nithril) for his contribution about 545 | [async](https://github.com/dadoonet/spring-elasticsearch/pull/30) 546 | 547 | # Running tests 548 | 549 | If you want to run tests (integration tests) from your IDE, you need to start first an elasticsearch instance. 550 | Tests are expecting a node running at `https://localhost:9200` with the user `elastic` and `changeme` as the password. 551 | 552 | To run the tests using Maven (on the CLI), just run: 553 | 554 | ```sh 555 | mvn clean install 556 | ``` 557 | 558 | You can change the target to run the tests. For example, if you want to run the tests against an elastic cloud instance: 559 | 560 | ```shell 561 | mvn clean install -Dtests.cluster=https://ID.es.ZONE.PROVIDER.cloud.es.io -Dtests.cluster.user=myuser -Dtests.cluster.pass=YOURPASSWORD 562 | ``` 563 | 564 | # Release guide 565 | 566 | To release the project you need to run the release plugin with the `release` profile as you need to sign the artifacts: 567 | 568 | ```sh 569 | mvn release:prepare 570 | git push --tags 571 | git push 572 | mvn release:perform -Prelease 573 | ``` 574 | 575 | If you need to skip the tests, run: 576 | 577 | ```sh 578 | mvn release:perform -Prelease -Darguments="-DskipTests" 579 | ``` 580 | 581 | If everything is ok in https://s01.oss.sonatype.org/#stagingRepositories, you can perform the release with: 582 | 583 | ```sh 584 | mvn nexus-staging:release 585 | mvn nexus-staging:drop 586 | ``` 587 | 588 | To announce the release, run: 589 | 590 | ```sh 591 | cd target/checkout 592 | # Run the following command if you want to check the announcement email 593 | mvn changes:announcement-generate 594 | cat target/announcement/announcement.vm 595 | 596 | # Announce the release (change your smtp username and password) 597 | mvn changes:announcement-mail -Dchanges.username='YourSmtpUserName' -Dchanges.password='YourSmtpUserPassword' 598 | ``` 599 | 600 | # License 601 | 602 | This software is licensed under the Apache 2 license, quoted below. 603 | 604 | Copyright 2011-2023 David Pilato 605 | 606 | Licensed under the Apache License, Version 2.0 (the "License"); you may not 607 | use this file except in compliance with the License. You may obtain a copy of 608 | the License at 609 | 610 | http://www.apache.org/licenses/LICENSE-2.0 611 | 612 | Unless required by applicable law or agreed to in writing, software 613 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 614 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 615 | License for the specific language governing permissions and limitations under 616 | the License. 617 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | fr.pilato.spring 6 | spring-elasticsearch 7 | jar 8 | spring-elasticsearch 9 | 8.7-SNAPSHOT 10 | https://github.com/dadoonet/spring-elasticsearch 11 | Spring factories for Elasticsearch 12 | 13 | 14 | 15 | The Apache Software License, Version 2.0 16 | http://www.apache.org/licenses/LICENSE-2.0.txt 17 | repo 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 17 25 | 26 | 6.0.9 27 | 8.8.1 28 | 8.6-SNAPSHOT 29 | 2.0.7 30 | 2.20.0 31 | 2.11.0 32 | 2.15.2 33 | 5.9.3 34 | 35 | false 36 | ${skipTests} 37 | ${skipTests} 38 | elastic 39 | changeme 40 | ${tests.cluster.username}:${tests.cluster.password} 41 | 42 | 43 | docker.elastic.co/elasticsearch/elasticsearch 44 | ${elasticsearch.version} 45 | 9200 46 | 9300 47 | 48 | 49 | smtp.ionos.fr 50 | 465 51 | 52 | 53 | 54 | 55 | sonatype-nexus-snapshots 56 | https://s01.oss.sonatype.org/content/repositories/snapshots 57 | 58 | 59 | sonatype-nexus-staging 60 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 61 | 62 | 63 | 64 | 65 | 66 | dadoonet 67 | David Pilato 68 | david@pilato.fr 69 | http://david.pilato.fr/ 70 | +1 71 | 72 | 73 | nhuray 74 | Nicolas Huray 75 | https://github.com/nhuray/ 76 | +1 77 | 78 | 79 | nlabrot 80 | Nicolas Labrot 81 | https://github.com/nithril‎/ 82 | Europe/Paris 83 | 84 | 85 | 86 | 87 | scm:git:git@github.com:dadoonet/spring-elasticsearch.git 88 | scm:git:git@github.com:dadoonet/spring-elasticsearch.git 89 | scm:git:git@github.com:dadoonet/spring-elasticsearch.git 90 | HEAD 91 | 92 | 93 | 94 | GitHub 95 | https://github.com/dadoonet/spring-elasticsearch/issues/ 96 | 97 | 98 | 99 | 100 | elastic-download-service 101 | Elastic Download Service 102 | https://artifacts.elastic.co/maven/ 103 | true 104 | false 105 | 106 | 107 | 108 | elastic-snapshots 109 | Elastic Snapshots 110 | https://snapshots.elastic.co/maven/ 111 | false 112 | true 113 | 114 | 115 | 116 | oss-snapshots 117 | Sonatype OSS Snapshots 118 | https://s01.oss.sonatype.org/content/repositories/snapshots/ 119 | false 120 | true 121 | 122 | 123 | 124 | 125 | 126 | org.hamcrest 127 | hamcrest-all 128 | 1.3 129 | test 130 | 131 | 132 | 133 | org.springframework 134 | spring-core 135 | ${spring.version} 136 | 137 | 138 | org.springframework 139 | spring-beans 140 | ${spring.version} 141 | 142 | 143 | org.springframework 144 | spring-context 145 | ${spring.version} 146 | 147 | 148 | 149 | 150 | org.slf4j 151 | slf4j-api 152 | ${slf4j.version} 153 | 154 | 155 | 156 | 157 | org.apache.logging.log4j 158 | log4j-api 159 | ${log4j.version} 160 | true 161 | 162 | 163 | org.apache.logging.log4j 164 | log4j-slf4j2-impl 165 | ${log4j.version} 166 | true 167 | 168 | 169 | org.apache.logging.log4j 170 | log4j-core 171 | ${log4j.version} 172 | true 173 | 174 | 175 | 176 | 177 | co.elastic.clients 178 | elasticsearch-java 179 | ${elasticsearch.version} 180 | 181 | 182 | org.elasticsearch.client 183 | elasticsearch-rest-client 184 | ${elasticsearch.version} 185 | 186 | 187 | fr.pilato.elasticsearch 188 | elasticsearch-beyonder 189 | ${beyonder.version} 190 | 191 | 192 | commons-io 193 | commons-io 194 | ${commons.io.version} 195 | 196 | 197 | 198 | org.springframework 199 | spring-test 200 | ${spring.version} 201 | test 202 | 203 | 204 | org.junit.jupiter 205 | junit-jupiter-api 206 | ${junit.version} 207 | test 208 | 209 | 210 | org.junit.jupiter 211 | junit-jupiter-engine 212 | ${junit.version} 213 | test 214 | 215 | 216 | cglib 217 | cglib 218 | 3.3.0 219 | test 220 | 221 | 222 | com.fasterxml.jackson.core 223 | jackson-core 224 | ${jackson.version} 225 | test 226 | 227 | 228 | com.fasterxml.jackson.core 229 | jackson-databind 230 | ${jackson.version} 231 | test 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | org.apache.maven.plugins 240 | maven-help-plugin 241 | 3.4.0 242 | 243 | 244 | org.apache.maven.plugins 245 | maven-resources-plugin 246 | 3.3.1 247 | 248 | 249 | org.apache.maven.plugins 250 | maven-compiler-plugin 251 | 3.11.0 252 | 253 | ${java.compiler.version} 254 | ${java.compiler.version} 255 | UTF-8 256 | true 257 | true 258 | true 259 | -Xlint:all,-serial,-path,-rawtypes,-unchecked 260 | 261 | 262 | 263 | org.apache.maven.plugins 264 | maven-dependency-plugin 265 | 3.5.0 266 | 267 | 268 | org.apache.maven.plugins 269 | maven-enforcer-plugin 270 | 3.3.0 271 | 272 | 273 | 274 | ${java.compiler.version} 275 | 276 | 277 | 278 | 279 | 280 | org.sonatype.plugins 281 | nexus-staging-maven-plugin 282 | 1.6.13 283 | true 284 | 285 | sonatype-nexus-staging 286 | https://s01.oss.sonatype.org/ 287 | false 288 | 289 | 290 | 291 | org.apache.maven.plugins 292 | maven-jar-plugin 293 | 3.3.0 294 | 295 | 296 | org.apache.maven.plugins 297 | maven-scm-plugin 298 | 2.0.0 299 | 300 | 301 | org.apache.maven.plugins 302 | maven-changes-plugin 303 | 2.12.1 304 | 305 | true 306 | dadoonet 307 | 308 | discuss+community-plugins@elastic.co 309 | 310 | 311 | GitHub 312 | 313 | 314 | new,doc 315 | bug 316 | update 317 | remove 318 | 319 | true 320 | 321 | https://repo1.maven.org/maven2/fr/pilato/spring/spring-elasticsearch/${project.version}/ 322 | 323 | 324 | 325 | 326 | org.apache.maven.plugins 327 | maven-release-plugin 328 | 3.0.0 329 | 330 | false 331 | 332 | 333 | 334 | 335 | io.fabric8 336 | docker-maven-plugin 337 | 0.43.2 338 | 339 | 340 | 341 | spring-elasticsearch 342 | dadoonet/spring-elasticsearch:${project.version} 343 | 344 | ${integ.elasticsearch.image}:${integ.elasticsearch.version} 345 | 346 | single-node 347 | ${tests.cluster.password} 348 | 349 | 350 | 351 | 352 | tests.cluster.rest.port:9200 353 | 354 | 355 | 356 | https://localhost:${tests.cluster.rest.port}/ 357 | 200..499 358 | true 359 | 360 | 361 | 362 | 363 | 364 | 365 | ${skip.integration.tests} 366 | 367 | 368 | 369 | start-elasticsearch 370 | pre-integration-test 371 | 372 | build 373 | stop 374 | start 375 | 376 | 377 | 378 | stop-elasticsearch 379 | post-integration-test 380 | 381 | stop 382 | 383 | 384 | 385 | 386 | 387 | org.apache.maven.plugins 388 | maven-surefire-plugin 389 | 3.1.0 390 | 391 | 392 | ${skip.unit.tests} 393 | 394 | 395 | **/it/**/*Test.java 396 | 397 | 398 | 399 | 400 | org.apache.maven.plugins 401 | maven-failsafe-plugin 402 | 3.1.0 403 | 404 | 407 | 408 | org.apache.maven.surefire 409 | surefire-api 410 | 3.1.0 411 | 412 | 413 | 414 | 418 | 419 | integration-tests 420 | 421 | integration-test 422 | verify 423 | 424 | 425 | 429 | ${skip.integration.tests} 430 | 431 | 432 | **/it/**/*Test.java 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | src/test/resources 442 | true 443 | 444 | 445 | 446 | 447 | 448 | 449 | release 450 | 451 | 452 | 453 | org.apache.maven.plugins 454 | maven-javadoc-plugin 455 | 3.5.0 456 | 457 | 458 | attach-javadocs 459 | 460 | jar 461 | 462 | 463 | 464 | 465 | 466 | org.apache.maven.plugins 467 | maven-source-plugin 468 | 3.2.1 469 | 470 | 471 | attach-sources 472 | 473 | jar-no-fork 474 | 475 | 476 | 477 | 478 | 479 | org.apache.maven.plugins 480 | maven-gpg-plugin 481 | 3.1.0 482 | 483 | 484 | sign-artifacts 485 | verify 486 | 487 | sign 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | -------------------------------------------------------------------------------- /src/main/java/fr/pilato/spring/elasticsearch/ElasticsearchClientFactoryBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import co.elastic.clients.elasticsearch._types.HealthStatus; 24 | import co.elastic.clients.json.jackson.JacksonJsonpMapper; 25 | import co.elastic.clients.transport.ElasticsearchTransport; 26 | import co.elastic.clients.transport.rest_client.RestClientTransport; 27 | import fr.pilato.elasticsearch.tools.util.ResourceList; 28 | import fr.pilato.elasticsearch.tools.util.SettingsFinder; 29 | import org.apache.http.HttpHost; 30 | import org.apache.http.auth.AuthScope; 31 | import org.apache.http.auth.UsernamePasswordCredentials; 32 | import org.apache.http.client.CredentialsProvider; 33 | import org.apache.http.impl.client.BasicCredentialsProvider; 34 | import org.elasticsearch.client.RestClient; 35 | import org.elasticsearch.client.RestClientBuilder; 36 | import org.slf4j.Logger; 37 | import org.slf4j.LoggerFactory; 38 | import org.springframework.beans.factory.DisposableBean; 39 | import org.springframework.beans.factory.FactoryBean; 40 | import org.springframework.beans.factory.InitializingBean; 41 | import org.springframework.util.Assert; 42 | 43 | import javax.net.ssl.SSLContext; 44 | import java.io.IOException; 45 | import java.net.URISyntaxException; 46 | import java.util.ArrayList; 47 | import java.util.Arrays; 48 | import java.util.Collection; 49 | import java.util.List; 50 | import java.util.Properties; 51 | 52 | import static fr.pilato.elasticsearch.tools.updaters.ElasticsearchAliasUpdater.manageAliases; 53 | import static fr.pilato.elasticsearch.tools.updaters.ElasticsearchAliasUpdater.manageAliasesWithJsonInElasticsearch; 54 | import static fr.pilato.elasticsearch.tools.updaters.ElasticsearchComponentTemplateUpdater.createComponentTemplate; 55 | import static fr.pilato.elasticsearch.tools.updaters.ElasticsearchIndexLifecycleUpdater.createIndexLifecycle; 56 | import static fr.pilato.elasticsearch.tools.updaters.ElasticsearchIndexTemplateUpdater.createIndexTemplate; 57 | import static fr.pilato.elasticsearch.tools.updaters.ElasticsearchIndexUpdater.createIndex; 58 | import static fr.pilato.elasticsearch.tools.updaters.ElasticsearchIndexUpdater.updateSettings; 59 | import static fr.pilato.elasticsearch.tools.updaters.ElasticsearchPipelineUpdater.createPipeline; 60 | import static fr.pilato.elasticsearch.tools.util.ResourceList.findIndexNames; 61 | 62 | /** 63 | * An abstract {@link FactoryBean} used to create an Elasticsearch 64 | * {@link ElasticsearchClient}. 65 | *

66 | * The lifecycle of the underlying {@link ElasticsearchClient} instance is tied to the 67 | * lifecycle of the bean via the {@link #destroy()} method which calls 68 | * {@link RestClient#close()} 69 | *

70 | *

71 | * If not using the default https://localhost:9200, you need to define the nodes you want to communicate with 72 | * and probably the credentials. 73 | *

74 | *

Example :

75 | *
 76 |  * {@code
 77 |  * @Configuration
 78 |  * public class AppConfig {
 79 |  *    @Bean
 80 |  *    public ElasticsearchClient esClient() throws Exception {
 81 |  * 		ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean();
 82 |  * 	    factory.setEsNodes(List.of(HttpHost.create("https://localhost:9200")));
 83 |  * 		factory.setPassword("changeme");
 84 |  * 		factory.afterPropertiesSet();
 85 |  * 		return factory.getObject();
 86 |  *    }
 87 |  *  }
 88 |  * }
 89 |  * 
90 | *

91 | * The factory is meant to be used with some classpath files which are automatically 92 | * loaded from {@code /es} directory to define your: 93 | *

101 | * 102 | *

You can force the manual creation of the above components but this is 103 | * not the goal of this factory. So it should be used only for some specific use cases: 104 | *

105 | *

106 | * Example : 107 | *

108 | *
109 |  * {@code
110 |  * @Configuration
111 |  * public class AppConfig {
112 |  *    @Bean
113 |  *    public ElasticsearchClient esClient() throws Exception {
114 |  *      ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean();
115 |  * 	    // Create two indices twitter and rss
116 |  * 	    factory.setIndices(new String[]{ "twitter", "rss" });
117 |  * 	    // Create an alias alltheworld on top of twitter and rss indices
118 |  * 	    factory.setAliases(new String[]{ "alltheworld:twitter", "alltheworld:rss" });
119 |  * 	    // Remove all the existing declared indices (twitter and rss). VERY DANGEROUS SETTING!
120 |  * 	    factory.setForceIndex(true);
121 |  * 	    // If setForceIndex is not set, we try to merge existing index settings
122 |  * 	    // with the provided ones
123 |  * 	    factory.setMergeSettings(true);
124 |  * 	    // Disable automatic scanning of the classpath.
125 |  * 	    factory.setAutoscan(false);
126 |  *      factory.afterPropertiesSet();
127 |  *      return factory.getObject();
128 |  *    }
129 |  *  }
130 |  * }
131 |  * 
132 | * By default, indexes are created with their default Elasticsearch settings. You can specify 133 | * your own settings for your index by putting a /es/indexname/_settings.json in your classpath. 134 | *
135 | * So if you create a file named /es/twitter/_settings.json in your src/main/resources folder (for maven lovers), 136 | * it will be used by the factory to create the twitter index. 137 | *
138 |  {
139 |   "settings" : {
140 |    "number_of_shards" : 3,
141 |    "number_of_replicas" : 2
142 |   },
143 |   "mappings" : {
144 |    "properties" : {
145 |     "message" : {"type" : "text"}
146 |    }
147 |   }
148 |  }
149 |  * 
150 | * 151 | * By convention, the factory will create all settings found under the /es classpath.
152 | * You can disable convention and use configuration by setting autoscan to false. 153 | * 154 | * @see ElasticsearchClient 155 | * @author David Pilato 156 | */ 157 | public class ElasticsearchClientFactoryBean 158 | implements FactoryBean, InitializingBean, DisposableBean { 159 | 160 | private static final Logger logger = LoggerFactory.getLogger(ElasticsearchClientFactoryBean.class); 161 | 162 | /** 163 | * Define the username:password to use. 164 | * @deprecated Now deprecated with username and password settings. 165 | * @see ElasticsearchClientFactoryBean#setUsername(String) 166 | * @see ElasticsearchClientFactoryBean#setPassword(String) 167 | */ 168 | @Deprecated 169 | public final static String XPACK_USER = "xpack.security.user"; 170 | 171 | private RestClient lowLevelClient; 172 | 173 | private boolean forceIndex; 174 | 175 | private boolean mergeSettings = true; 176 | 177 | private boolean autoscan = true; 178 | 179 | private String username; 180 | private String password; 181 | 182 | // TODO add support for keys 183 | 184 | @Deprecated 185 | private String[] indices; 186 | 187 | @Deprecated 188 | private String[] aliases; 189 | 190 | @Deprecated 191 | private String[] componentTemplates; 192 | 193 | @Deprecated 194 | private String[] indexTemplates; 195 | 196 | @Deprecated 197 | private String[] pipelines; 198 | 199 | @Deprecated 200 | private String[] lifecycles; 201 | 202 | private String classpathRoot = "es"; 203 | 204 | private Collection esNodes = List.of(HttpHost.create("https://localhost:9200")); 205 | 206 | private ElasticsearchClient client; 207 | 208 | private SSLContext sslContext; 209 | 210 | public RestClient getLowLevelClient() { 211 | return lowLevelClient; 212 | } 213 | 214 | /** 215 | * Elasticsearch properties 216 | * @param properties the properties 217 | * @deprecated it was only used to set xpack.security.user. Please use now {@link #setUsername(String)} 218 | * and {@link #setPassword(String)}. 219 | */ 220 | @Deprecated 221 | public void setProperties(Properties properties) { 222 | String securedUser = properties.getProperty(XPACK_USER, null); 223 | if (securedUser != null) { 224 | logger.warn("Usage of xpack.security.user property has been deprecated. " + 225 | "You should now use username and password factory settings."); 226 | 227 | // We split the username and the password 228 | String[] split = securedUser.split(":"); 229 | if (split.length < 2) { 230 | throw new IllegalArgumentException(XPACK_USER + " must have the form username:password"); 231 | } 232 | username = split[0]; 233 | password = split[1]; 234 | } 235 | } 236 | 237 | /** 238 | * Set to true if you want to force reinit the indices. This will remove all existing indices managed by the factory. 239 | * @param forceIndex true if you want to force reinit the indices 240 | */ 241 | public void setForceIndex(boolean forceIndex) { 242 | this.forceIndex = forceIndex; 243 | } 244 | 245 | /** 246 | * Set to true if you want to try to merge index settings 247 | * @param mergeSettings true if you want to try to merge index settings 248 | */ 249 | public void setMergeSettings(boolean mergeSettings) { 250 | this.mergeSettings = mergeSettings; 251 | } 252 | 253 | /** 254 | * Set to false if you want to use configuration instead of convention. 255 | * @param autoscan false if you want to use configuration instead of convention. 256 | * @deprecated you must use automatic discovery 257 | */ 258 | @Deprecated 259 | public void setAutoscan(boolean autoscan) { 260 | this.autoscan = autoscan; 261 | } 262 | 263 | /** 264 | * Define the Elasticsearch username. Defaults to "elastic". 265 | * @param username Elasticsearch username. 266 | */ 267 | public void setUsername(String username) { 268 | this.username = username; 269 | } 270 | 271 | /** 272 | * Define the Elasticsearch password. Must be provided. 273 | * @param password Elasticsearch password. 274 | */ 275 | public void setPassword(String password) { 276 | this.password = password; 277 | } 278 | 279 | /** 280 | * Define indices you want to manage with this factory 281 | * in case you are not using automatic discovery (see {@link #setAutoscan(boolean)}) 282 | * @param indices Array of index names 283 | * @deprecated you must use automatic discovery (see {@link #setAutoscan(boolean)}) 284 | */ 285 | @Deprecated 286 | public void setIndices(String[] indices) { 287 | this.indices = indices; 288 | } 289 | 290 | /** 291 | * Define aliases you want to manage with this factory 292 | * in case you are not using automatic discovery (see {@link #setAutoscan(boolean)}) 293 | * @param aliases alias array of aliasname:indexname 294 | * @deprecated you must use automatic discovery (see {@link #setAutoscan(boolean)}) 295 | */ 296 | @Deprecated 297 | public void setAliases(String[] aliases) { 298 | this.aliases = aliases; 299 | } 300 | 301 | /** 302 | * Define the index templates you want to manage with this factory 303 | * in case you are not using automatic discovery (see {@link #setAutoscan(boolean)}) 304 | * @param indexTemplates list of index templates 305 | * @deprecated you must use automatic discovery (see {@link #setAutoscan(boolean)}) 306 | */ 307 | @Deprecated 308 | public void setIndexTemplates(String[] indexTemplates) { 309 | this.indexTemplates = indexTemplates; 310 | } 311 | 312 | /** 313 | * Define component templates you want to manage with this factory 314 | * in case you are not using automatic discovery (see {@link #setAutoscan(boolean)}) 315 | * @param componentTemplates list of component templates 316 | * @deprecated you must use automatic discovery (see {@link #setAutoscan(boolean)}) 317 | */ 318 | @Deprecated 319 | public void setComponentTemplates(String[] componentTemplates) { 320 | this.componentTemplates = componentTemplates; 321 | } 322 | 323 | /** 324 | * Define the pipelines you want to manage with this factory 325 | * in case you are not using automatic discovery (see {@link #setAutoscan(boolean)}) 326 | * @param pipelines list of pipelines 327 | * @deprecated you must use automatic discovery (see {@link #setAutoscan(boolean)}) 328 | */ 329 | @Deprecated 330 | public void setPipelines(String[] pipelines) { 331 | this.pipelines = pipelines; 332 | } 333 | 334 | /** 335 | * Classpath root for index and mapping files (default : /es) 336 | *

Example :

337 | *
338 |      * {@code
339 |      * factory.setClasspathRoot("/es");
340 |      * }
341 |      * 
342 | * That means that the factory will look in es folder to find index settings. 343 | *
So if you want to define settings or mappings for the twitter index, you 344 | * should put a _settings.json file under /es/twitter/ folder. 345 | * @param classpathRoot Classpath root for index and mapping files 346 | */ 347 | public void setClasspathRoot(String classpathRoot) { 348 | // For compatibility reasons, we need to convert "/classpathroot" to "classpathroot" 349 | if (classpathRoot.startsWith("/")) { 350 | this.classpathRoot = classpathRoot.substring(1); 351 | } else { 352 | 353 | this.classpathRoot = classpathRoot; 354 | } 355 | } 356 | 357 | /** 358 | * Define ES nodes to communicate with. 359 | * Defaults to [ "https://localhost:9200" ]. 360 | * @param esNodes A collection of nodes 361 | */ 362 | public void setEsNodes(Collection esNodes) { 363 | this.esNodes = esNodes; 364 | } 365 | 366 | /** 367 | * Define ES nodes to communicate with. 368 | *
use : protocol://hostname:port form 369 | * @param esNodes An array of nodes hostname:port 370 | * @deprecated #setEsNodes(HttpHost[]) 371 | */ 372 | @Deprecated 373 | public void setEsNodes(String[] esNodes) { 374 | Collection hosts = new ArrayList<>(esNodes.length); 375 | for (String esNode : esNodes) { 376 | hosts.add(HttpHost.create(esNode)); 377 | } 378 | 379 | this.esNodes = hosts; 380 | } 381 | 382 | /** 383 | * Define the SSLContext to use if any 384 | * @param sslContext SSLContext 385 | * @see SSLUtils#yesSSLContext() for test purposes 386 | * @see SSLUtils#createSslContextFromCa(String) when you want to pass the Elasticsearch self-signed certificate 387 | */ 388 | public void setSslContext(SSLContext sslContext) { 389 | this.sslContext = sslContext; 390 | } 391 | 392 | @Override 393 | public void afterPropertiesSet() throws Exception { 394 | logger.info("Starting Elasticsearch Low Level client"); 395 | lowLevelClient = buildElasticsearchLowLevelClient(); 396 | 397 | logger.info("Starting Elasticsearch client"); 398 | // Create the transport with a Jackson mapper 399 | ElasticsearchTransport transport = new RestClientTransport(lowLevelClient, new JacksonJsonpMapper()); 400 | // And create the API client 401 | client = new ElasticsearchClient(transport); 402 | 403 | // Automagically initialize the cluster/indices 404 | initLifecycles(); 405 | initPipelines(); 406 | initTemplates(); 407 | initSettings(); 408 | initAliases(); 409 | } 410 | 411 | @Override 412 | public void destroy() { 413 | try { 414 | logger.info("Closing Elasticsearch Low Level client"); 415 | if (lowLevelClient != null) { 416 | lowLevelClient.close(); 417 | } 418 | } catch (final Exception e) { 419 | logger.error("Error closing Elasticsearch Low Level client: ", e); 420 | } 421 | } 422 | 423 | @Override 424 | public ElasticsearchClient getObject() { 425 | return client; 426 | } 427 | 428 | @Override 429 | public Class getObjectType() { 430 | return ElasticsearchClient.class; 431 | } 432 | 433 | @Override 434 | public boolean isSingleton() { 435 | return true; 436 | } 437 | 438 | /** 439 | * We use convention over configuration : see ... 440 | */ 441 | static String[] computeIndexNames(boolean autoscan, String[] resources, String classpathRoot) { 442 | if (!autoscan) { 443 | logger.debug("Automatic discovery is disabled. Only static resources are used: {}", (Object) resources); 444 | return resources; 445 | } 446 | if (resources != null && resources.length > 0) { 447 | logger.debug("Resources are manually provided so we won't do any automatic discovery."); 448 | return resources; 449 | } 450 | 451 | if (logger.isDebugEnabled()) { 452 | logger.debug("Automatic discovery is activated. Looking for definition files in classpath under [{}].", 453 | classpathRoot); 454 | } 455 | 456 | try { 457 | // Let's scan our resources 458 | return findIndexNames(classpathRoot).toArray(new String[0]); 459 | } catch (IOException |URISyntaxException e) { 460 | logger.debug("Automatic discovery does not succeed for finding json files in classpath under " + classpathRoot + "."); 461 | logger.trace("", e); 462 | return null; 463 | } 464 | } 465 | 466 | static String[] discoverFromClasspath(boolean autoscan, String[] resources, String classpathRoot, String subdir) { 467 | if (!autoscan) { 468 | logger.debug("Automatic discovery is disabled. Only static resources are used: {}", (Object) resources); 469 | return resources; 470 | } 471 | if (resources != null && resources.length > 0) { 472 | logger.debug("Resources are manually provided so we won't do any automatic discovery."); 473 | return resources; 474 | } 475 | 476 | logger.debug("Automatic discovery is activated. Looking for resource files in classpath under [{}/{}].", 477 | classpathRoot, subdir); 478 | ArrayList autoResources = new ArrayList<>(); 479 | try { 480 | // Let's scan our resources 481 | List scannedResources = ResourceList.getResourceNames(classpathRoot, subdir); 482 | autoResources.addAll(scannedResources); 483 | 484 | return autoResources.toArray(new String[0]); 485 | } catch (IOException|URISyntaxException e) { 486 | logger.debug("Automatic discovery does not succeed for finding json files in classpath under [{}/{}].", classpathRoot, subdir); 487 | logger.trace("", e); 488 | return resources; 489 | } 490 | } 491 | 492 | /** 493 | * Init index settings if needed. 494 | *

Note that you can force to reinit the index using {@link #setForceIndex(boolean)} 495 | */ 496 | private void initSettings() throws Exception { 497 | logger.debug("Initializing indices"); 498 | String[] indices = computeIndexNames(autoscan, this.indices, classpathRoot); 499 | // We extract indexes and mappings to manage from mappings definition 500 | if (indices != null) { 501 | // Let's initialize indexes and mappings if needed 502 | for (String index : indices) { 503 | logger.debug("Initializing index {}", index); 504 | createIndex(lowLevelClient, classpathRoot, index, forceIndex); 505 | if (mergeSettings) { 506 | updateSettings(lowLevelClient, classpathRoot, index); 507 | } 508 | } 509 | 510 | // Let's wait until the index is properly ready to be used 511 | client.cluster().health(hrb -> hrb.index(Arrays.stream(indices).toList()).waitForStatus(HealthStatus.Yellow)); 512 | } 513 | } 514 | 515 | /** 516 | * It creates or updates: 517 | *

    518 | *
  • component templates
  • 519 | *
  • index templates
  • 520 | *
521 | */ 522 | private void initTemplates() throws Exception { 523 | logger.debug("Initializing component templates"); 524 | String[] componentTemplates = discoverFromClasspath(autoscan, this.componentTemplates, classpathRoot, SettingsFinder.Defaults.ComponentTemplatesDir); 525 | if (componentTemplates != null) { 526 | for (String componentTemplate : componentTemplates) { 527 | logger.debug("Initializing component template {}", componentTemplate); 528 | Assert.hasText(componentTemplate, "Can not read component template in [" 529 | + componentTemplate 530 | + "]. Check that component template is not empty."); 531 | createComponentTemplate(lowLevelClient, classpathRoot, componentTemplate); 532 | } 533 | } 534 | logger.debug("Initializing index templates"); 535 | String[] indexTemplates = discoverFromClasspath(autoscan, this.indexTemplates, classpathRoot, SettingsFinder.Defaults.IndexTemplatesDir); 536 | if (indexTemplates != null) { 537 | for (String indexTemplate : indexTemplates) { 538 | logger.debug("Initializing index template {}", indexTemplate); 539 | Assert.hasText(indexTemplate, "Can not read component template in [" 540 | + indexTemplate 541 | + "]. Check that component template is not empty."); 542 | createIndexTemplate(lowLevelClient, classpathRoot, indexTemplate); 543 | } 544 | } 545 | } 546 | 547 | /** 548 | * It creates or updates the index pipelines 549 | */ 550 | private void initPipelines() throws Exception { 551 | logger.debug("Initializing ingest pipelines"); 552 | String[] pipelines = discoverFromClasspath(autoscan, this.pipelines, classpathRoot, SettingsFinder.Defaults.PipelinesDir); 553 | if (pipelines != null) { 554 | for (String pipeline : pipelines) { 555 | logger.debug("Initializing pipeline {}", pipeline); 556 | Assert.hasText(pipeline, "Can not read pipeline in [" 557 | + pipeline 558 | + "]. Check that pipeline is not empty."); 559 | createPipeline(lowLevelClient, classpathRoot, pipeline); 560 | } 561 | } 562 | } 563 | 564 | /** 565 | * It creates or updates the index lifecycles 566 | */ 567 | private void initLifecycles() throws Exception { 568 | logger.debug("Initializing lifecycle policies"); 569 | String [] lifecycles = discoverFromClasspath(autoscan, this.lifecycles, classpathRoot, SettingsFinder.Defaults.IndexLifecyclesDir); 570 | if (lifecycles != null) { 571 | for (String lifecycle : lifecycles) { 572 | logger.debug("Initializing lifecycle {}", lifecycle); 573 | Assert.hasText(lifecycle, "Can not read lifecycle in [" 574 | + lifecycle 575 | + "]. Check that lifecycle is not empty."); 576 | createIndexLifecycle(lowLevelClient, classpathRoot, lifecycle); 577 | } 578 | } 579 | } 580 | 581 | /** 582 | * Init aliases if needed. 583 | */ 584 | private void initAliases() throws Exception { 585 | logger.debug("Initializing aliases"); 586 | 587 | if (!autoscan) { 588 | logger.debug("Automatic discovery is disabled. Only static resources are used: {}", (Object) aliases); 589 | } else { 590 | logger.debug("Automatic discovery is activated. Looking for aliases in classpath under [{}/{}{}].", 591 | classpathRoot, SettingsFinder.Defaults.AliasesFile, SettingsFinder.Defaults.JsonFileExtension); 592 | } 593 | 594 | if (aliases != null && aliases.length > 0) { 595 | logger.debug("Resources are manually provided so we won't do any automatic discovery."); 596 | String request = "{\"actions\":["; 597 | boolean first = true; 598 | for (String aliasIndex : aliases) { 599 | if (!first) { 600 | request += ","; 601 | } 602 | first = false; 603 | Tuple aliasIndexSplitted = computeAlias(aliasIndex); 604 | logger.debug("add alias {} on index {}", aliasIndexSplitted.v2(), aliasIndexSplitted.v1()); 605 | request += "{\"add\":{\"index\":\"" + aliasIndexSplitted.v1() +"\",\"alias\":\"" + aliasIndexSplitted.v2() +"\"}}"; 606 | } 607 | request += "]}"; 608 | manageAliasesWithJsonInElasticsearch(lowLevelClient, request); 609 | } else { 610 | manageAliases(lowLevelClient, classpathRoot); 611 | } 612 | } 613 | 614 | static Tuple computeAlias(String aliasIndex) { 615 | String[] aliasIndexSplitted = aliasIndex.split(":"); 616 | String alias = aliasIndexSplitted[0]; 617 | String index = aliasIndexSplitted[1]; 618 | 619 | if (index == null) throw new IllegalArgumentException("Can not read index in [" + aliasIndex + 620 | "]. Check that aliases contains only aliasname:indexname elements."); 621 | if (alias == null) throw new IllegalArgumentException("Can not read mapping in [" + aliasIndex + 622 | "]. Check that aliases contains only aliasname:indexname elements."); 623 | 624 | return new Tuple<>(index, alias); 625 | } 626 | 627 | private RestClient buildElasticsearchLowLevelClient() { 628 | RestClientBuilder rcb = RestClient.builder(esNodes.toArray(new HttpHost[]{})); 629 | 630 | // We need to check if we have a user security property 631 | if (username == null || password == null) { 632 | throw new IllegalArgumentException("From version 8, you MUST define a user and a password to access Elasticsearch."); 633 | } 634 | 635 | final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); 636 | credentialsProvider.setCredentials(AuthScope.ANY, 637 | new UsernamePasswordCredentials(username, password)); 638 | 639 | rcb.setHttpClientConfigCallback(hcb -> { 640 | hcb.setDefaultCredentialsProvider(credentialsProvider); 641 | if (sslContext != null) { 642 | hcb.setSSLContext(sslContext); 643 | } 644 | return hcb; 645 | }); 646 | 647 | return rcb.build(); 648 | } 649 | } 650 | -------------------------------------------------------------------------------- /src/main/java/fr/pilato/spring/elasticsearch/SSLUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch; 21 | 22 | import org.apache.commons.io.IOUtils; 23 | import org.apache.http.ssl.SSLContextBuilder; 24 | import org.apache.http.ssl.SSLContexts; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | import javax.net.ssl.SSLContext; 29 | import javax.net.ssl.TrustManagerFactory; 30 | import javax.net.ssl.X509TrustManager; 31 | import java.io.ByteArrayInputStream; 32 | import java.io.IOException; 33 | import java.io.InputStream; 34 | import java.nio.file.Files; 35 | import java.nio.file.Path; 36 | import java.nio.file.Paths; 37 | import java.security.KeyManagementException; 38 | import java.security.KeyStore; 39 | import java.security.KeyStoreException; 40 | import java.security.NoSuchAlgorithmException; 41 | import java.security.cert.Certificate; 42 | import java.security.cert.CertificateException; 43 | import java.security.cert.CertificateFactory; 44 | import java.security.cert.X509Certificate; 45 | 46 | public class SSLUtils { 47 | private static final Logger logger = LoggerFactory.getLogger(SSLUtils.class); 48 | private static SSLContext yesCtx = null; 49 | private static SSLContext checkCertificatesSSLContext = null; 50 | 51 | /** 52 | * Returns an SSLContext that will accept any server certificate. 53 | * Use with great care and in limited situations, as it allows MITM attacks. 54 | */ 55 | public static SSLContext yesSSLContext() { 56 | logger.warn("You disabled checking the https certificate. This could lead to " + 57 | "'Man in the middle' attacks. This setting is only intended for tests."); 58 | 59 | if (yesCtx == null) { 60 | X509TrustManager yesTm = new X509TrustManager() { 61 | @Override 62 | public void checkClientTrusted(X509Certificate[] certs, String authType) { 63 | // Accept anything 64 | } 65 | 66 | @Override 67 | public void checkServerTrusted(X509Certificate[] certs, String authType) { 68 | // Accept anything 69 | } 70 | 71 | @Override 72 | public X509Certificate[] getAcceptedIssuers() { 73 | return new X509Certificate[0]; 74 | } 75 | }; 76 | 77 | try { 78 | SSLContext ctx = SSLContext.getInstance("SSL"); 79 | ctx.init(null, new X509TrustManager[] { yesTm }, null); 80 | yesCtx = ctx; 81 | } catch (Exception e) { 82 | // An exception here means SSL is not supported, which is unlikely 83 | throw new RuntimeException(e); 84 | } 85 | } 86 | 87 | return yesCtx; 88 | } 89 | 90 | /** 91 | * 92 | * @param trustStore 93 | * @param keyStoreType pkcs12 94 | * @return 95 | */ 96 | public static SSLContext checkCertificatesSSLContext(String trustStore, String keyStoreType, String keyStorePass) { 97 | if (checkCertificatesSSLContext == null) { 98 | try { 99 | Path trustStorePath = Paths.get(trustStore); 100 | KeyStore truststore = KeyStore.getInstance(keyStoreType); 101 | try (InputStream is = Files.newInputStream(trustStorePath)) { 102 | truststore.load(is, keyStorePass.toCharArray()); 103 | } 104 | SSLContextBuilder sslBuilder = SSLContexts.custom().loadTrustMaterial(truststore, null); 105 | checkCertificatesSSLContext = sslBuilder.build(); 106 | } catch (IOException | CertificateException | NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) { 107 | logger.error("Can not load the SSLContext for {}, {}", trustStore, keyStoreType); 108 | } 109 | } 110 | return checkCertificatesSSLContext; 111 | } 112 | 113 | /** 114 | * A SSL context based on the self signed CA, so that using this SSL Context allows to connect to the Elasticsearch service 115 | * @return a customized SSL Context 116 | */ 117 | public SSLContext createSslContextFromCa(String certPath) { 118 | try { 119 | byte[] bytes = IOUtils.resourceToByteArray(certPath); 120 | CertificateFactory factory = CertificateFactory.getInstance("X.509"); 121 | Certificate trustedCa = factory.generateCertificate(new ByteArrayInputStream(bytes)); 122 | KeyStore trustStore = KeyStore.getInstance("pkcs12"); 123 | trustStore.load(null, null); 124 | trustStore.setCertificateEntry("ca", trustedCa); 125 | 126 | final SSLContext sslContext = SSLContext.getInstance("TLSv1.3"); 127 | TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 128 | tmfactory.init(trustStore); 129 | sslContext.init(null, tmfactory.getTrustManagers(), null); 130 | return sslContext; 131 | } catch (Exception e) { 132 | throw new RuntimeException(e); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/fr/pilato/spring/elasticsearch/Tuple.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch; 21 | 22 | public class Tuple { 23 | 24 | public static Tuple tuple(V1 v1, V2 v2) { 25 | return new Tuple<>(v1, v2); 26 | } 27 | 28 | private final V1 v1; 29 | private final V2 v2; 30 | 31 | public Tuple(V1 v1, V2 v2) { 32 | this.v1 = v1; 33 | this.v2 = v2; 34 | } 35 | 36 | public V1 v1() { 37 | return v1; 38 | } 39 | 40 | public V2 v2() { 41 | return v2; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return "Tuple [v1=" + v1 + ", v2=" + v2 + "]"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/resources/org/apache/maven/plugin/announcement/announcement.vm: -------------------------------------------------------------------------------- 1 | ## Licensed to the Apache Software Foundation (ASF) under one 2 | ## or more contributor license agreements. See the NOTICE file 3 | ## distributed with this work for additional information 4 | ## regarding copyright ownership. The ASF licenses this file 5 | ## to you under the Apache License, Version 2.0 (the 6 | ## "License"); you may not use this file except in compliance 7 | ## with the License. You may obtain a copy of the License at 8 | ## 9 | ## http://www.apache.org/licenses/LICENSE-2.0 10 | ## 11 | ## Unless required by applicable law or agreed to in writing, 12 | ## software distributed under the License is distributed on an 13 | ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | ## KIND, either express or implied. See the License for the 15 | ## specific language governing permissions and limitations 16 | ## under the License. 17 | The ${developmentTeam} is pleased to announce the **${finalName}** release! 18 | 19 | # ${introduction} 20 | 21 |

Usage

22 | 23 | Add this library to you project: 24 | 25 | ``` 26 | 27 | ${project.groupId} 28 | ${project.artifactId} 29 | ${project.version} 30 | 31 | ``` 32 | 33 | #if ($release.getActions().size() == 0) 34 | No changes defined in this version. 35 | #else 36 | 37 | #if ($release.getActions('add').size() !=0) 38 |

New features

39 | 40 | #foreach($actionItem in $release.getActions('add')) 41 | #set($action=$actionItem.getAction()) 42 | #if ($actionItem.getIssue()) 43 | #set($issue=$actionItem.getIssue()) 44 | #else 45 | #set($issue="") 46 | #end 47 | #if ($actionItem.getDueTo()) 48 | #set($dueto=$actionItem.getDueTo()) 49 | #else 50 | #set($dueto="") 51 | #end 52 | * [#$issue](https://github.com/dadoonet/spring-elasticsearch/issues/$issue): ${action} #if($!issue != ""). #end#if($!dueto != "")Thanks to $dueto. #end 53 | 54 | #set($issue="") 55 | #set($dueto="") 56 | #end 57 | #end 58 | 59 | #if ($release.getActions('fix').size() !=0) 60 |

Fixed Bugs

61 | 62 | #foreach($actionItem in $release.getActions('fix')) 63 | #set($action=$actionItem.getAction()) 64 | #if ($actionItem.getIssue()) 65 | #set($issue=$actionItem.getIssue()) 66 | #else 67 | #set($issue="") 68 | #end 69 | #if ($actionItem.getDueTo()) 70 | #set($dueto=$actionItem.getDueTo()) 71 | #else 72 | #set($dueto="") 73 | #end 74 | * [#$issue](https://github.com/dadoonet/spring-elasticsearch/issues/$issue): ${action} #if($!issue != ""). #end#if($!dueto != "")Thanks to $dueto. #end 75 | 76 | #set($issue="") 77 | #set($dueto="") 78 | #end 79 | #end 80 | 81 | #if ($release.getActions('update').size() !=0) 82 |

Changes

83 | 84 | #foreach($actionItem in $release.getActions('update')) 85 | #set($action=$actionItem.getAction()) 86 | #if ($actionItem.getIssue()) 87 | #set($issue=$actionItem.getIssue()) 88 | #else 89 | #set($issue="") 90 | #end 91 | #if ($actionItem.getDueTo()) 92 | #set($dueto=$actionItem.getDueTo()) 93 | #else 94 | #set($dueto="") 95 | #end 96 | * [#$issue](https://github.com/dadoonet/spring-elasticsearch/issues/$issue): ${action} #if($!issue != ""). #end#if($!dueto != "")Thanks to $dueto. #end 97 | 98 | #set($issue="") 99 | #set($dueto="") 100 | #end 101 | #end 102 | 103 | #if ($release.getActions('remove').size() !=0) 104 |

Removed

105 | 106 | #foreach($actionItem in $release.getActions('remove')) 107 | #set($action=$actionItem.getAction()) 108 | #if ($actionItem.getIssue()) 109 | #set($issue=$actionItem.getIssue()) 110 | #else 111 | #set($issue="") 112 | #end 113 | #if ($actionItem.getDueTo()) 114 | #set($dueto=$actionItem.getDueTo()) 115 | #else 116 | #set($dueto="") 117 | #end 118 | * [#$issue](https://github.com/dadoonet/spring-elasticsearch/issues/$issue): ${action} #if($!issue != ""). #end#if($!dueto != "")Thanks to $dueto. #end 119 | 120 | #set($issue="") 121 | #set($dueto="") 122 | #end 123 | #end 124 | ## End of main loop 125 | #end 126 | #if ($urlDownload) 127 | 128 | For a manual installation, you can download the ${finalName} here: 129 | ${urlDownload} 130 | #end 131 | 132 | Have fun! 133 | -${developmentTeam} 134 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/BaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it; 21 | 22 | import com.fasterxml.jackson.core.type.TypeReference; 23 | import com.fasterxml.jackson.databind.ObjectMapper; 24 | import fr.pilato.spring.elasticsearch.SSLUtils; 25 | import org.apache.http.HttpHost; 26 | import org.apache.http.auth.AuthScope; 27 | import org.apache.http.auth.UsernamePasswordCredentials; 28 | import org.apache.http.client.CredentialsProvider; 29 | import org.apache.http.impl.client.BasicCredentialsProvider; 30 | import org.elasticsearch.client.Request; 31 | import org.elasticsearch.client.Response; 32 | import org.elasticsearch.client.ResponseException; 33 | import org.elasticsearch.client.RestClient; 34 | import org.elasticsearch.client.RestClientBuilder; 35 | import org.junit.jupiter.api.AfterAll; 36 | import org.junit.jupiter.api.AfterEach; 37 | import org.junit.jupiter.api.BeforeAll; 38 | import org.junit.jupiter.api.BeforeEach; 39 | import org.slf4j.Logger; 40 | import org.slf4j.LoggerFactory; 41 | 42 | import java.io.IOException; 43 | import java.net.ConnectException; 44 | import java.util.ArrayList; 45 | import java.util.List; 46 | import java.util.Map; 47 | 48 | import static org.junit.jupiter.api.Assumptions.assumeFalse; 49 | 50 | public abstract class BaseTest { 51 | private final static Logger staticLogger = LoggerFactory.getLogger(BaseTest.class); 52 | protected final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); 53 | 54 | private static RestClient client; 55 | 56 | public final static String DEFAULT_TEST_CLUSTER = "https://127.0.0.1:9200"; 57 | private final static String DEFAULT_TEST_USER = "elastic"; 58 | private final static String DEFAULT_TEST_PASSWORD = "changeme"; 59 | 60 | public final static String testCluster = System.getProperty("tests.cluster", DEFAULT_TEST_CLUSTER); 61 | public final static String testClusterUser = System.getProperty("tests.cluster.user", DEFAULT_TEST_USER); 62 | public final static String testClusterPass = System.getProperty("tests.cluster.pass", DEFAULT_TEST_PASSWORD); 63 | 64 | private static void testClusterRunning() throws IOException { 65 | try { 66 | Response response = client.performRequest(new Request("GET", "/")); 67 | Map result = new ObjectMapper().readValue(response.getEntity().getContent(), new TypeReference<>() { 68 | }); 69 | 70 | Map asMap = (Map) result.get("version"); 71 | 72 | staticLogger.info("Starting integration tests against an external cluster running elasticsearch [{}]", 73 | asMap.get("number")); 74 | } catch (ConnectException e) { 75 | // If we have an exception here, let's ignore the test 76 | staticLogger.warn("Integration tests are skipped: [{}]", e.getMessage()); 77 | assumeFalse(e.getMessage().contains("Connection refused"), "Integration tests are skipped"); 78 | } catch (IOException e) { 79 | staticLogger.error("Full error is", e); 80 | throw e; 81 | } 82 | } 83 | 84 | 85 | @BeforeAll 86 | public static void startElasticsearchClient() { 87 | try { 88 | if (client == null) { 89 | staticLogger.info("Starting tests against {}", testCluster); 90 | RestClientBuilder builder = RestClient.builder(HttpHost.create(testCluster)); 91 | final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); 92 | credentialsProvider.setCredentials(AuthScope.ANY, 93 | new UsernamePasswordCredentials(testClusterUser, testClusterPass)); 94 | 95 | builder.setHttpClientConfigCallback(hcb -> { 96 | hcb.setDefaultCredentialsProvider(credentialsProvider); 97 | if (testCluster.equals(DEFAULT_TEST_CLUSTER)) { 98 | hcb.setSSLContext(SSLUtils.yesSSLContext()); 99 | } 100 | return hcb; 101 | }); 102 | 103 | client = builder.build(); 104 | testClusterRunning(); 105 | } 106 | } catch (Exception e) { 107 | staticLogger.error("Error", e); 108 | assumeFalse(true, "Elasticsearch does not seem to run."); 109 | } 110 | } 111 | 112 | @AfterAll 113 | public static void stopClient() throws IOException { 114 | if (client != null) { 115 | client.close(); 116 | client = null; 117 | } 118 | } 119 | 120 | protected void executeBefore(RestClient client) throws IOException { 121 | // Do nothing 122 | } 123 | 124 | @BeforeEach @AfterEach 125 | public void cleanIndex() throws IOException { 126 | if (indexName() != null) { 127 | deleteIndex(indexName()); 128 | } 129 | for (String otherTestIndex : otherTestIndices()) { 130 | deleteIndex(otherTestIndex); 131 | } 132 | deleteIndex("twitter"); 133 | executeBefore(client); 134 | } 135 | 136 | private void deleteIndex(String indexName) throws IOException { 137 | try { 138 | logger.debug("Removing index {}", indexName); 139 | client.performRequest(new Request("DELETE", "/" + indexName)); 140 | logger.debug("Removing index {} - ok", indexName); 141 | } catch (ResponseException e) { 142 | if (e.getResponse().getStatusLine().getStatusCode() != 404) { 143 | throw e; 144 | } 145 | logger.debug("Removing index {} - not found", indexName); 146 | } 147 | } 148 | 149 | /** 150 | * Overwrite if twitter is not the index name. Can be null if no index should be created 151 | * @return Index name. Could be null 152 | */ 153 | protected String indexName() { 154 | return "twitter"; 155 | } 156 | 157 | /** 158 | * Overwrite if the test is using multiple indices. Can be null if no other index should be created 159 | * @return Index name. Could be null 160 | */ 161 | protected List otherTestIndices() { 162 | return new ArrayList<>(); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/AbstractAnnotationContextModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation; 21 | 22 | import fr.pilato.spring.elasticsearch.it.BaseTest; 23 | import org.junit.jupiter.api.AfterEach; 24 | import org.junit.jupiter.api.BeforeEach; 25 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 26 | 27 | public abstract class AbstractAnnotationContextModel extends BaseTest { 28 | protected AnnotationConfigApplicationContext ctx; 29 | 30 | /** 31 | * @return list of specific classpath to load if not the default one 32 | */ 33 | String classpath() { 34 | return null; 35 | } 36 | 37 | @BeforeEach 38 | void startContext() { 39 | String classpath = classpath(); 40 | 41 | if (classpath == null || classpath.isEmpty()) { 42 | // If not set, the test package name is used. 43 | classpath = this.getClass().getPackage().getName(); 44 | } 45 | 46 | logger.info(" --> Starting Spring Context on [{}] classpath", classpath); 47 | ctx = new AnnotationConfigApplicationContext(); 48 | ctx.scan(classpath); 49 | ctx.refresh(); 50 | } 51 | 52 | @AfterEach 53 | void stopContext() { 54 | if (ctx != null) { 55 | logger.info(" --> Closing Spring Context"); 56 | ctx.close(); 57 | } 58 | } 59 | 60 | /** 61 | * Overwrite it if the number of expected shards is not 5 62 | * @return Number of expected primaries 63 | */ 64 | protected int expectedShards() { 65 | return 1; 66 | } 67 | 68 | /** 69 | * Overwrite it if the number of expected replicas is not 1 70 | * @return Number of expected replicas 71 | */ 72 | protected int expectedReplicas() { 73 | return 1; 74 | } 75 | 76 | protected String beanName() { 77 | return "esClient"; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/AbstractRestAnnotationContextModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import co.elastic.clients.elasticsearch.core.GetResponse; 24 | import co.elastic.clients.elasticsearch.indices.GetIndicesSettingsResponse; 25 | import fr.pilato.spring.elasticsearch.it.annotation.AbstractAnnotationContextModel; 26 | import org.junit.jupiter.api.Test; 27 | 28 | import java.io.IOException; 29 | import java.io.StringReader; 30 | 31 | import static org.hamcrest.MatcherAssert.assertThat; 32 | import static org.hamcrest.Matchers.*; 33 | 34 | public abstract class AbstractRestAnnotationContextModel extends AbstractAnnotationContextModel { 35 | protected ElasticsearchClient checkClient(String name) { 36 | ElasticsearchClient client; 37 | 38 | if (name != null) { 39 | client = ctx.getBean(name, ElasticsearchClient.class); 40 | } else { 41 | client = ctx.getBean(ElasticsearchClient.class); 42 | } 43 | assertThat(client, not(nullValue())); 44 | return client; 45 | } 46 | 47 | @Test 48 | public void testFactoriesCreated() throws Exception { 49 | ElasticsearchClient client = checkClient(beanName()); 50 | checkUseCaseSpecific(client); 51 | 52 | // If an index is expected, let's check it actually exists 53 | if (indexName() != null) { 54 | // We test how many shards and replica we have 55 | assertShardsAndReplicas(client, indexName(), expectedShards(), expectedReplicas()); 56 | 57 | // #92: search errors with async created Client 58 | client.index(ir -> ir.index("twitter").id("1").withJson(new StringReader("{\"foo\":\"bar\"}"))); 59 | GetResponse response = client.get(gr -> gr.index("twitter").id("1"), Void.class); 60 | assertThat(response, notNullValue()); 61 | } 62 | } 63 | 64 | /** 65 | * Overwrite it to implement use case specific tests 66 | * @param client Client representing bean named esClient 67 | */ 68 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws Exception { 69 | } 70 | 71 | protected void assertShardsAndReplicas(ElasticsearchClient client, String indexName, int expectedShards, int expectedReplicas) throws IOException { 72 | GetIndicesSettingsResponse settings = client.indices().getSettings(gisr -> gisr.index(indexName)); 73 | assertThat(Integer.parseInt(settings.get(indexName).settings().index().numberOfShards()), is(expectedShards)); 74 | assertThat(Integer.parseInt(settings.get(indexName).settings().index().numberOfReplicas()), is(expectedReplicas)); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/RestAppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 24 | import fr.pilato.spring.elasticsearch.SSLUtils; 25 | import org.apache.http.HttpHost; 26 | import org.springframework.context.annotation.Bean; 27 | 28 | import java.util.List; 29 | 30 | import static fr.pilato.spring.elasticsearch.it.BaseTest.*; 31 | 32 | public abstract class RestAppConfig { 33 | 34 | abstract protected void enrichFactory(ElasticsearchClientFactoryBean factory); 35 | 36 | @Bean 37 | public ElasticsearchClient esClient() throws Exception { 38 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 39 | enrichFactoryWithNodeSettings(factory); 40 | enrichFactory(factory); 41 | factory.afterPropertiesSet(); 42 | return factory.getObject(); 43 | } 44 | 45 | public static void enrichFactoryWithNodeSettings(ElasticsearchClientFactoryBean factory) { 46 | factory.setEsNodes(List.of(HttpHost.create(testCluster))); 47 | factory.setUsername(testClusterUser); 48 | factory.setPassword(testClusterPass); 49 | if (testCluster.equals(DEFAULT_TEST_CLUSTER)) { 50 | factory.setSslContext(SSLUtils.yesSSLContext()); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/aliases/AliasesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.aliases; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import co.elastic.clients.elasticsearch.indices.get_alias.IndexAliases; 24 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 25 | 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import static java.util.Arrays.asList; 30 | import static org.hamcrest.MatcherAssert.assertThat; 31 | import static org.hamcrest.Matchers.hasKey; 32 | import static org.hamcrest.Matchers.not; 33 | 34 | public class AliasesTest extends AbstractRestAnnotationContextModel { 35 | 36 | @Override 37 | protected List otherTestIndices() { 38 | return asList("test_1", "test_2"); 39 | } 40 | 41 | @Override 42 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws Exception { 43 | Map response = client.indices().getAlias(gar -> gar.name("test")).result(); 44 | assertThat(response, not(hasKey("test_1"))); 45 | assertThat(response, hasKey("test_2")); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/aliases/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.aliases; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/models/root/aliases"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/badclasspath/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.badclasspath; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/esdoesnotexist"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/badclasspath/BadClasspath7Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.badclasspath; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | 25 | import java.io.IOException; 26 | 27 | import static org.hamcrest.MatcherAssert.assertThat; 28 | import static org.hamcrest.Matchers.is; 29 | 30 | 31 | public class BadClasspath7Test extends AbstractRestAnnotationContextModel { 32 | @Override 33 | public String indexName() { 34 | return null; 35 | } 36 | 37 | @Override 38 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 39 | assertThat("twitter index should not exist", client.indices().exists(er -> er.index("twitter")).value(), is(false)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/configuration/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.configuration; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/configuration/ConfigurationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.configuration; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | 25 | class ConfigurationTest extends AbstractRestAnnotationContextModel { 26 | 27 | @Override 28 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws Exception { 29 | // We call the Rest client to make sure it works properly 30 | client.info(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/customanalyzers/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.customanalyzers; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/models/root/custom-analyzers-12/client"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/customanalyzers/CustomAnalyzers12Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.customanalyzers; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | 25 | import java.io.IOException; 26 | 27 | import static org.hamcrest.MatcherAssert.assertThat; 28 | import static org.hamcrest.Matchers.is; 29 | 30 | 31 | public class CustomAnalyzers12Test extends AbstractRestAnnotationContextModel { 32 | 33 | @Override 34 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 35 | assertThat(client.indices().getSettings(gisr -> gisr.index("twitter")) 36 | .get("twitter").settings().index().analysis().analyzer().get("francais").isCustom(), 37 | is(true)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/indextemplates/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.indextemplates; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/models/root/index-templates/client"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/indextemplates/IndexTemplatesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.indextemplates; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | import org.elasticsearch.client.Request; 25 | import org.elasticsearch.client.ResponseException; 26 | import org.elasticsearch.client.RestClient; 27 | 28 | import java.io.IOException; 29 | 30 | import static org.hamcrest.MatcherAssert.assertThat; 31 | import static org.hamcrest.Matchers.is; 32 | 33 | 34 | public class IndexTemplatesTest extends AbstractRestAnnotationContextModel { 35 | 36 | @Override 37 | protected void executeBefore(RestClient client) throws IOException { 38 | try { 39 | client.performRequest(new Request("DELETE", "/_index_template/template_1")); 40 | } catch (ResponseException ignored) { } 41 | try { 42 | client.performRequest(new Request("DELETE", "/_component_template/component1")); 43 | } catch (ResponseException ignored) { } 44 | try { 45 | client.performRequest(new Request("DELETE", "/_component_template/component2")); 46 | } catch (ResponseException ignored) { } 47 | } 48 | 49 | @Override 50 | protected String indexName() { 51 | return null; 52 | } 53 | 54 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 55 | boolean existsTemplate = client.indices().existsIndexTemplate(eit -> eit.name("template_1")).value(); 56 | assertThat(existsTemplate, is(true)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/indicesalreadyexist/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.indicesalreadyexist; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 24 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 25 | import org.springframework.context.annotation.Bean; 26 | import org.springframework.context.annotation.Configuration; 27 | 28 | @Configuration 29 | public class AppConfig extends RestAppConfig { 30 | 31 | @Override 32 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 33 | factory.setClasspathRoot("/models/root/indices-already-exist-86/client"); 34 | } 35 | 36 | @Bean 37 | public ElasticsearchClient esClient2() throws Exception { 38 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 39 | enrichFactoryWithNodeSettings(factory); 40 | factory.setClasspathRoot("/models/root/indices-already-exist-86/client"); 41 | factory.afterPropertiesSet(); 42 | return factory.getObject(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/indicesalreadyexist/IndicesAlreadyExistTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.indicesalreadyexist; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import java.util.Collections; 27 | import java.util.List; 28 | 29 | import static org.hamcrest.MatcherAssert.assertThat; 30 | import static org.hamcrest.Matchers.notNullValue; 31 | 32 | public class IndicesAlreadyExistTest extends AbstractRestAnnotationContextModel { 33 | 34 | @Override 35 | protected List otherTestIndices() { 36 | return Collections.singletonList("badindex"); 37 | } 38 | 39 | @Test 40 | void testTwoClients() { 41 | ElasticsearchClient esClient = checkClient("esClient"); 42 | assertThat(esClient, notNullValue()); 43 | ElasticsearchClient esClient2 = checkClient("esClient2"); 44 | assertThat(esClient2, notNullValue()); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/lifecycles/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.lifecycles; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/models/root/lifecycles"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/lifecycles/LifecyclesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.lifecycles; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | import org.elasticsearch.client.Request; 25 | import org.elasticsearch.client.ResponseException; 26 | import org.elasticsearch.client.RestClient; 27 | 28 | import java.io.IOException; 29 | 30 | import static org.hamcrest.MatcherAssert.assertThat; 31 | import static org.hamcrest.Matchers.notNullValue; 32 | 33 | 34 | public class LifecyclesTest extends AbstractRestAnnotationContextModel { 35 | 36 | @Override 37 | protected void executeBefore(RestClient client) throws IOException { 38 | try { 39 | client.performRequest(new Request("DELETE", "/_ilm/policy/policy1")); 40 | } catch (ResponseException ignored) { } 41 | } 42 | 43 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 44 | assertThat(client.ilm().getLifecycle(glr -> glr.name("policy1")), notNullValue()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/manualsettings/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.manualsettings; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/models/root/manual-settings"); 32 | factory.setIndices(new String[]{"twitter"}); 33 | factory.setAliases(new String[]{"alltheworld:twitter"}); 34 | factory.setPipelines(new String[]{"pipeline1"}); 35 | factory.setComponentTemplates(new String[]{"component1"}); 36 | factory.setIndexTemplates(new String[]{"template_1"}); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/manualsettings/ManualSettingsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.manualsettings; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import co.elastic.clients.elasticsearch._types.ElasticsearchException; 24 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 25 | import org.elasticsearch.client.Request; 26 | import org.elasticsearch.client.ResponseException; 27 | import org.elasticsearch.client.RestClient; 28 | 29 | import java.io.IOException; 30 | 31 | import static org.hamcrest.MatcherAssert.assertThat; 32 | import static org.hamcrest.Matchers.*; 33 | import static org.junit.jupiter.api.Assertions.assertThrows; 34 | 35 | public class ManualSettingsTest extends AbstractRestAnnotationContextModel { 36 | @Override 37 | protected void executeBefore(RestClient client) throws IOException { 38 | try { 39 | client.performRequest(new Request("DELETE", "/_index_template/template_1")); 40 | } catch (ResponseException ignored) { } 41 | try { 42 | client.performRequest(new Request("DELETE", "/_component_template/component1")); 43 | } catch (ResponseException ignored) { } 44 | try { 45 | client.performRequest(new Request("DELETE", "/_pipeline/pipeline1")); 46 | } catch (ResponseException ignored) { } 47 | } 48 | 49 | @Override 50 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws Exception { 51 | // Test manual creation of one index even though we have multiple ones in the classpath 52 | assertThat(client.indices().get(gir -> gir.index("twitter")).result(), hasKey("twitter")); 53 | assertThat(client.indices().get(gir -> gir.index("foobar").ignoreUnavailable(true)).result(), not(hasKey("twitter"))); 54 | 55 | // Test manual creation of one alias even though we have multiple ones in the classpath 56 | assertThat(client.indices().getAlias(gar -> gar.index("twitter")).result().get("twitter").aliases(), hasKey("alltheworld")); 57 | assertThat(client.indices().getAlias(gar -> gar.index("twitter")).result().get("twitter").aliases(), not(hasKey("alias"))); 58 | 59 | // Test manual creation of one pipeline even though we have multiple ones in the classpath 60 | assertThat(client.ingest().getPipeline(gpr -> gpr.id("pipeline1")).get("pipeline1"), notNullValue()); 61 | assertThat(client.ingest().getPipeline(gpr -> gpr.id("pipeline2")).get("pipeline2"), nullValue()); 62 | 63 | // Test manual creation of one component template even though we have multiple ones in the classpath 64 | assertThat(client.cluster().getComponentTemplate(gctr -> gctr.name("component1")).componentTemplates(), hasSize(1)); 65 | assertThrows(ElasticsearchException.class, () -> { 66 | try { 67 | client.cluster().getComponentTemplate(gctr -> gctr.name("component2")); 68 | } catch (ElasticsearchException e) { 69 | assertThat(e.status(), is(404)); 70 | throw e; 71 | } 72 | }); 73 | 74 | // Test manual creation of one index template even though we have multiple ones in the classpath 75 | assertThat(client.indices().existsIndexTemplate(eit -> eit.name("template_1")).value(), is(true)); 76 | assertThat(client.indices().existsIndexTemplate(eit -> eit.name("template_2")).value(), is(false)); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/mapping/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.mapping; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 24 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 25 | import org.springframework.context.annotation.Bean; 26 | import org.springframework.context.annotation.Configuration; 27 | 28 | @Configuration 29 | public class AppConfig extends RestAppConfig { 30 | 31 | @Override 32 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 33 | factory.setClasspathRoot("/models/root/mapping/client1"); 34 | factory.setForceIndex(false); 35 | } 36 | 37 | @Bean 38 | public ElasticsearchClient esClient2() throws Exception { 39 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 40 | enrichFactoryWithNodeSettings(factory); 41 | factory.setClasspathRoot("/models/root/mapping/client2"); 42 | factory.setMergeSettings(true); 43 | factory.afterPropertiesSet(); 44 | return factory.getObject(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/mapping/MappingTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.mapping; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import co.elastic.clients.elasticsearch._types.mapping.Property; 24 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 25 | 26 | import java.io.IOException; 27 | import java.util.Map; 28 | 29 | import static org.hamcrest.MatcherAssert.assertThat; 30 | import static org.hamcrest.Matchers.hasKey; 31 | 32 | 33 | public class MappingTest extends AbstractRestAnnotationContextModel { 34 | 35 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 36 | ElasticsearchClient client2 = checkClient("esClient2"); 37 | 38 | Map response = client2.indices() 39 | .getMapping(gmr -> gmr.index("twitter")).get("twitter").mappings().properties(); 40 | // This one comes from the first mapping 41 | assertThat(response, hasKey("message")); 42 | // This one comes from the second mapping 43 | assertThat(response, hasKey("author")); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/mappingconvention/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.mappingconvention; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/mappingconvention/MappingConventionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.mappingconvention; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import co.elastic.clients.elasticsearch._types.mapping.Property; 24 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 25 | 26 | import java.io.IOException; 27 | 28 | import static org.hamcrest.MatcherAssert.assertThat; 29 | import static org.hamcrest.Matchers.is; 30 | import static org.hamcrest.Matchers.notNullValue; 31 | 32 | public class MappingConventionTest extends AbstractRestAnnotationContextModel { 33 | 34 | @Override 35 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 36 | Property property = client.indices().getMapping(gmr -> gmr.index("twitter")).get("twitter").mappings().properties().get("message"); 37 | assertThat(property, notNullValue()); 38 | assertThat(property.text().store(), is(true)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/mappingfailed/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.mappingfailed; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | 27 | import static fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig.enrichFactoryWithNodeSettings; 28 | 29 | @Configuration 30 | public class AppConfig { 31 | 32 | @Bean 33 | public ElasticsearchClient esClient() throws Exception { 34 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 35 | enrichFactoryWithNodeSettings(factory); 36 | factory.setClasspathRoot("/models/root/mapping-failed/client1"); 37 | factory.setForceIndex(false); 38 | factory.afterPropertiesSet(); 39 | return factory.getObject(); 40 | } 41 | 42 | @Bean 43 | public ElasticsearchClient esClient2() throws Exception { 44 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 45 | enrichFactoryWithNodeSettings(factory); 46 | factory.setClasspathRoot("/models/root/mapping-failed/client2"); 47 | factory.setMergeSettings(true); 48 | factory.afterPropertiesSet(); 49 | return factory.getObject(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/mappingfailed/MappingFailedTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.mappingfailed; 21 | 22 | import fr.pilato.spring.elasticsearch.it.BaseTest; 23 | import org.elasticsearch.client.ResponseException; 24 | import org.junit.jupiter.api.Test; 25 | import org.springframework.beans.factory.BeanCreationException; 26 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 27 | 28 | import static org.hamcrest.MatcherAssert.assertThat; 29 | import static org.hamcrest.Matchers.is; 30 | import static org.junit.jupiter.api.Assertions.assertEquals; 31 | import static org.junit.jupiter.api.Assertions.assertThrows; 32 | 33 | /** 34 | * We try to merge non merging mapping. 35 | * An exception should be raised. 36 | * @author David Pilato aka dadoonet 37 | * 38 | */ 39 | public class MappingFailedTest extends BaseTest { 40 | 41 | @Override 42 | public String indexName() { 43 | return null; 44 | } 45 | 46 | @Test 47 | void test_rest_client() { 48 | assertThrows(BeanCreationException.class, () -> { 49 | try { 50 | logger.info(" --> Starting Spring Context on [{}] classpath", this.getClass().getPackage().getName()); 51 | new AnnotationConfigApplicationContext(AppConfig.class); 52 | } catch (BeanCreationException e) { 53 | Throwable cause = e.getCause().getCause(); 54 | assertEquals(ResponseException.class, cause.getClass()); 55 | ResponseException responseException = (ResponseException) cause; 56 | assertThat(responseException.getResponse().getStatusLine().getStatusCode(), is(400)); 57 | throw e; 58 | } 59 | }); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/multipleclients/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.multipleclients; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | 27 | import static fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig.enrichFactoryWithNodeSettings; 28 | 29 | @Configuration 30 | public class AppConfig { 31 | 32 | @Bean 33 | public ElasticsearchClient esClient() throws Exception { 34 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 35 | enrichFactoryWithNodeSettings(factory); 36 | factory.setClasspathRoot("/models/root/multiple-clients/client1"); 37 | factory.setForceIndex(false); 38 | factory.afterPropertiesSet(); 39 | return factory.getObject(); 40 | } 41 | 42 | @Bean 43 | public ElasticsearchClient esClient2() throws Exception { 44 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 45 | enrichFactoryWithNodeSettings(factory); 46 | factory.setClasspathRoot("/models/root/multiple-clients/client2"); 47 | factory.setMergeSettings(true); 48 | factory.afterPropertiesSet(); 49 | return factory.getObject(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/multipleclients/MultipleClientsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.multipleclients; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | 25 | import java.io.IOException; 26 | 27 | public class MultipleClientsTest extends AbstractRestAnnotationContextModel { 28 | 29 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 30 | ElasticsearchClient client2 = checkClient("esClient2"); 31 | // We test how many shards and replica we have 32 | // Let's do the same thing with the second client 33 | // We test how many shards and replica we have 34 | // We don't expect the number of replicas to be 4 as we won't merge _update_settings.json 35 | // See #31: https://github.com/dadoonet/spring-elasticsearch/issues/31 36 | assertShardsAndReplicas(client2, "twitter", 1, 1); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/pipelines/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.pipelines; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/models/root/pipelines"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/pipelines/PipelinesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.pipelines; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | import org.elasticsearch.client.Request; 25 | import org.elasticsearch.client.ResponseException; 26 | import org.elasticsearch.client.RestClient; 27 | 28 | import java.io.IOException; 29 | 30 | import static org.hamcrest.MatcherAssert.assertThat; 31 | import static org.hamcrest.Matchers.notNullValue; 32 | 33 | 34 | public class PipelinesTest extends AbstractRestAnnotationContextModel { 35 | 36 | @Override 37 | protected void executeBefore(RestClient client) throws IOException { 38 | try { 39 | client.performRequest(new Request("DELETE", "/_pipeline/pipeline1")); 40 | } catch (ResponseException ignored) { } 41 | } 42 | 43 | @Override 44 | protected String indexName() { 45 | return null; 46 | } 47 | 48 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 49 | assertThat(client.ingest().getPipeline(gpr -> gpr.id("pipeline1")).get("pipeline1"), notNullValue()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/settings13/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.settings13; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/models/root/settings-13/client"); 32 | factory.setForceIndex(true); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/settings13/Settings13Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.settings13; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | 25 | import java.io.IOException; 26 | import java.util.Collections; 27 | import java.util.List; 28 | 29 | 30 | public class Settings13Test extends AbstractRestAnnotationContextModel { 31 | 32 | @Override 33 | protected List otherTestIndices() { 34 | return Collections.singletonList("rss"); 35 | } 36 | 37 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 38 | assertShardsAndReplicas(client, "rss", 1, 1); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/settingsfailed/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.settingsfailed; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | 27 | import static fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig.enrichFactoryWithNodeSettings; 28 | 29 | @Configuration 30 | public class AppConfig { 31 | 32 | @Bean 33 | public ElasticsearchClient esClient() throws Exception { 34 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 35 | enrichFactoryWithNodeSettings(factory); 36 | factory.setClasspathRoot("/models/root/settings-failed/client1"); 37 | factory.setForceIndex(false); 38 | factory.afterPropertiesSet(); 39 | return factory.getObject(); 40 | } 41 | 42 | @Bean 43 | public ElasticsearchClient esClient2() throws Exception { 44 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 45 | enrichFactoryWithNodeSettings(factory); 46 | factory.setClasspathRoot("/models/root/settings-failed/client2"); 47 | factory.setMergeSettings(true); 48 | factory.afterPropertiesSet(); 49 | return factory.getObject(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/settingsfailed/SettingsFailedTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.settingsfailed; 21 | 22 | import fr.pilato.spring.elasticsearch.it.BaseTest; 23 | import org.elasticsearch.client.ResponseException; 24 | import org.junit.jupiter.api.Test; 25 | import org.springframework.beans.factory.BeanCreationException; 26 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 27 | 28 | import static org.hamcrest.MatcherAssert.assertThat; 29 | import static org.hamcrest.Matchers.containsString; 30 | import static org.hamcrest.Matchers.is; 31 | import static org.junit.jupiter.api.Assertions.assertEquals; 32 | import static org.junit.jupiter.api.Assertions.assertThrows; 33 | 34 | /** 35 | * We try to merge non merging mapping. 36 | * An exception should be raised. 37 | * @author David Pilato aka dadoonet 38 | * 39 | */ 40 | public class SettingsFailedTest extends BaseTest { 41 | 42 | @Override 43 | public String indexName() { 44 | return null; 45 | } 46 | 47 | @Test 48 | void test_rest_client() { 49 | assertThrows(BeanCreationException.class, () -> { 50 | try { 51 | logger.info(" --> Starting Spring Context on [{}] classpath", this.getClass().getPackage().getName()); 52 | new AnnotationConfigApplicationContext(AppConfig.class); 53 | } catch (BeanCreationException e) { 54 | Throwable cause = e.getCause().getCause(); 55 | assertEquals(ResponseException.class, cause.getClass()); 56 | ResponseException responseException = (ResponseException) cause; 57 | assertThat(responseException.getResponse().getStatusLine().getStatusCode(), is(400)); 58 | assertThat(responseException.getMessage(), containsString("Can't update non dynamic settings")); 59 | throw e; 60 | } 61 | }); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/settingsnomapping21/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.settingsnomapping21; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/models/root/settings-no-mapping-21/client"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/settingsnomapping21/SettingsNoMapping21Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.settingsnomapping21; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 24 | 25 | import java.io.IOException; 26 | 27 | import static org.hamcrest.MatcherAssert.assertThat; 28 | import static org.hamcrest.Matchers.hasKey; 29 | 30 | 31 | public class SettingsNoMapping21Test extends AbstractRestAnnotationContextModel { 32 | 33 | protected void checkUseCaseSpecific(ElasticsearchClient client) throws IOException { 34 | // We should have an existing index here 35 | assertThat(client.indices().get(gir -> gir.index("twitter")).result(), hasKey("twitter")); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/shards/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.shards; 21 | 22 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 23 | import fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | @Configuration 27 | public class AppConfig extends RestAppConfig { 28 | 29 | @Override 30 | protected void enrichFactory(ElasticsearchClientFactoryBean factory) { 31 | factory.setClasspathRoot("/models/root/shards/client"); 32 | factory.setForceIndex(true); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/updatesettingsdisabled31/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.updatesettingsdisabled31; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | 27 | import static fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig.enrichFactoryWithNodeSettings; 28 | 29 | @Configuration 30 | public class AppConfig { 31 | 32 | @Bean 33 | public ElasticsearchClient esClient() throws Exception { 34 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 35 | enrichFactoryWithNodeSettings(factory); 36 | factory.setClasspathRoot("/models/root/update-settings-31/client1"); 37 | factory.afterPropertiesSet(); 38 | return factory.getObject(); 39 | } 40 | 41 | @Bean 42 | public ElasticsearchClient esClient2() throws Exception { 43 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 44 | enrichFactoryWithNodeSettings(factory); 45 | factory.setClasspathRoot("/models/root/update-settings-31/client2"); 46 | factory.setMergeSettings(false); 47 | factory.afterPropertiesSet(); 48 | return factory.getObject(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/updatesettingsdisabled31/UpdateSettingsDisabled31Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.updatesettingsdisabled31; 21 | 22 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 23 | 24 | public class UpdateSettingsDisabled31Test extends AbstractRestAnnotationContextModel { 25 | 26 | @Override 27 | protected int expectedShards() { 28 | return 2; 29 | } 30 | 31 | @Override 32 | protected int expectedReplicas() { 33 | return 0; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/updatesettingsenabled31/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.updatesettingsenabled31; 21 | 22 | import co.elastic.clients.elasticsearch.ElasticsearchClient; 23 | import fr.pilato.spring.elasticsearch.ElasticsearchClientFactoryBean; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | 27 | import static fr.pilato.spring.elasticsearch.it.annotation.rest.RestAppConfig.enrichFactoryWithNodeSettings; 28 | 29 | @Configuration 30 | public class AppConfig { 31 | 32 | @Bean 33 | public ElasticsearchClient esClient() throws Exception { 34 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 35 | enrichFactoryWithNodeSettings(factory); 36 | factory.setClasspathRoot("/models/root/update-settings-disabled-31/client1"); 37 | factory.afterPropertiesSet(); 38 | return factory.getObject(); 39 | } 40 | 41 | @Bean 42 | public ElasticsearchClient esClient2() throws Exception { 43 | ElasticsearchClientFactoryBean factory = new ElasticsearchClientFactoryBean(); 44 | enrichFactoryWithNodeSettings(factory); 45 | factory.setClasspathRoot("/models/root/update-settings-disabled-31/client2"); 46 | factory.setMergeSettings(true); 47 | factory.afterPropertiesSet(); 48 | return factory.getObject(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/it/annotation/rest/updatesettingsenabled31/UpdateSettings31Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to David Pilato (the "Author") under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. Author licenses this 6 | * file to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package fr.pilato.spring.elasticsearch.it.annotation.rest.updatesettingsenabled31; 21 | 22 | import fr.pilato.spring.elasticsearch.it.annotation.rest.AbstractRestAnnotationContextModel; 23 | 24 | public class UpdateSettings31Test extends AbstractRestAnnotationContextModel { 25 | 26 | @Override 27 | protected int expectedShards() { 28 | return 2; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/fr/pilato/spring/elasticsearch/unit/ClassPathReaderTest.java: -------------------------------------------------------------------------------- 1 | package fr.pilato.spring.elasticsearch.unit; 2 | 3 | import fr.pilato.elasticsearch.tools.util.SettingsReader; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static org.hamcrest.MatcherAssert.assertThat; 7 | import static org.hamcrest.Matchers.nullValue; 8 | import static org.hamcrest.Matchers.startsWith; 9 | 10 | class ClassPathReaderTest { 11 | 12 | @Test 13 | void testReadFileInClasspath_ExpectFileReadOk() { 14 | String url = "classpath-reader-test.txt"; 15 | String contents = SettingsReader.readFileFromClasspath(url); 16 | assertThat(contents, startsWith("This file is here for testing purposes")); 17 | } 18 | 19 | @Test 20 | void testReadFileInClasspath_ExpectFileNotFound_ReturnsNull() { 21 | String url = "__unknown_file_path_____"; 22 | String contents = SettingsReader.readFileFromClasspath(url); 23 | assertThat(contents, nullValue()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/resources/classpath-reader-test.txt: -------------------------------------------------------------------------------- 1 | This file is here for testing purposes. Please don't delete. :) -------------------------------------------------------------------------------- /src/test/resources/es/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": { 3 | "properties" : { 4 | "message" : {"type" : "text", "store" : true} 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/test/resources/models/root/aliases/_aliases.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions" : [ 3 | { "remove": { "index": "test_1", "alias": "test" } }, 4 | { "add": { "index": "test_2", "alias": "test" } } 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/test/resources/models/root/aliases/test_1/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": { 3 | "properties" : { 4 | "message" : {"type" : "text", "store" : true} 5 | } 6 | }, 7 | "aliases": { 8 | "test": { } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/models/root/aliases/test_2/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": { 3 | "properties" : { 4 | "message" : {"type" : "text", "store" : true} 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/models/root/aliases/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": { 3 | "properties" : { 4 | "message" : {"type" : "text", "store" : true} 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/models/root/custom-analyzers-12/client/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "analysis":{ 4 | "analyzer":{ 5 | "custom_uax_url_email":{ 6 | "type":"custom", 7 | "tokenizer" : "uax_url_email", 8 | "filter" : ["lowercase", "stop"] 9 | }, 10 | "francais":{ 11 | "type":"custom", 12 | "tokenizer":"standard", 13 | "filter":["lowercase", "stop_francais", "fr_stemmer", "asciifolding", "elision"] 14 | } 15 | }, 16 | "filter":{ 17 | "stop_francais":{ 18 | "type":"stop", 19 | "stopwords":["_french_"] 20 | }, 21 | "fr_stemmer" : { 22 | "type" : "stemmer", 23 | "language" : "french" 24 | } 25 | } 26 | } 27 | }, 28 | "mappings": { 29 | "properties" : { 30 | "message" : {"type" : "text", "store" : true, "analyzer": "francais"}, 31 | "author" : {"type" : "text", "store" : false, "analyzer": "custom_uax_url_email"} 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/resources/models/root/index-templates/client/_component_templates/component1.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": { 3 | "mappings": { 4 | "properties": { 5 | "@timestamp": { 6 | "type": "date" 7 | } 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/models/root/index-templates/client/_component_templates/component2.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": { 3 | "mappings": { 4 | "runtime": { 5 | "day_of_week": { 6 | "type": "keyword", 7 | "script": { 8 | "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))" 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/resources/models/root/index-templates/client/_index_templates/template_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_patterns": ["te*", "bar*"], 3 | "template": { 4 | "settings": { 5 | "number_of_shards": 1 6 | }, 7 | "mappings": { 8 | "_source": { 9 | "enabled": true 10 | }, 11 | "properties": { 12 | "host_name": { 13 | "type": "keyword" 14 | }, 15 | "created_at": { 16 | "type": "date", 17 | "format": "EEE MMM dd HH:mm:ss Z yyyy" 18 | } 19 | } 20 | }, 21 | "aliases": { 22 | "mydata": { } 23 | } 24 | }, 25 | "priority": 500, 26 | "composed_of": ["component1", "component2"], 27 | "version": 3, 28 | "_meta": { 29 | "description": "my custom" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/resources/models/root/index-with-type/client/twitter/_doc.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties" : { 3 | "message" : {"type" : "text", "store" : true} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/models/root/indices-already-exist-86/client/badindex/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings": { 3 | "number_of_shards" : 2, 4 | "number_of_replicas" : 2 5 | }, 6 | "mappings": { 7 | "properties" : { 8 | "foo" : {"type" : "text"} 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/models/root/indices-already-exist-86/client/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": { 3 | "properties" : { 4 | "message" : {"type" : "text", "store" : true} 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/models/root/lifecycles/_index_lifecycles/policy1.json: -------------------------------------------------------------------------------- 1 | { 2 | "policy": { 3 | "phases": { 4 | "warm": { 5 | "min_age": "10d", 6 | "actions": { 7 | "forcemerge": { 8 | "max_num_segments": 1 9 | } 10 | } 11 | }, 12 | "delete": { 13 | "min_age": "30d", 14 | "actions": { 15 | "delete": {} 16 | } 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/models/root/lifecycles/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "index.lifecycle.name": "policy1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/models/root/manual-settings/_aliases.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions" : [ 3 | { "add": { "index": "twitter", "alias": "alias" } } 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/models/root/manual-settings/_component_templates/component1.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": { 3 | "mappings": { 4 | "properties": { 5 | "@timestamp": { 6 | "type": "date" 7 | } 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/models/root/manual-settings/_component_templates/component2.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": { 3 | "mappings": { 4 | "runtime": { 5 | "day_of_week": { 6 | "type": "keyword", 7 | "script": { 8 | "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))" 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/resources/models/root/manual-settings/_index_templates/template_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_patterns": ["te*", "bar*"], 3 | "template": { 4 | "settings": { 5 | "number_of_shards": 1 6 | } 7 | }, 8 | "priority": 100, 9 | "composed_of": ["component1"], 10 | "version": 1, 11 | "_meta": { 12 | "description": "my custom" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/resources/models/root/manual-settings/_index_templates/template_2.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_patterns": ["te*", "bar*"], 3 | "template": { 4 | "settings": { 5 | "number_of_shards": 1 6 | } 7 | }, 8 | "priority": 100, 9 | "composed_of": ["component1"], 10 | "version": 1, 11 | "_meta": { 12 | "description": "my custom should be ignored" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/resources/models/root/manual-settings/_pipelines/pipeline1.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "My optional pipeline1 description", 3 | "processors": [ 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/models/root/manual-settings/_pipelines/pipeline2.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "My optional pipeline2 description", 3 | "processors": [ 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/models/root/manual-settings/foobar/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/test/resources/models/root/mapping-failed/client1/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": { 3 | "properties" : { 4 | "message" : {"type" : "text" } 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/models/root/mapping-failed/client2/twitter/_update_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": { 3 | "properties" : { 4 | "message" : {"type" : "date"} 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/models/root/mapping/client1/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "analysis":{ 4 | "analyzer":{ 5 | "francais":{ 6 | "type":"custom", 7 | "tokenizer":"standard", 8 | "filter":["lowercase", "stop_francais", "fr_stemmer", "asciifolding", "elision"] 9 | } 10 | }, 11 | "filter":{ 12 | "stop_francais":{ 13 | "type":"stop", 14 | "stopwords":["_french_"] 15 | }, 16 | "fr_stemmer" : { 17 | "type" : "stemmer", 18 | "language" : "french" 19 | } 20 | } 21 | } 22 | }, 23 | "mappings": { 24 | "properties" : { 25 | "message" : {"type" : "text", "store" : true, "analyzer" : "francais" } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/resources/models/root/mapping/client2/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "analysis":{ 4 | "analyzer":{ 5 | "francais":{ 6 | "type":"custom", 7 | "tokenizer":"standard", 8 | "filter":["lowercase", "stop_francais", "fr_stemmer", "asciifolding", "elision"] 9 | } 10 | }, 11 | "filter":{ 12 | "stop_francais":{ 13 | "type":"stop", 14 | "stopwords":["_french_"] 15 | }, 16 | "fr_stemmer" : { 17 | "type" : "stemmer", 18 | "language" : "french" 19 | } 20 | } 21 | } 22 | }, 23 | "mappings": { 24 | "properties" : { 25 | "message" : {"type" : "text", "store" : true, "analyzer" : "francais" }, 26 | "author" : {"type" : "text", "store" : false} 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/resources/models/root/multiple-clients/client1/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "analysis":{ 4 | "analyzer":{ 5 | "francais":{ 6 | "type":"custom", 7 | "tokenizer":"standard", 8 | "filter":["lowercase", "stop_francais", "fr_stemmer", "asciifolding", "elision"] 9 | } 10 | }, 11 | "filter":{ 12 | "stop_francais":{ 13 | "type":"stop", 14 | "stopwords":["_french_"] 15 | }, 16 | "fr_stemmer" : { 17 | "type" : "stemmer", 18 | "language" : "french" 19 | } 20 | } 21 | } 22 | }, 23 | "mappings": { 24 | "properties" : { 25 | "message" : {"type" : "text", "store" : true, "analyzer" : "francais" } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/resources/models/root/multiple-clients/client2/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "number_of_replicas" : 4, 4 | "analysis" : { 5 | "analyzer":{ 6 | "mysimple":{ 7 | "type":"simple" 8 | } 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/models/root/no-namespace/client/rss/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "analysis":{ 4 | "analyzer":{ 5 | "francais":{ 6 | "type":"custom", 7 | "tokenizer":"standard", 8 | "filter":["lowercase", "stop_francais", "fr_stemmer", "asciifolding", "elision"] 9 | } 10 | }, 11 | "filter":{ 12 | "stop_francais":{ 13 | "type":"stop", 14 | "stopwords":["_french_"] 15 | }, 16 | "fr_stemmer" : { 17 | "type" : "stemmer", 18 | "name" : "french" 19 | } 20 | } 21 | } 22 | }, 23 | "mappings": { 24 | "properties" : { 25 | "message" : {"type" : "text", "store" : true, "analyzer" : "francais" }, 26 | "author" : {"type" : "text", "store" : false} 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/resources/models/root/no-namespace/client/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "analysis":{ 4 | "analyzer":{ 5 | "francais":{ 6 | "type":"custom", 7 | "tokenizer":"standard", 8 | "filter":["lowercase", "stop_francais", "fr_stemmer", "asciifolding", "elision"] 9 | } 10 | }, 11 | "filter":{ 12 | "stop_francais":{ 13 | "type":"stop", 14 | "stopwords":["_french_"] 15 | }, 16 | "fr_stemmer" : { 17 | "type" : "stemmer", 18 | "name" : "french" 19 | } 20 | } 21 | } 22 | }, 23 | "mappings": { 24 | "properties" : { 25 | "message" : {"type" : "text", "store" : true, "analyzer" : "francais" }, 26 | "author" : {"type" : "text", "store" : false} 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/resources/models/root/pipelines/_pipelines/pipeline1.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "My optional pipeline description", 3 | "processors": [ 4 | { 5 | "set": { 6 | "description": "My optional processor description", 7 | "field": "my-long-field", 8 | "value": 10 9 | } 10 | }, 11 | { 12 | "set": { 13 | "description": "Set 'my-boolean-field' to true", 14 | "field": "my-boolean-field", 15 | "value": true 16 | } 17 | }, 18 | { 19 | "lowercase": { 20 | "field": "my-keyword-field" 21 | } 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/test/resources/models/root/plugins/client/twitter/_doc.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties" : { 3 | "message" : {"type" : "text", "store" : true, "analyzer" : "francais" }, 4 | "author" : {"type" : "text", "store" : false} 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/test/resources/models/root/plugins/client/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "analysis":{ 4 | "analyzer":{ 5 | "francais":{ 6 | "type":"custom", 7 | "tokenizer":"standard", 8 | "filter":["lowercase", "stop_francais", "fr_stemmer", "asciifolding", "elision"] 9 | } 10 | }, 11 | "filter":{ 12 | "stop_francais":{ 13 | "type":"stop", 14 | "stopwords":["_french_"] 15 | }, 16 | "fr_stemmer" : { 17 | "type" : "stemmer", 18 | "name" : "french" 19 | } 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/resources/models/root/rest-client-namespace/client/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": { 3 | "properties" : { 4 | "message" : {"type" : "text", "store" : true} 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/models/root/settings-13/client/rss/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "analysis":{ 4 | "analyzer":{ 5 | "francais":{ 6 | "type":"custom", 7 | "tokenizer":"standard", 8 | "filter":["lowercase", "stop_francais", "fr_stemmer", "asciifolding", "elision"] 9 | } 10 | }, 11 | "filter":{ 12 | "stop_francais":{ 13 | "type":"stop", 14 | "stopwords":["_french_"] 15 | }, 16 | "fr_stemmer" : { 17 | "type" : "stemmer", 18 | "language" : "french" 19 | } 20 | } 21 | } 22 | }, 23 | "mappings": { 24 | "properties" : { 25 | "message" : {"type" : "text", "store" : true, "analyzer" : "francais" }, 26 | "author" : {"type" : "text", "store" : false} 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/resources/models/root/settings-13/client/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "analysis":{ 4 | "analyzer":{ 5 | "francais":{ 6 | "type":"custom", 7 | "tokenizer":"standard", 8 | "filter":["lowercase", "stop_francais", "fr_stemmer", "asciifolding", "elision"] 9 | } 10 | }, 11 | "filter":{ 12 | "stop_francais":{ 13 | "type":"stop", 14 | "stopwords":["_french_"] 15 | }, 16 | "fr_stemmer" : { 17 | "type" : "stemmer", 18 | "language" : "french" 19 | } 20 | } 21 | } 22 | }, 23 | "mappings": { 24 | "properties" : { 25 | "message" : {"type" : "text", "store" : true, "analyzer" : "francais" }, 26 | "author" : {"type" : "text", "store" : false} 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/resources/models/root/settings-failed/client1/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "index" : { 4 | "number_of_shards" : 1 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/models/root/settings-failed/client2/twitter/_update_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "index" : { 3 | "number_of_shards" : 4 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/models/root/settings-no-mapping-21/client/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /src/test/resources/models/root/shards/client/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "number_of_shards" : 3, 4 | "number_of_replicas" : 2 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/test/resources/models/root/update-settings-31/client1/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "number_of_shards" : 2, 4 | "number_of_replicas" : 0 5 | }, 6 | "mappings": { 7 | "properties" : { 8 | "message" : {"type" : "text", "store" : true, "analyzer" : "simple" } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/models/root/update-settings-31/client2/twitter/_update_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "index" : { 3 | "number_of_replicas" : 1 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/models/root/update-settings-disabled-31/client1/twitter/_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings" : { 3 | "number_of_shards" : 2, 4 | "number_of_replicas" : 0 5 | }, 6 | "mappings": { 7 | "properties" : { 8 | "message" : {"type" : "text", "store" : true, "analyzer" : "simple" } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/models/root/update-settings-disabled-31/client2/twitter/_update_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "index" : { 3 | "number_of_replicas" : 1 4 | } 5 | } 6 | --------------------------------------------------------------------------------