├── .github ├── dependabot.yml └── workflows │ └── build.yml ├── .gitignore ├── .java-version ├── .travis.yml ├── .travis_after_success.sh ├── LICENSE ├── README.md ├── pom.xml └── src ├── main └── java │ └── io │ └── dropwizard │ └── elasticsearch │ ├── config │ └── EsConfiguration.java │ ├── health │ ├── EsClusterHealthCheck.java │ ├── EsIndexDocsHealthCheck.java │ └── EsIndexExistsHealthCheck.java │ ├── managed │ └── ManagedEsClient.java │ └── util │ └── TransportAddressHelper.java ├── site └── site.xml └── test ├── java └── io │ └── dropwizard │ └── elasticsearch │ ├── config │ └── EsConfigurationTest.java │ ├── health │ ├── EsClusterHealthCheckTest.java │ ├── EsIndexDocsHealthCheckTest.java │ └── EsIndexExistsHealthCheckTest.java │ ├── managed │ └── ManagedEsClientTest.java │ └── util │ └── TransportAddressHelperTest.java └── resources ├── custom_settings_file.yml ├── custom_settings_precedence.yml ├── elasticsearch.yml ├── elasticsearch_precedence.yml ├── invalid.yml ├── logback-test.xml ├── node_client.yml ├── transport_client.yml └── transport_client_with_empty_server_list.yml /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: github-actions 8 | directory: "/" 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | jobs: 4 | build: 5 | runs-on: ${{ matrix.os }} 6 | strategy: 7 | fail-fast: false 8 | matrix: 9 | java_version: ['8', '11', '15'] 10 | os: ['ubuntu-latest'] 11 | env: 12 | JAVA_OPTS: "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: Set up JDK 16 | uses: joschi/setup-jdk@v2.4.0 17 | with: 18 | java-version: ${{ matrix.java_version }} 19 | - uses: actions/cache@v3 20 | if: runner.os != 'Windows' 21 | with: 22 | path: ~/.m2 23 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} 24 | restore-keys: | 25 | ${{ runner.os }}-maven- 26 | - uses: actions/cache@v3 27 | if: runner.os == 'Windows' 28 | with: 29 | path: ~/.m2 30 | key: ${{ runner.os }}-maven-${{ hashFiles('**\pom.xml') }} 31 | restore-keys: | 32 | ${{ runner.os }}-maven- 33 | - name: Cache SonarCloud packages 34 | if: ${{ env.SONAR_TOKEN != null && env.SONAR_TOKEN != '' && matrix.java_version == '11' }} 35 | env: 36 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 37 | uses: actions/cache@v3 38 | with: 39 | path: ~/.sonar/cache 40 | key: ${{ runner.os }}-sonar 41 | restore-keys: ${{ runner.os }}-sonar 42 | - name: Build 43 | run: mvn -B -V -ntp install 44 | - name: Analyze with SonarCloud 45 | if: ${{ env.SONAR_TOKEN != null && env.SONAR_TOKEN != '' && matrix.java_version == '11' }} 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any 48 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 49 | run: mvn -B -V -ntp org.sonarsource.scanner.maven:sonar-maven-plugin:sonar 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.releaseBackup 3 | pom.xml.versionsBackup 4 | release.properties 5 | 6 | # IntelliJ IDEA 7 | *.iml 8 | *.ipr 9 | *.iws 10 | .idea/ 11 | out/ 12 | 13 | # Eclipse 14 | .settings/ 15 | .classpath 16 | .project 17 | -------------------------------------------------------------------------------- /.java-version: -------------------------------------------------------------------------------- 1 | 1.8 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: java 3 | after_success: 4 | - bash .travis_after_success.sh 5 | jdk: 6 | - openjdk8 7 | -------------------------------------------------------------------------------- /.travis_after_success.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "${TRAVIS_JDK_VERSION}" != "oraclejdk8" ]]; then 4 | echo "Skipping after_success actions for JDK version \"${TRAVIS_JDK_VERSION}\"" 5 | exit 6 | fi 7 | 8 | mvn -B jacoco:report coveralls:report 9 | -------------------------------------------------------------------------------- /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 2011 Coda Hale and Yammer, Inc. 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dropwizard Elasticsearch 2 | ======================== 3 | 4 | [![Build Status](https://travis-ci.org/dropwizard/dropwizard-elasticsearch.svg?branch=master)](https://travis-ci.org/dropwizard/dropwizard-elasticsearch) 5 | [![Coverage Status](https://img.shields.io/coveralls/dropwizard/dropwizard-elasticsearch.svg)](https://coveralls.io/r/dropwizard/dropwizard-elasticsearch) 6 | [![Maven Central](https://img.shields.io/maven-central/v/io.dropwizard.modules/dropwizard-elasticsearch.svg)](http://mvnrepository.com/artifact/io.dropwizard.modules/dropwizard-elasticsearch) 7 | 8 | A set of classes for using [Elasticsearch][1] (version 2.3.0 and higher) in a [Dropwizard][2] application. 9 | 10 | The package provides a [lifecycle-managed][3] client class (`ManagedEsClient`), a configuration class with the most 11 | common options (`EsConfiguration`), and some [health checks][4] which can instantly be used in any Dropwizard application. 12 | 13 | [1]: http://www.elasticsearch.org/ 14 | [2]: http://dropwizard.io/1.2.0/docs 15 | [3]: http://dropwizard.io/1.2.0/docs/manual/core.html#managed-objects 16 | [4]: http://dropwizard.io/1.2.0/docs/manual/core.html#health-checks 17 | 18 | 19 | Usage 20 | ----- 21 | 22 | Just add `EsConfiguration` to your [Configuration](http://dropwizard.io/1.2.0/docs/manual/core.html#configuration) class and 23 | create an `ManagedEsClient` instance in the run method of your service. 24 | 25 | You can also add one of the existing health checks to your [Environment](http://dropwizard.io/1.2.0/docs/manual/core.html#environments) 26 | in the same method. At least the usage of `EsClusterHealthCheck` is strongly advised. 27 | 28 | ```java 29 | public class DemoApplication extends Application { 30 | // [...] 31 | @Override 32 | public void run(DemoConfiguration config, Environment environment) { 33 | final ManagedEsClient managedClient = new ManagedEsClient(configuration.getEsConfiguration()); 34 | environment.lifecycle().manage(managedClient); 35 | environment.healthChecks().register("ES cluster health", new EsClusterHealthCheck(managedClient.getClient())); 36 | // [...] 37 | } 38 | } 39 | ``` 40 | 41 | Configuration 42 | ------------- 43 | 44 | The following configuration settings are supported by `EsConfiguration`: 45 | 46 | * `nodeClient`: When `true`, `ManagedEsClient` will create a `NodeClient`, otherwise a `TransportClient`; default: `true` 47 | * `servers`: A list of servers for usage with the created TransportClient if `nodeClient` is `false` 48 | * `clusterName`: The name of the Elasticsearch cluster; default: "elasticsearch" 49 | * `settings`: Any additional settings for Elasticsearch, see [Configuration](https://www.elastic.co/guide/en/elasticsearch/reference/2.4/setup-configuration.html) 50 | * `settingsFile`: Any additional settings file for Elasticsearch, see [Configuration](https://www.elastic.co/guide/en/elasticsearch/reference/2.4/setup-configuration.html) 51 | 52 | An example configuration file for creating a Node Client could like this: 53 | 54 | ```yaml 55 | clusterName: MyClusterName 56 | settings: 57 | node.name: MyCustomNodeName 58 | ``` 59 | 60 | The order of precedence is: `nodeClient`/`servers`/`clusterName` > `settings` > `settingsFile`, meaning that 61 | any setting in `settingsFile` can be overwritten with `settings` which in turn get overwritten by the specific settings 62 | like `clusterName`. 63 | 64 | Maven Artifacts 65 | --------------- 66 | 67 | This project is available on Maven Central. To add it to your project simply add the following dependencies to your 68 | `pom.xml`: 69 | ```xml 70 | 71 | io.dropwizard.modules 72 | dropwizard-elasticsearch 73 | 1.2.0-1 74 | 75 | ``` 76 | 77 | Support 78 | ------- 79 | 80 | Please file bug reports and feature requests in [GitHub issues](https://github.com/dropwizard/dropwizard-elasticsearch/issues). 81 | 82 | 83 | Acknowledgements 84 | ---------------- 85 | 86 | Thanks to Alexander Reelsen (@spinscale) for his [Dropwizard Blog Sample](https://github.com/spinscale/dropwizard-blog-sample) 87 | which sparked the idea for this project. 88 | 89 | 90 | License 91 | ------- 92 | 93 | Copyright (c) 2013-2017 Jochen Schalanda 94 | 95 | This library is licensed under the Apache License, Version 2.0. 96 | 97 | See http://www.apache.org/licenses/LICENSE-2.0.html or the LICENSE file in this repository for the full license text. 98 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | 3.0.0 7 | 8 | 9 | io.dropwizard.modules 10 | dropwizard-elasticsearch 11 | 1.2.0-2-SNAPSHOT 12 | jar 13 | 14 | Dropwizard Elasticsearch Bundle 15 | Addon bundle for Dropwizard to support Elasticsearch 16 | https://github.com/dropwizard/dropwizard-elasticsearch 17 | 18 | 19 | 20 | Apache 2.0 21 | http://www.apache.org/licenses/LICENSE-2.0.txt 22 | repo 23 | 24 | 25 | 26 | 27 | scm:git:git@github.com:dropwizard/dropwizard-elasticsearch.git 28 | scm:git:https://github.com/dropwizard/dropwizard-elasticsearch.git 29 | https://github.com/dropwizard/dropwizard-elasticsearch 30 | HEAD 31 | 32 | 33 | 34 | Travis CI 35 | https://travis-ci.org/dropwizard/dropwizard-elasticsearch 36 | 37 | 38 | 39 | GitHub Issues 40 | https://github.com/dropwizard/dropwizard-elasticsearch/issues 41 | 42 | 43 | 44 | 45 | ossrh 46 | https://s01.oss.sonatype.org/content/repositories/snapshots 47 | 48 | 49 | ossrh 50 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 51 | 52 | 53 | dropwizard-elasticsearch 54 | http://dropwizard.github.io/dropwizard-elasticsearch/${project.version} 55 | 56 | 57 | 58 | 59 | 60 | j.schalanda 61 | Jochen Schalanda 62 | jochen@schalanda.name 63 | 64 | 65 | 66 | 67 | UTF-8 68 | UTF-8 69 | 1.8 70 | 1.8 71 | dropwizard_dropwizard-elasticsearch 72 | dropwizard 73 | https://sonarcloud.io 74 | 1.3.16 75 | 2.4.6 76 | 77 | 78 | 79 | 80 | 81 | io.dropwizard 82 | dropwizard-bom 83 | ${dropwizard.version} 84 | pom 85 | import 86 | 87 | 88 | 89 | 90 | 91 | 92 | io.dropwizard 93 | dropwizard-core 94 | 95 | 96 | org.elasticsearch 97 | elasticsearch 98 | ${elasticsearch.version} 99 | 100 | 101 | junit 102 | junit 103 | 4.13.2 104 | test 105 | 106 | 107 | org.mockito 108 | mockito-core 109 | 4.9.0 110 | test 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | org.apache.maven.plugins 119 | maven-compiler-plugin 120 | 3.10.1 121 | 122 | 123 | org.apache.maven.plugins 124 | maven-source-plugin 125 | 3.2.1 126 | 127 | 128 | org.apache.maven.plugins 129 | maven-javadoc-plugin 130 | 3.4.1 131 | 132 | 133 | org.apache.maven.plugins 134 | maven-site-plugin 135 | 3.12.1 136 | 137 | 138 | org.apache.maven.plugins 139 | maven-clean-plugin 140 | 3.2.0 141 | 142 | 143 | org.apache.maven.plugins 144 | maven-deploy-plugin 145 | 3.0.0 146 | 147 | 148 | org.apache.maven.plugins 149 | maven-install-plugin 150 | 3.1.0 151 | 152 | 153 | org.apache.maven.plugins 154 | maven-jar-plugin 155 | 3.3.0 156 | 157 | 158 | org.apache.maven.plugins 159 | maven-resources-plugin 160 | 3.3.0 161 | 162 | 163 | org.apache.maven.plugins 164 | maven-surefire-plugin 165 | 2.22.2 166 | 167 | 168 | org.apache.maven.plugins 169 | maven-project-info-reports-plugin 170 | 3.4.1 171 | 172 | 173 | org.apache.maven.plugins 174 | maven-release-plugin 175 | 2.5.3 176 | 177 | 178 | org.apache.maven.plugins 179 | maven-gpg-plugin 180 | 3.0.1 181 | 182 | 183 | com.github.github 184 | site-maven-plugin 185 | 0.12 186 | 187 | 188 | org.jacoco 189 | jacoco-maven-plugin 190 | 0.8.8 191 | 192 | 193 | org.eluder.coveralls 194 | coveralls-maven-plugin 195 | 4.3.0 196 | 197 | 198 | org.sonarsource.scanner.maven 199 | sonar-maven-plugin 200 | 3.9.1.2184 201 | 202 | 203 | 204 | 205 | 206 | 207 | org.apache.maven.plugins 208 | maven-site-plugin 209 | 210 | true 211 | 212 | 213 | 214 | com.github.github 215 | site-maven-plugin 216 | 217 | ${project.version} 218 | Creating site for ${project.name} ${project.version} 219 | true 220 | true 221 | 222 | 223 | 224 | 225 | site 226 | 227 | site-deploy 228 | 229 | 230 | 231 | 232 | org.jacoco 233 | jacoco-maven-plugin 234 | 235 | 236 | prepare-agent 237 | 238 | prepare-agent 239 | 240 | 241 | 242 | 243 | 244 | org.eluder.coveralls 245 | coveralls-maven-plugin 246 | 247 | 248 | 249 | 250 | 251 | 252 | org.apache.maven.plugins 253 | maven-javadoc-plugin 254 | 255 | ${javadoc.doclint.none} 256 | public 257 | true 258 | 259 | 260 | 261 | html 262 | 263 | javadoc 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | java8-disable-strict-javadoc 274 | 275 | [1.8,) 276 | 277 | 278 | -Xdoclint:none 279 | 280 | 281 | 282 | release 283 | 284 | 285 | 286 | org.apache.maven.plugins 287 | maven-source-plugin 288 | 289 | 290 | attach-sources 291 | 292 | jar 293 | 294 | 295 | 296 | 297 | 298 | org.apache.maven.plugins 299 | maven-javadoc-plugin 300 | 301 | ${javadoc.doclint.none} 302 | 303 | 304 | 305 | attach-javadocs 306 | 307 | jar 308 | 309 | 310 | 311 | 312 | 313 | org.apache.maven.plugins 314 | maven-gpg-plugin 315 | 316 | 317 | sign-artifacts 318 | verify 319 | 320 | sign 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/elasticsearch/config/EsConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.config; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.google.common.net.HostAndPort; 6 | import io.dropwizard.validation.ValidationMethod; 7 | import org.hibernate.validator.constraints.NotEmpty; 8 | 9 | import javax.validation.constraints.NotNull; 10 | import java.util.Collections; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * Configuration class for Elasticsearch related settings. 16 | */ 17 | public class EsConfiguration { 18 | @JsonProperty 19 | @NotNull 20 | private List servers = Collections.emptyList(); 21 | 22 | @JsonProperty 23 | @NotEmpty 24 | private String clusterName = "elasticsearch"; 25 | 26 | @JsonProperty 27 | private boolean nodeClient = true; 28 | 29 | @JsonProperty 30 | @NotNull 31 | private Map settings = Collections.emptyMap(); 32 | 33 | @JsonProperty 34 | private String settingsFile = null; 35 | 36 | public List getServers() { 37 | return servers; 38 | } 39 | 40 | public String getClusterName() { 41 | return clusterName; 42 | } 43 | 44 | public boolean isNodeClient() { 45 | return nodeClient; 46 | } 47 | 48 | public Map getSettings() { 49 | return settings; 50 | } 51 | 52 | public String getSettingsFile() { 53 | return settingsFile; 54 | } 55 | 56 | @ValidationMethod 57 | @JsonIgnore 58 | public boolean isValidConfig() { 59 | return nodeClient || !servers.isEmpty(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheck.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.health; 2 | 3 | import com.codahale.metrics.health.HealthCheck; 4 | import org.elasticsearch.client.Client; 5 | import org.elasticsearch.cluster.health.ClusterHealthStatus; 6 | 7 | import static com.google.common.base.Preconditions.checkNotNull; 8 | 9 | /** 10 | * A {@link HealthCheck} which checks the cluster state of an Elasticsearch cluster. 11 | * 12 | * @see Admin Cluster Health 13 | */ 14 | public class EsClusterHealthCheck extends HealthCheck { 15 | private final Client client; 16 | private final boolean failOnYellow; 17 | 18 | /** 19 | * Construct a new Elasticsearch cluster health check. 20 | * 21 | * @param client an Elasticsearch {@link Client} instance connected to the cluster 22 | * @param failOnYellow whether the health check should fail if the cluster health state is yellow 23 | */ 24 | public EsClusterHealthCheck(Client client, boolean failOnYellow) { 25 | this.client = checkNotNull(client); 26 | this.failOnYellow = failOnYellow; 27 | } 28 | 29 | /** 30 | * Construct a new Elasticsearch cluster health check which will fail if the cluster health state is 31 | * {@link ClusterHealthStatus#RED}. 32 | * 33 | * @param client an Elasticsearch {@link Client} instance connected to the cluster 34 | */ 35 | public EsClusterHealthCheck(Client client) { 36 | this(client, false); 37 | } 38 | 39 | /** 40 | * Perform a check of the Elasticsearch cluster health. 41 | * 42 | * @return if the Elasticsearch cluster is healthy, a healthy {@link com.codahale.metrics.health.HealthCheck.Result}; 43 | * otherwise, an unhealthy {@link com.codahale.metrics.health.HealthCheck.Result} with a descriptive error 44 | * message or exception 45 | * @throws Exception if there is an unhandled error during the health check; this will result in 46 | * a failed health check 47 | */ 48 | @Override 49 | protected Result check() throws Exception { 50 | final ClusterHealthStatus status = client.admin().cluster().prepareHealth().get().getStatus(); 51 | 52 | if (status == ClusterHealthStatus.RED || (failOnYellow && status == ClusterHealthStatus.YELLOW)) { 53 | return Result.unhealthy("Last status: %s", status.name()); 54 | } else { 55 | return Result.healthy("Last status: %s", status.name()); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheck.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.health; 2 | 3 | import com.codahale.metrics.health.HealthCheck; 4 | import com.google.common.collect.ImmutableList; 5 | import org.elasticsearch.action.admin.indices.stats.IndexStats; 6 | import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; 7 | import org.elasticsearch.client.Client; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import static com.google.common.base.Preconditions.checkArgument; 13 | import static com.google.common.base.Preconditions.checkNotNull; 14 | 15 | /** 16 | * A {@link HealthCheck} which checks if one or more indices in Elasticsearch contain a given number of documents 17 | * in their primaries. 18 | * 19 | * @see Admin Indices Stats 20 | */ 21 | public class EsIndexDocsHealthCheck extends HealthCheck { 22 | private static final String HEALTH_CHECK_NAME = "elasticsearch-index-documents"; 23 | private static final long DEFAULT_DOCUMENT_THRESHOLD = 1L; 24 | private final Client client; 25 | private final String[] indices; 26 | private final long documentThreshold; 27 | 28 | /** 29 | * Construct a new Elasticsearch index document count health check. 30 | * 31 | * @param client an Elasticsearch {@link Client} instance connected to the cluster 32 | * @param indices a {@link List} of indices in Elasticsearch which should be checked 33 | * @param documentThreshold the minimal number of documents in an index 34 | * @throws IllegalArgumentException if {@code indices} was {@literal null} or empty, 35 | * or {@code documentThreshold} was less than 1 36 | */ 37 | public EsIndexDocsHealthCheck(Client client, List indices, long documentThreshold) { 38 | checkArgument(!indices.isEmpty(), "At least one index must be given"); 39 | checkArgument(documentThreshold > 0L, "The document threshold must at least be 1"); 40 | 41 | this.client = checkNotNull(client); 42 | this.indices = checkNotNull(indices.toArray(new String[indices.size()])); 43 | this.documentThreshold = documentThreshold; 44 | } 45 | 46 | 47 | /** 48 | * Construct a new Elasticsearch index document count health check. 49 | * 50 | * @param client an Elasticsearch {@link Client} instance connected to the cluster 51 | * @param indices a {@link List} of indices in Elasticsearch which should be checked 52 | */ 53 | public EsIndexDocsHealthCheck(Client client, List indices) { 54 | this(client, indices, DEFAULT_DOCUMENT_THRESHOLD); 55 | } 56 | 57 | /** 58 | * Construct a new Elasticsearch index document count health check. 59 | * 60 | * @param client an Elasticsearch {@link Client} instance connected to the cluster 61 | * @param indexName the index in Elasticsearch which should be checked 62 | * @param documentThreshold the minimal number of documents in an index 63 | */ 64 | public EsIndexDocsHealthCheck(Client client, String indexName, long documentThreshold) { 65 | this(client, ImmutableList.of(indexName), documentThreshold); 66 | } 67 | 68 | /** 69 | * Construct a new Elasticsearch index document count health check. 70 | * 71 | * @param client an Elasticsearch {@link Client} instance connected to the cluster 72 | * @param indexName the index in Elasticsearch which should be checked 73 | */ 74 | public EsIndexDocsHealthCheck(Client client, String indexName) { 75 | this(client, indexName, DEFAULT_DOCUMENT_THRESHOLD); 76 | } 77 | 78 | /** 79 | * Perform a check of the number of documents in the Elasticsearch indices. 80 | * 81 | * @return if the Elasticsearch indices contain the minimal number of documents, a healthy 82 | * {@link com.codahale.metrics.health.HealthCheck.Result}; otherwise, an unhealthy 83 | * {@link com.codahale.metrics.health.HealthCheck.Result} with a descriptive error message or exception 84 | * @throws Exception if there is an unhandled error during the health check; this will result in 85 | * a failed health check 86 | */ 87 | @Override 88 | protected Result check() throws Exception { 89 | final IndicesStatsResponse indicesStatsResponse = client.admin().indices().prepareStats(indices).get(); 90 | 91 | final List indexDetails = new ArrayList(indices.length); 92 | boolean healthy = true; 93 | 94 | for (IndexStats indexStats : indicesStatsResponse.getIndices().values()) { 95 | long documentCount = indexStats.getPrimaries().getDocs().getCount(); 96 | 97 | if (documentCount < documentThreshold) { 98 | healthy = false; 99 | indexDetails.add(String.format("%s (%d)", indexStats.getIndex(), documentCount)); 100 | } else { 101 | indexDetails.add(String.format("%s (%d!)", indexStats.getIndex(), documentCount)); 102 | } 103 | } 104 | 105 | final String resultDetails = String.format("Last stats: %s", indexDetails); 106 | 107 | if (healthy) { 108 | return Result.healthy(resultDetails); 109 | } else { 110 | return Result.unhealthy(resultDetails); 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheck.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.health; 2 | 3 | import com.codahale.metrics.health.HealthCheck; 4 | import com.google.common.collect.ImmutableList; 5 | import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; 6 | import org.elasticsearch.client.Client; 7 | 8 | import java.util.List; 9 | 10 | import static com.google.common.base.Preconditions.checkArgument; 11 | import static com.google.common.base.Preconditions.checkNotNull; 12 | 13 | /** 14 | * A {@link HealthCheck} which checks if one or more indices exist in Elasticsearch. 15 | * 16 | * @see Admin Indices Indices Exists 17 | */ 18 | public class EsIndexExistsHealthCheck extends HealthCheck { 19 | private final Client client; 20 | private final String[] indices; 21 | 22 | /** 23 | * Construct a new Elasticsearch index exists health check. 24 | * 25 | * @param client an Elasticsearch {@link Client} instance connected to the cluster 26 | * @param indices a {@link List} of indices in Elasticsearch which should be checked 27 | * @throws IllegalArgumentException if {@code indices} was {@literal null} or empty 28 | */ 29 | public EsIndexExistsHealthCheck(Client client, List indices) { 30 | checkArgument(!indices.isEmpty(), "At least one index must be given"); 31 | 32 | this.client = checkNotNull(client); 33 | this.indices = checkNotNull(indices.toArray(new String[indices.size()])); 34 | } 35 | 36 | /** 37 | * Construct a new Elasticsearch index exists health check. 38 | * 39 | * @param client an Elasticsearch {@link org.elasticsearch.client.Client} instance connected to the cluster 40 | * @param indexName the index in Elasticsearch which should be checked 41 | */ 42 | public EsIndexExistsHealthCheck(Client client, String indexName) { 43 | this(client, ImmutableList.of(indexName)); 44 | } 45 | 46 | /** 47 | * Perform a check of the number of documents in the Elasticsearch indices. 48 | * 49 | * @return if the Elasticsearch indices exist, a healthy {@link com.codahale.metrics.health.HealthCheck.Result}; 50 | * otherwise, an unhealthy {@link com.codahale.metrics.health.HealthCheck.Result} with a descriptive error 51 | * message or exception 52 | * @throws Exception if there is an unhandled error during the health check; this will result in 53 | * a failed health check 54 | */ 55 | @Override 56 | protected Result check() throws Exception { 57 | final IndicesExistsResponse indicesExistsResponse = client.admin().indices().prepareExists(indices).get(); 58 | 59 | if (indicesExistsResponse.isExists()) { 60 | return Result.healthy(); 61 | } else { 62 | return Result.unhealthy("One or more indices do not exist."); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/elasticsearch/managed/ManagedEsClient.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.managed; 2 | 3 | import com.google.common.io.Resources; 4 | import io.dropwizard.elasticsearch.config.EsConfiguration; 5 | import io.dropwizard.elasticsearch.util.TransportAddressHelper; 6 | import io.dropwizard.lifecycle.Managed; 7 | import org.elasticsearch.client.Client; 8 | import org.elasticsearch.client.transport.TransportClient; 9 | import org.elasticsearch.common.settings.Settings; 10 | import org.elasticsearch.common.transport.TransportAddress; 11 | import org.elasticsearch.node.Node; 12 | 13 | import java.io.File; 14 | import java.net.URISyntaxException; 15 | import java.net.URL; 16 | import java.nio.file.Path; 17 | import java.nio.file.Paths; 18 | 19 | import static com.google.common.base.Preconditions.checkNotNull; 20 | import static com.google.common.base.Strings.isNullOrEmpty; 21 | import static org.elasticsearch.node.NodeBuilder.nodeBuilder; 22 | 23 | /** 24 | * A Dropwizard managed Elasticsearch {@link Client}. Depending on the {@link EsConfiguration} a Node Client or 25 | * a {@link TransportClient} a is being created and its lifecycle is managed by Dropwizard. 26 | * 27 | * @see Node Client 28 | * @see Transport Client 29 | */ 30 | public class ManagedEsClient implements Managed { 31 | private Node node = null; 32 | private Client client = null; 33 | 34 | /** 35 | * Create a new managed Elasticsearch {@link Client}. If {@link EsConfiguration#nodeClient} is {@literal true}, a 36 | * Node Client is being created, otherwise a {@link TransportClient} is being created with {@link EsConfiguration#servers} 37 | * as transport addresses. 38 | * 39 | * @param config a valid {@link EsConfiguration} instance 40 | */ 41 | public ManagedEsClient(final EsConfiguration config) { 42 | checkNotNull(config, "EsConfiguration must not be null"); 43 | 44 | final Settings.Builder settingsBuilder = Settings.builder(); 45 | if (!isNullOrEmpty(config.getSettingsFile())) { 46 | Path path = Paths.get(config.getSettingsFile()); 47 | if (!path.toFile().exists()) { 48 | try { 49 | final URL url = Resources.getResource(config.getSettingsFile()); 50 | path = new File(url.toURI()).toPath(); 51 | } catch (URISyntaxException | NullPointerException e) { 52 | throw new IllegalArgumentException("settings file cannot be found", e); 53 | } 54 | } 55 | settingsBuilder.loadFromPath(path); 56 | } 57 | 58 | final Settings settings = settingsBuilder 59 | .put(config.getSettings()) 60 | .put("cluster.name", config.getClusterName()) 61 | .build(); 62 | 63 | if (config.isNodeClient()) { 64 | this.node = nodeBuilder() 65 | .client(true) 66 | .data(false) 67 | .settings(settings) 68 | .build(); 69 | this.client = this.node.client(); 70 | } else { 71 | final TransportAddress[] addresses = TransportAddressHelper.fromHostAndPorts(config.getServers()); 72 | this.client = TransportClient.builder().settings(settings).build().addTransportAddresses(addresses); 73 | } 74 | } 75 | 76 | /** 77 | * Create a new managed Elasticsearch {@link Client} from the provided {@link Node}. 78 | * 79 | * @param node a valid {@link Node} instance 80 | */ 81 | public ManagedEsClient(final Node node) { 82 | this.node = checkNotNull(node, "Elasticsearch node must not be null"); 83 | this.client = node.client(); 84 | } 85 | 86 | 87 | /** 88 | * Create a new managed Elasticsearch {@link Client} from the provided {@link Client}. 89 | * 90 | * @param client an initialized {@link Client} instance 91 | */ 92 | public ManagedEsClient(Client client) { 93 | this.client = checkNotNull(client, "Elasticsearch client must not be null"); 94 | } 95 | 96 | /** 97 | * Starts the Elasticsearch {@link Node} (if appropriate). Called before the service becomes available. 98 | * 99 | * @throws Exception if something goes wrong; this will halt the service startup. 100 | */ 101 | @Override 102 | public void start() throws Exception { 103 | startNode(); 104 | } 105 | 106 | /** 107 | * Stops the Elasticsearch {@link Client} and (if appropriate) {@link Node} objects. Called after the service 108 | * is no longer accepting requests. 109 | * 110 | * @throws Exception if something goes wrong. 111 | */ 112 | @Override 113 | public void stop() throws Exception { 114 | closeClient(); 115 | closeNode(); 116 | } 117 | 118 | /** 119 | * Get the managed Elasticsearch {@link Client} instance. 120 | * 121 | * @return a valid Elasticsearch {@link Client} instance 122 | */ 123 | public Client getClient() { 124 | return client; 125 | } 126 | 127 | private Node startNode() { 128 | if (null != node) { 129 | return node.start(); 130 | } 131 | 132 | return null; 133 | } 134 | 135 | private void closeNode() { 136 | if (null != node && !node.isClosed()) { 137 | node.close(); 138 | } 139 | } 140 | 141 | private void closeClient() { 142 | if (null != client) { 143 | client.close(); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/elasticsearch/util/TransportAddressHelper.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.util; 2 | 3 | import com.google.common.net.HostAndPort; 4 | import org.elasticsearch.common.transport.InetSocketTransportAddress; 5 | import org.elasticsearch.common.transport.TransportAddress; 6 | 7 | import java.net.InetSocketAddress; 8 | import java.util.List; 9 | 10 | /** 11 | * Helper class for converting Guava {@link HostAndPort} objects to Elasticsearch {@link TransportAddress}. 12 | */ 13 | public class TransportAddressHelper { 14 | private static final int DEFAULT_PORT = 9300; 15 | 16 | /** 17 | * Convert a {@link HostAndPort} instance to {@link TransportAddress}. If the {@link HostAndPort} instance doesn't 18 | * contain a port the resulting {@link TransportAddress} will have {@link #DEFAULT_PORT} as port. 19 | * 20 | * @param hostAndPort a valid {@link HostAndPort} instance 21 | * @return a {@link TransportAddress} equivalent to the provided {@link HostAndPort} instance 22 | */ 23 | public static TransportAddress fromHostAndPort(final HostAndPort hostAndPort) { 24 | InetSocketAddress address = new InetSocketAddress(hostAndPort.getHost(), hostAndPort.getPortOrDefault(DEFAULT_PORT)); 25 | return new InetSocketTransportAddress(address); 26 | } 27 | 28 | /** 29 | * Convert a list of {@link HostAndPort} instances to an array of {@link TransportAddress} instances. 30 | * 31 | * @param hostAndPorts a {@link List} of valid {@link HostAndPort} instances 32 | * @return an array of {@link TransportAddress} instances 33 | * @see #fromHostAndPort(com.google.common.net.HostAndPort) 34 | */ 35 | public static TransportAddress[] fromHostAndPorts(final List hostAndPorts) { 36 | if (hostAndPorts == null) { 37 | return new TransportAddress[0]; 38 | } else { 39 | TransportAddress[] transportAddresses = new TransportAddress[hostAndPorts.size()]; 40 | 41 | for (int i = 0; i < hostAndPorts.size(); i++) { 42 | transportAddresses[i] = fromHostAndPort(hostAndPorts.get(i)); 43 | } 44 | 45 | return transportAddresses; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | org.apache.maven.skins 6 | maven-fluido-skin 7 | 1.5 8 | 9 | 10 | 11 | 12 | dropwizard/dropwizard-elasticsearch 13 | right 14 | red 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/elasticsearch/config/EsConfigurationTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.config; 2 | 3 | import io.dropwizard.configuration.ConfigurationException; 4 | import io.dropwizard.configuration.ConfigurationFactory; 5 | import io.dropwizard.configuration.DefaultConfigurationFactoryFactory; 6 | import io.dropwizard.jackson.Jackson; 7 | import org.junit.Test; 8 | 9 | import javax.validation.Validation; 10 | import javax.validation.Validator; 11 | import java.io.File; 12 | import java.io.IOException; 13 | import java.net.URISyntaxException; 14 | import java.net.URL; 15 | 16 | /** 17 | * Unit tests for {@link EsConfiguration}. 18 | */ 19 | public class EsConfigurationTest { 20 | private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); 21 | private final ConfigurationFactory configFactory = 22 | new DefaultConfigurationFactoryFactory() 23 | .create(EsConfiguration.class, validator, Jackson.newObjectMapper(), "dw"); 24 | 25 | @Test 26 | public void defaultConfigShouldBeValid() throws IOException, ConfigurationException { 27 | configFactory.build(); 28 | } 29 | 30 | @Test(expected = ConfigurationException.class) 31 | public void eitherNodeClientOrServerListMustBeSet() throws IOException, ConfigurationException, URISyntaxException { 32 | URL configFileUrl = this.getClass().getResource("/invalid.yml"); 33 | File configFile = new File(configFileUrl.toURI()); 34 | configFactory.build(configFile); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheckTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.health; 2 | 3 | import org.elasticsearch.client.Client; 4 | import org.junit.Test; 5 | 6 | import static org.mockito.Mockito.mock; 7 | 8 | /** 9 | * Unit tests for {@link EsClusterHealthCheck} 10 | */ 11 | public class EsClusterHealthCheckTest { 12 | @Test(expected = NullPointerException.class) 13 | public void initializationWithNullClientShouldFail() { 14 | new EsClusterHealthCheck(null); 15 | } 16 | 17 | @Test 18 | public void initializationWithClientShouldSucceed() { 19 | new EsClusterHealthCheck(mock(Client.class)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheckTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.health; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import org.elasticsearch.client.Client; 5 | import org.junit.Test; 6 | 7 | import java.util.Collections; 8 | 9 | import static org.mockito.Mockito.mock; 10 | 11 | /** 12 | * Unit tests for {@link EsIndexDocsHealthCheck}. 13 | */ 14 | public class EsIndexDocsHealthCheckTest { 15 | @Test(expected = NullPointerException.class) 16 | public void initializationWithNullClientShouldFail() { 17 | new EsIndexDocsHealthCheck(null, "index"); 18 | } 19 | 20 | @Test(expected = IllegalArgumentException.class) 21 | public void initializationWithoutIndicesShouldFail() { 22 | new EsIndexDocsHealthCheck(mock(Client.class), Collections.emptyList()); 23 | } 24 | 25 | @Test(expected = NullPointerException.class) 26 | public void initializationWithoutIndexShouldFail() { 27 | new EsIndexDocsHealthCheck(mock(Client.class), (String) null); 28 | } 29 | 30 | @Test 31 | public void initializationWithClientAndIndicesShouldSucceed() { 32 | new EsIndexDocsHealthCheck(mock(Client.class), ImmutableList.of("index", "foobar")); 33 | } 34 | 35 | @Test 36 | public void initializationWithClientAndIndexShouldSucceed() { 37 | new EsIndexDocsHealthCheck(mock(Client.class), "index"); 38 | } 39 | 40 | @Test(expected = IllegalArgumentException.class) 41 | public void initializationWithDocumentThresholdTooLowShouldFail() { 42 | new EsIndexDocsHealthCheck(mock(Client.class), "index", 0L); 43 | } 44 | 45 | @Test 46 | public void initializationWithValidParametersShouldSucceedl() { 47 | new EsIndexDocsHealthCheck(mock(Client.class), "index", 10L); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheckTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.health; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import org.elasticsearch.client.Client; 5 | import org.junit.Test; 6 | 7 | import java.util.Collections; 8 | 9 | import static org.mockito.Mockito.mock; 10 | 11 | /** 12 | * Unit tests for {@link EsIndexExistsHealthCheck}. 13 | */ 14 | public class EsIndexExistsHealthCheckTest { 15 | @Test(expected = NullPointerException.class) 16 | public void initializationWithNullClientShouldFail() { 17 | new EsIndexExistsHealthCheck(null, "index"); 18 | } 19 | 20 | @Test(expected = IllegalArgumentException.class) 21 | public void initializationWithoutIndicesShouldFail() { 22 | new EsIndexExistsHealthCheck(mock(Client.class), Collections.emptyList()); 23 | } 24 | 25 | @Test(expected = NullPointerException.class) 26 | public void initializationWithoutIndexShouldFail() { 27 | new EsIndexExistsHealthCheck(mock(Client.class), (String) null); 28 | } 29 | 30 | @Test 31 | public void initializationWithClientAndIndexShouldSucceed() { 32 | new EsIndexExistsHealthCheck(mock(Client.class), "index"); 33 | } 34 | 35 | @Test 36 | public void initializationWithClientAndIndicesShouldSucceed() { 37 | new EsIndexExistsHealthCheck(mock(Client.class), ImmutableList.of("index", "foobar")); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/elasticsearch/managed/ManagedEsClientTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.managed; 2 | 3 | import com.google.common.net.HostAndPort; 4 | import io.dropwizard.configuration.ConfigurationException; 5 | import io.dropwizard.configuration.ConfigurationFactory; 6 | import io.dropwizard.configuration.DefaultConfigurationFactoryFactory; 7 | import io.dropwizard.elasticsearch.config.EsConfiguration; 8 | import io.dropwizard.elasticsearch.util.TransportAddressHelper; 9 | import io.dropwizard.jackson.Jackson; 10 | import io.dropwizard.lifecycle.Managed; 11 | import org.elasticsearch.client.Client; 12 | import org.elasticsearch.client.node.NodeClient; 13 | import org.elasticsearch.client.transport.TransportClient; 14 | import org.elasticsearch.node.Node; 15 | import org.junit.Test; 16 | 17 | import javax.validation.Validation; 18 | import javax.validation.Validator; 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.net.URISyntaxException; 22 | import java.net.URL; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | import static org.junit.Assert.assertNotNull; 26 | import static org.junit.Assert.assertSame; 27 | import static org.junit.Assert.assertTrue; 28 | import static org.mockito.Mockito.mock; 29 | import static org.mockito.Mockito.verify; 30 | import static org.mockito.Mockito.when; 31 | 32 | /** 33 | * Unit tests for {@link ManagedEsClient}. 34 | */ 35 | public class ManagedEsClientTest { 36 | private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); 37 | private final ConfigurationFactory configFactory = 38 | new DefaultConfigurationFactoryFactory() 39 | .create(EsConfiguration.class, validator, Jackson.newObjectMapper(), "dw"); 40 | 41 | @Test(expected = NullPointerException.class) 42 | public void ensureEsConfigurationIsNotNull() { 43 | new ManagedEsClient((EsConfiguration) null); 44 | } 45 | 46 | @Test(expected = NullPointerException.class) 47 | public void ensureNodeIsNotNull() { 48 | new ManagedEsClient((Node) null); 49 | } 50 | 51 | @Test(expected = NullPointerException.class) 52 | public void ensureClientIsNotNull() { 53 | new ManagedEsClient((Client) null); 54 | } 55 | 56 | @Test 57 | public void stopShouldCloseTheClient() throws Exception { 58 | Client client = mock(Client.class); 59 | Managed managed = new ManagedEsClient(client); 60 | 61 | managed.start(); 62 | managed.stop(); 63 | 64 | verify(client).close(); 65 | } 66 | 67 | @Test 68 | public void lifecycleMethodsShouldStartAndCloseTheNode() throws Exception { 69 | Node node = mock(Node.class); 70 | when(node.isClosed()).thenReturn(false); 71 | Managed managed = new ManagedEsClient(node); 72 | 73 | managed.start(); 74 | verify(node).start(); 75 | 76 | managed.stop(); 77 | verify(node).close(); 78 | } 79 | 80 | @Test 81 | public void managedEsClientWithNodeShouldReturnClient() throws Exception { 82 | Client client = mock(Client.class); 83 | Node node = mock(Node.class); 84 | when(node.client()).thenReturn(client); 85 | 86 | ManagedEsClient managed = new ManagedEsClient(node); 87 | 88 | assertSame(client, managed.getClient()); 89 | } 90 | 91 | @Test 92 | public void nodeClientShouldBeCreatedFromConfig() throws URISyntaxException, IOException, ConfigurationException { 93 | URL configFileUrl = this.getClass().getResource("/node_client.yml"); 94 | File configFile = new File(configFileUrl.toURI()); 95 | EsConfiguration config = configFactory.build(configFile); 96 | 97 | ManagedEsClient managedEsClient = new ManagedEsClient(config); 98 | Client client = managedEsClient.getClient(); 99 | 100 | assertNotNull(client); 101 | assertTrue(client instanceof NodeClient); 102 | 103 | NodeClient nodeClient = (NodeClient) client; 104 | assertEquals(config.getClusterName(), nodeClient.settings().get("cluster.name")); 105 | assertEquals("true", nodeClient.settings().get("node.client")); 106 | assertEquals("false", nodeClient.settings().get("node.data")); 107 | } 108 | 109 | @Test 110 | public void transportClientShouldBeCreatedFromConfig() throws URISyntaxException, IOException, ConfigurationException { 111 | URL configFileUrl = this.getClass().getResource("/transport_client.yml"); 112 | File configFile = new File(configFileUrl.toURI()); 113 | EsConfiguration config = configFactory.build(configFile); 114 | 115 | ManagedEsClient managedEsClient = new ManagedEsClient(config); 116 | Client client = managedEsClient.getClient(); 117 | 118 | assertNotNull(client); 119 | assertTrue(client instanceof TransportClient); 120 | 121 | final TransportClient transportClient = (TransportClient) client; 122 | assertEquals(3, transportClient.transportAddresses().size()); 123 | assertEquals( 124 | TransportAddressHelper.fromHostAndPort(HostAndPort.fromParts("127.0.0.1", 9300)), 125 | transportClient.transportAddresses().get(0)); 126 | assertEquals( 127 | TransportAddressHelper.fromHostAndPort(HostAndPort.fromParts("127.0.0.1", 9301)), 128 | transportClient.transportAddresses().get(1)); 129 | assertEquals( 130 | TransportAddressHelper.fromHostAndPort(HostAndPort.fromParts("127.0.0.1", 9302)), 131 | transportClient.transportAddresses().get(2)); 132 | } 133 | 134 | @Test 135 | public void managedClientShouldUseCustomElasticsearchConfig() throws URISyntaxException, IOException, ConfigurationException { 136 | URL configFileUrl = this.getClass().getResource("/custom_settings_file.yml"); 137 | File configFile = new File(configFileUrl.toURI()); 138 | EsConfiguration config = configFactory.build(configFile); 139 | 140 | ManagedEsClient managedEsClient = new ManagedEsClient(config); 141 | Client client = managedEsClient.getClient(); 142 | 143 | assertNotNull(client); 144 | assertTrue(client instanceof NodeClient); 145 | 146 | NodeClient nodeClient = (NodeClient) client; 147 | assertEquals(config.getClusterName(), nodeClient.settings().get("cluster.name")); 148 | assertEquals("19300-19400", nodeClient.settings().get("transport.tcp.port")); 149 | } 150 | 151 | @Test 152 | public void managedClientObeysPrecedenceOfSettings() throws URISyntaxException, IOException, ConfigurationException { 153 | URL configFileUrl = this.getClass().getResource("/custom_settings_precedence.yml"); 154 | File configFile = new File(configFileUrl.toURI()); 155 | EsConfiguration config = configFactory.build(configFile); 156 | 157 | ManagedEsClient managedEsClient = new ManagedEsClient(config); 158 | Client client = managedEsClient.getClient(); 159 | 160 | assertNotNull(client); 161 | assertTrue(client instanceof NodeClient); 162 | 163 | NodeClient nodeClient = (NodeClient) client; 164 | assertEquals(config.getClusterName(), nodeClient.settings().get("cluster.name")); 165 | assertEquals("29300-29400", nodeClient.settings().get("transport.tcp.port")); 166 | assertEquals("target/data/yaml", nodeClient.settings().get("path.home")); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/elasticsearch/util/TransportAddressHelperTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.elasticsearch.util; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.google.common.net.HostAndPort; 5 | import org.elasticsearch.common.transport.InetSocketTransportAddress; 6 | import org.elasticsearch.common.transport.TransportAddress; 7 | import org.junit.Test; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | import static org.junit.Assert.assertEquals; 13 | 14 | /** 15 | * Unit tests for {@link TransportAddressHelper}. 16 | */ 17 | public class TransportAddressHelperTest { 18 | 19 | private static final int ES_DEFAULT_PORT = 9300; 20 | 21 | @Test(expected = NullPointerException.class) 22 | public void fromHostAndPortWithNullShouldFail() { 23 | TransportAddressHelper.fromHostAndPort(null); 24 | } 25 | 26 | @Test 27 | public void fromHostAndPortsWithNullShouldReturnEmptyArray() { 28 | TransportAddress[] result = TransportAddressHelper.fromHostAndPorts(null); 29 | 30 | assertEquals(0, result.length); 31 | } 32 | 33 | @Test 34 | public void fromHostAndPortsWithEmptyListShouldReturnEmptyArray() { 35 | TransportAddress[] result = TransportAddressHelper.fromHostAndPorts(Collections.emptyList()); 36 | 37 | assertEquals(0, result.length); 38 | } 39 | 40 | @Test 41 | public void fromHostAndPortWithoutPortShouldUseDefaultPort() { 42 | InetSocketTransportAddress result = (InetSocketTransportAddress) TransportAddressHelper 43 | .fromHostAndPort(HostAndPort.fromString("localhost")); 44 | 45 | assertEquals("localhost", result.address().getHostName()); 46 | assertEquals(ES_DEFAULT_PORT, result.address().getPort()); 47 | } 48 | 49 | @Test 50 | public void fromHostAndPortWithCorrectDataShouldSucceed() { 51 | InetSocketTransportAddress result = (InetSocketTransportAddress) TransportAddressHelper 52 | .fromHostAndPort(HostAndPort.fromParts("localhost", 1234)); 53 | 54 | assertEquals("localhost", result.address().getHostName()); 55 | assertEquals(1234, result.address().getPort()); 56 | } 57 | 58 | @Test 59 | public void fromHostAndPostWithCorrectDataShouldSucceed() { 60 | final List hostAndPorts = ImmutableList.of( 61 | HostAndPort.fromParts("example.net", 1234), 62 | HostAndPort.fromParts("example.com", 5678), 63 | HostAndPort.fromString("example.org") 64 | ); 65 | final TransportAddress[] result = TransportAddressHelper.fromHostAndPorts(hostAndPorts); 66 | 67 | assertEquals(3, result.length); 68 | 69 | for (int i = 0; i < result.length; i++) { 70 | final InetSocketTransportAddress transportAddress = (InetSocketTransportAddress) result[i]; 71 | assertEquals(hostAndPorts.get(i).getHost(), transportAddress.address().getHostName()); 72 | assertEquals(hostAndPorts.get(i).getPortOrDefault(ES_DEFAULT_PORT), transportAddress.address().getPort()); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/resources/custom_settings_file.yml: -------------------------------------------------------------------------------- 1 | clusterName: dropwizard_elasticsearch_test 2 | settingsFile: elasticsearch.yml -------------------------------------------------------------------------------- /src/test/resources/custom_settings_precedence.yml: -------------------------------------------------------------------------------- 1 | clusterName: dropwizard_elasticsearch_test 2 | settingsFile: elasticsearch_precedence.yml 3 | settings: 4 | cluster.name: settingsYaml 5 | transport.tcp.port: 29300-29400 6 | path.home: "target/data/yaml" -------------------------------------------------------------------------------- /src/test/resources/elasticsearch.yml: -------------------------------------------------------------------------------- 1 | transport.tcp.port: 19300-19400 2 | path.home: "target/data" -------------------------------------------------------------------------------- /src/test/resources/elasticsearch_precedence.yml: -------------------------------------------------------------------------------- 1 | cluster.name: settingsFile 2 | transport.tcp.port: 19300-19400 3 | path.home: "target/data/settings" -------------------------------------------------------------------------------- /src/test/resources/invalid.yml: -------------------------------------------------------------------------------- 1 | nodeClient: false -------------------------------------------------------------------------------- /src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/test/resources/node_client.yml: -------------------------------------------------------------------------------- 1 | clusterName: dropwizard_elasticsearch_test 2 | settings: 3 | path.home: "target/data" -------------------------------------------------------------------------------- /src/test/resources/transport_client.yml: -------------------------------------------------------------------------------- 1 | nodeClient: false 2 | clusterName: dropwizard_elasticsearch_test 3 | servers: 4 | - 127.0.0.1 5 | - 127.0.0.1:9301 6 | - 127.0.0.1:9302 -------------------------------------------------------------------------------- /src/test/resources/transport_client_with_empty_server_list.yml: -------------------------------------------------------------------------------- 1 | nodeClient: false 2 | clusterName: dropwizard_elasticsearch_test --------------------------------------------------------------------------------