├── elasticsearch
├── src
│ ├── test
│ │ ├── resources
│ │ │ ├── application.properties
│ │ │ └── logback.xml
│ │ └── groovy
│ │ │ └── io
│ │ │ └── micronaut
│ │ │ └── elasticsearch
│ │ │ ├── ElasticsearchAuthorizationSpec.groovy
│ │ │ ├── health
│ │ │ └── ElasticsearchClientHealthIndicatorSpec.groovy
│ │ │ ├── ElasticsearchMappingSpec.groovy
│ │ │ └── DefaultElasticsearchConfigurationPropertiesSpec.groovy
│ └── main
│ │ └── java
│ │ └── io
│ │ └── micronaut
│ │ └── elasticsearch
│ │ ├── convert
│ │ ├── package-info.java
│ │ ├── StringToHttpHostConverter.java
│ │ ├── StringToHeaderConverter.java
│ │ ├── StringToNodeSelectorConverter.java
│ │ └── StringToInetAddressConverter.java
│ │ ├── conditon
│ │ ├── package-info.java
│ │ └── RequiresElasticsearch.java
│ │ ├── package-info.java
│ │ ├── ElasticsearchSettings.java
│ │ ├── DefaultHttpAsyncClientBuilderFactory.java
│ │ ├── DefaultElasticsearchConfiguration.java
│ │ ├── DefaultElasticsearchConfigurationProperties.java
│ │ ├── DefaultElasticsearchClientFactory.java
│ │ └── health
│ │ └── ElasticsearchClientHealthIndicator.java
└── build.gradle.kts
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── license.gradle
└── libs.versions.toml
├── src
└── main
│ └── docs
│ └── guide
│ ├── repository.adoc
│ ├── releaseHistory.adoc
│ ├── toc.yml
│ ├── introduction.adoc
│ ├── graalvm.adoc
│ ├── healthChecks.adoc
│ └── configuration.adoc
├── .github
├── ISSUE_TEMPLATE
│ ├── other.yaml
│ ├── new_feature.yaml
│ ├── config.yml
│ └── bug_report.yaml
├── renovate.json
├── release.yml
├── workflows
│ ├── publish-snapshot.yml
│ ├── central-sync.yml
│ ├── graalvm-latest.yml
│ ├── graalvm-dev.yml
│ ├── gradle.yml
│ └── release.yml
└── instructions
│ ├── docs.instructions.md
│ └── coding.instructions.md
├── test-suite-java
├── src
│ └── test
│ │ ├── java
│ │ └── micronaut
│ │ │ └── example
│ │ │ ├── service
│ │ │ ├── MovieService.java
│ │ │ ├── Movie.java
│ │ │ └── MovieServiceImpl.java
│ │ │ ├── exception
│ │ │ └── MovieServiceException.java
│ │ │ └── ElasticSearchTest.java
│ │ └── resources
│ │ ├── application.yml
│ │ └── logback.xml
└── build.gradle
├── elasticsearch-bom
└── build.gradle.kts
├── gradle.properties
├── config
├── checkstyle
│ ├── suppressions.xml
│ └── checkstyle.xml
├── HEADER
└── spotless.license.java
├── .gitattributes
├── test-suite-groovy
├── src
│ └── test
│ │ ├── resources
│ │ └── logback.xml
│ │ └── groovy
│ │ └── io
│ │ └── micronaut
│ │ └── docs
│ │ └── configuration
│ │ └── elasticsearch
│ │ └── ElasticsearchSpec.groovy
└── build.gradle.kts
├── .editorconfig
├── .clineignore
├── settings.gradle
├── SECURITY.md
├── .gitignore
├── ISSUE_TEMPLATE.md
├── README.md
├── .clinerules
├── docs.md
└── coding.md
├── gradlew.bat
├── CONTRIBUTING.md
├── gradlew
├── LICENSE
└── MAINTAINING.md
/elasticsearch/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | elasticsearch.httpHosts=http://localhost:9200,http://127.0.0.1:9200
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/micronaut-projects/micronaut-elasticsearch/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/src/main/docs/guide/repository.adoc:
--------------------------------------------------------------------------------
1 | You can find the source code of this project in this repository:
2 |
3 | https://github.com/{githubSlug}[https://github.com/{githubSlug}]
--------------------------------------------------------------------------------
/src/main/docs/guide/releaseHistory.adoc:
--------------------------------------------------------------------------------
1 | For this project, you can find a list of releases (with release notes) here:
2 |
3 | https://github.com/{githubSlug}/releases[https://github.com/{githubSlug}/releases]
4 |
--------------------------------------------------------------------------------
/src/main/docs/guide/toc.yml:
--------------------------------------------------------------------------------
1 | introduction:
2 | title: Introduction
3 | releaseHistory: Release History
4 | configuration: Configuration
5 | healthChecks: Health Checks
6 | graalvm: GraalVM Support
7 | repository: Repository
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/other.yaml:
--------------------------------------------------------------------------------
1 | name: Other
2 | description: Something different
3 | body:
4 | - type: textarea
5 | attributes:
6 | label: Issue description
7 | validations:
8 | required: true
9 |
10 |
--------------------------------------------------------------------------------
/src/main/docs/guide/introduction.adoc:
--------------------------------------------------------------------------------
1 | Micronaut supports automatic configuration of Elasticsearch https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html[ElasticsearchClient^] via the `elasticsearch` module.
2 |
3 |
--------------------------------------------------------------------------------
/test-suite-java/src/test/java/micronaut/example/service/MovieService.java:
--------------------------------------------------------------------------------
1 | package micronaut.example.service;
2 |
3 |
4 | public interface MovieService {
5 |
6 | String saveMovie(Movie movie);
7 |
8 | Movie searchMovies(String title);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/docs/guide/graalvm.adoc:
--------------------------------------------------------------------------------
1 |
2 | Micronaut Elasticsearch is compatible with https://www.graalvm.org/[GraalVM] out of the box.
3 |
4 | NOTE: See the section on https://docs.micronaut.io/latest/guide/index.html#graal[GraalVM] in the user guide for more
5 | information.
6 |
--------------------------------------------------------------------------------
/test-suite-java/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | micronaut:
2 | application:
3 | name: micronaut-elasticsearch-graal
4 | elasticsearch:
5 | indexes:
6 | movies: micronaut.movies
7 | test-resources:
8 | containers:
9 | elasticsearch:
10 | startup-timeout: 300s
11 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/test-suite-java/src/test/java/micronaut/example/exception/MovieServiceException.java:
--------------------------------------------------------------------------------
1 | package micronaut.example.exception;
2 |
3 | public class MovieServiceException extends RuntimeException {
4 |
5 | public MovieServiceException(String message, Throwable cause) {
6 | super(message, cause);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/elasticsearch-bom/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("io.micronaut.build.internal.bom")
3 | }
4 | micronautBuild {
5 | micronautBuild {
6 | // required because elasticsearch-rest-high-level-client was removed
7 | tasks.named("checkVersionCatalogCompatibility") { onlyIf { false } }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | projectVersion=6.0.0-SNAPSHOT
2 | projectGroup=io.micronaut.elasticsearch
3 | title=Micronaut Elasticsearch
4 | projectDesc=Integration between Micronaut and Elasticsearch
5 | projectUrl=https://micronaut.io
6 | githubSlug=micronaut-projects/micronaut-elasticsearch
7 | developers=Puneet Behl
8 | testsuite=test-suite/src/test/groovy/io/micronaut/docs
9 | org.gradle.caching=true
10 | org.gradle.jvmargs=-Xmx1g
11 |
--------------------------------------------------------------------------------
/config/checkstyle/suppressions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/elasticsearch/src/test/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | %d{HH:mm:ss.SSS} %-5level [%thread] %logger{25} [%file:%line] - %msg%n
7 | UTF-8
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/new_feature.yaml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Create a new feature request
3 | body:
4 | - type: markdown
5 | attributes:
6 | value: |
7 | Please describe the feature you want for Micronaut to implement, before that check if there is already an existing issue to add it.
8 | - type: textarea
9 | attributes:
10 | label: Feature description
11 | placeholder: Tell us what feature you would like for Micronaut to have and what problem is it going to solve
12 | validations:
13 | required: true
14 |
15 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | *.java text eol=lf
5 | *.groovy text eol=lf
6 | *.html text eol=lf
7 | *.kt text eol=lf
8 | *.kts text eol=lf
9 | *.md text diff=markdown eol=lf
10 | *.py text diff=python executable
11 | *.pl text diff=perl executable
12 | *.pm text diff=perl
13 | *.css text diff=css eol=lf
14 | *.js text eol=lf
15 | *.sql text eol=lf
16 | *.q text eol=lf
17 |
18 | *.sh text eol=lf
19 | gradlew text eol=lf
20 |
21 | *.bat text eol=crlf
22 | *.cmd text eol=crlf
23 |
--------------------------------------------------------------------------------
/test-suite-groovy/src/test/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | trim_trailing_whitespace = true
5 | insert_final_newline = true
6 | charset = utf-8
7 | indent_style = space
8 |
9 | [{*.sh,gradlew}]
10 | end_of_line = lf
11 |
12 | [{*.bat,*.cmd}]
13 | end_of_line = crlf
14 |
15 | [{*.mustache,*.ftl}]
16 | insert_final_newline = false
17 |
18 | [*.java]
19 | indent_size = 4
20 | tab_width = 4
21 | max_line_length = 100
22 | # Import order can be configured with ij_java_imports_layout=...
23 | # See documentation https://youtrack.jetbrains.com/issue/IDEA-170643#focus=streamItem-27-3708697.0-0
24 |
25 | [*.xml]
26 | indent_size = 4
27 |
--------------------------------------------------------------------------------
/config/HEADER:
--------------------------------------------------------------------------------
1 | Copyright ${year} original authors
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | https://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | contact_links:
2 | - name: Micronaut Core Discussions
3 | url: https://github.com/micronaut-projects/micronaut-core/discussions
4 | about: Ask questions about Micronaut on Github
5 | - name: Micronaut Data Discussions
6 | url: https://github.com/micronaut-projects/micronaut-data/discussions
7 | about: Ask Micronaut Data related questions on Github
8 | - name: Stack Overflow
9 | url: https://stackoverflow.com/tags/micronaut
10 | about: Ask questions on Stack Overflow
11 | - name: Chat
12 | url: https://gitter.im/micronautfw/
13 | about: Chat with us on Gitter.
--------------------------------------------------------------------------------
/gradle/license.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.github.hierynomus.license'
2 |
3 | license {
4 | header = rootProject.file('config/HEADER')
5 | strictCheck = true
6 | ignoreFailures = true
7 | mapping {
8 | kt = 'SLASHSTAR_STYLE'
9 | java = 'SLASHSTAR_STYLE'
10 | groovy = 'SLASHSTAR_STYLE'
11 | }
12 | ext.year = '2017-2021'
13 |
14 | exclude "**/transaction/**"
15 | exclude '**/*.txt'
16 | exclude '**/*.html'
17 | exclude '**/*.xml'
18 | exclude '**/*.json'
19 | exclude '**/build-info.properties'
20 | exclude '**/git.properties'
21 | exclude '**/othergit.properties'
22 | }
23 |
--------------------------------------------------------------------------------
/.clineignore:
--------------------------------------------------------------------------------
1 | # .clineignore - Cline AI ignore file for Micronaut projects
2 | # This file tells Cline which files/directories to ignore for code intelligence and automation
3 |
4 | # === Build outputs ===
5 | build/
6 | */build/
7 | !build/docs/
8 | !build/docs/**
9 | !build/generated/
10 | !build/generated/**
11 |
12 | # === Dependency/Cache directories ===
13 | .gradle/
14 | */.gradle/
15 |
16 | # === IDE/Editor/OS Metadata ===
17 | .vscode/
18 | .idea/
19 | .DS_Store
20 | *.swp
21 | *.swo
22 | *.bak
23 | *.tmp
24 | *.orig
25 |
26 | # === Tool-specific/Config artifacts ===
27 | *.log
28 |
29 | # === Gradle Wrappers/Binaries ===
30 | gradlew
31 | gradlew.bat
32 |
--------------------------------------------------------------------------------
/config/spotless.license.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-$YEAR original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | plugins {
9 | id("io.micronaut.build.shared.settings") version "8.0.0-M12"
10 | }
11 |
12 | rootProject.name = 'elasticsearch-parent'
13 |
14 | include 'elasticsearch-bom'
15 | include 'elasticsearch'
16 | include 'test-suite-groovy'
17 | include 'test-suite-java'
18 |
19 | enableFeaturePreview 'TYPESAFE_PROJECT_ACCESSORS'
20 |
21 | micronautBuild {
22 | useStandardizedProjectNames = true
23 | importMicronautCatalog()
24 | importMicronautCatalog("micronaut-security")
25 | importMicronautCatalog("micronaut-test-resources")
26 | }
27 |
--------------------------------------------------------------------------------
/test-suite-java/src/test/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 | %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:recommended"
4 | ],
5 | "addLabels": [
6 | "type: dependency-upgrade"
7 | ],
8 | "schedule": [
9 | "after 10pm"
10 | ],
11 | "prHourlyLimit": 1,
12 | "prConcurrentLimit": 20,
13 | "timezone": "Europe/Prague",
14 | "packageRules": [
15 | {
16 | "dependencyDashboardApproval": true,
17 | "matchUpdateTypes": [
18 | "patch"
19 | ],
20 | "matchCurrentVersion": "!/^0/",
21 | "automerge": true,
22 | "matchPackageNames": [
23 | "/actions.*/"
24 | ]
25 | },
26 | {
27 | "matchUpdateTypes": [
28 | "patch"
29 | ],
30 | "matchCurrentVersion": "!/^0/",
31 | "automerge": true
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | We release patches for security vulnerabilities. Which versions are eligible
4 | receiving such patches depend on the CVSS v3.0 Rating:
5 |
6 | | CVSS v3.0 | Supported Versions |
7 | |-----------|-------------------------------------------|
8 | | 9.0-10.0 | Releases within the previous three months |
9 | | 4.0-8.9 | Most recent release |
10 |
11 | ## Reporting a Vulnerability
12 |
13 | Please responsibly disclose (suspected) security vulnerabilities to
14 | **[The Micronaut Foundation](foundation@micronaut.io)**. You will receive a response from
15 | us within 48 hours. If the issue is confirmed, we will release a patch as soon
16 | as possible depending on complexity but historically within a few days.
17 |
--------------------------------------------------------------------------------
/test-suite-groovy/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("groovy")
3 | id("io.micronaut.build.internal.elasticsearch-tests")
4 | }
5 |
6 | dependencies {
7 | testCompileOnly(mn.micronaut.inject.groovy)
8 |
9 | testImplementation(platform(mn.micronaut.core.bom))
10 | testImplementation(mnTest.micronaut.test.spock)
11 |
12 | // tag::testcontainers-dependencies[]
13 | testImplementation(mnTestResources.testcontainers.elasticsearch)
14 | // end::testcontainers-dependencies[]
15 | testImplementation(libs.apache.http.client)
16 | testImplementation(libs.apache.http.async.client)
17 | testImplementation(projects.micronautElasticsearch)
18 | testRuntimeOnly(mnLogging.logback.classic)
19 | testRuntimeOnly(mnTest.junit.platform.launcher)
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | changelog:
2 | exclude:
3 | authors:
4 | - micronaut-build
5 | categories:
6 | - title: Breaking Changes 🛠
7 | labels:
8 | - 'type: breaking'
9 | - title: New Features 🎉
10 | labels:
11 | - 'type: enhancement'
12 | - title: Bug Fixes 🐞
13 | labels:
14 | - 'type: bug'
15 | - title: Improvements ⭐
16 | labels:
17 | - 'type: improvement'
18 | - title: Docs 📖
19 | labels:
20 | - 'type: docs'
21 | - title: Dependency updates 🚀
22 | labels:
23 | - 'type: dependency-upgrade'
24 | - 'dependency-upgrade'
25 | - title: Regressions 🧐
26 | labels:
27 | - 'type: regression'
28 | - title: GraalVM 🏆
29 | labels:
30 | - 'relates-to: graal'
31 | - title: Other Changes 💡
32 | labels:
33 | - "*"
34 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/convert/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /**
17 | * Elasticsearch converters.
18 | *
19 | * @author Puneet Behl
20 | * @since 1.0.0
21 | */
22 |
23 | package io.micronaut.elasticsearch.convert;
24 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/conditon/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /**
17 | * Elasticsearch Client condition.
18 | *
19 | * @author Puneet Behl
20 | * @since 1.0.0
21 | */
22 |
23 | package io.micronaut.elasticsearch.conditon;
24 |
--------------------------------------------------------------------------------
/test-suite-java/src/test/java/micronaut/example/ElasticSearchTest.java:
--------------------------------------------------------------------------------
1 | package micronaut.example;
2 |
3 | import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
4 | import micronaut.example.service.Movie;
5 | import micronaut.example.service.MovieService;
6 | import org.junit.jupiter.api.Assertions;
7 | import org.junit.jupiter.api.Test;
8 |
9 | import static java.util.concurrent.TimeUnit.SECONDS;
10 | import static org.awaitility.Awaitility.await;
11 |
12 | @MicronautTest
13 | class ElasticSearchTest {
14 | @Test
15 | void testElasticSearch(MovieService movieService) {
16 | String title = "Die Hard";
17 | movieService.saveMovie(new Movie("KJFDOD", title));
18 | await().atMost(10, SECONDS).until(() ->
19 | movieService.searchMovies(title) != null
20 | );
21 | Movie result = movieService.searchMovies(title);
22 | Assertions.assertNotNull(result);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/docs/guide/healthChecks.adoc:
--------------------------------------------------------------------------------
1 | When the `elasticsearch` module is activated a api:elasticsearch.health.ElasticsearchClientHealthIndicator[] is
2 | activated resulting in the `/health` endpoint and https://docs.micronaut.io/latest/api/io/micronaut/health/CurrentHealthStatus.html[CurrentHealthStatus]
3 | interface resolving the health of the Elasticsearch cluster.
4 |
5 | To enable or disable the indicator use:
6 |
7 | [source,yaml]
8 | .application.yml
9 | ----
10 | endpoints:
11 | health:
12 | elasticsearch:
13 | enabled: true
14 | ----
15 |
16 |
17 | To use the deprecated health indicator use:
18 |
19 | [source,yaml]
20 | .application.yml
21 | ----
22 | endpoints:
23 | health:
24 | elasticsearch:
25 | rest:
26 | high:
27 | level:
28 | enabled: false
29 | ----
30 |
31 | See the section on the https://docs.micronaut.io/latest/guide/index.html#healthEndpoint[Health Endpoint] for more information.
32 |
--------------------------------------------------------------------------------
/test-suite-java/src/test/java/micronaut/example/service/Movie.java:
--------------------------------------------------------------------------------
1 | package micronaut.example.service;
2 |
3 | import io.micronaut.core.annotation.Introspected;
4 |
5 | @Introspected
6 | public class Movie {
7 |
8 | private String imdb;
9 | private String title;
10 |
11 | public Movie(String imdb, String title) {
12 | this.imdb = imdb;
13 | this.title = title;
14 | }
15 |
16 | public String getImdb() {
17 | return imdb;
18 | }
19 |
20 | public void setImdb(String imdb) {
21 | this.imdb = imdb;
22 | }
23 |
24 | public String getTitle() {
25 | return title;
26 | }
27 |
28 | public void setTitle(String title) {
29 | this.title = title;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return "Movie{" +
35 | "imdb='" + imdb + '\'' +
36 | ", title='" + title + '\'' +
37 | '}';
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | .DS_Store
3 | target/
4 | .gradle/
5 | .idea/
6 | build/
7 | !build-logic/src/main/java/io/micronaut/build
8 | !build-logic/src/main/kotlin/io/micronaut/build
9 | classes/
10 | out/
11 | *.db
12 | *.log
13 | *.iml
14 | .classpath
15 | .factorypath
16 | bin/
17 | .settings/
18 | .project
19 | */test/
20 | */META-INF/
21 | *.ipr
22 | *.iws
23 | .kotlintest
24 | */.kotlintest/
25 |
26 | # ignore resources, are downloaded via a gradle task from micronaut_docs
27 | src/main/docs/resources/css/highlight/*.css
28 | src/main/docs/resources/css/highlight/*.png
29 | src/main/docs/resources/css/highlight/*.jpg
30 | src/main/docs/resources/css/*.css
31 | src/main/docs/resources/js/*.js
32 | src/main/docs/resources/style/*.html
33 | src/main/docs/resources/img/micronaut-logo-white.svg
34 |
35 | # Ignore files generated by test-resources
36 | **/.micronaut/test-resources/
37 |
38 | # Ignore gradle.properties generated by micronaut-build
39 | /buildSrc/gradle.properties
40 |
--------------------------------------------------------------------------------
/elasticsearch/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("io.micronaut.build.internal.elasticsearch-module")
3 | }
4 |
5 | dependencies {
6 | annotationProcessor(mn.micronaut.graal)
7 |
8 | compileOnly(libs.graal.svm)
9 | implementation(mn.micronaut.management)
10 | api(libs.managed.elasticsearch.java) {
11 | exclude(group="org.elasticsearch.client", module = "elasticsearch-rest-client")
12 | }
13 | implementation(libs.managed.elasticsearch.rest.client) {
14 | exclude(group="commons-logging", module = "commons-logging")
15 | }
16 | runtimeOnly(mnLogging.slf4j.jcl.over.slf4j)
17 | api(mn.micronaut.http)
18 |
19 | implementation(mn.micronaut.jackson.databind)
20 |
21 | testImplementation(mnTestResources.testcontainers.elasticsearch)
22 | testImplementation(mn.groovy.json)
23 | testImplementation(mnSecurity.micronaut.security)
24 | testImplementation(mn.reactor)
25 | }
26 |
27 |
28 | tasks {
29 | named("test") {
30 | systemProperty("elasticsearch.version", libs.versions.managed.elasticsearch.get())
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /**
17 | * Configuration for Elasticsearch RestHighLevelClient.
18 | * refer to https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.3/java-rest-high.html
19 | *
20 | * @author lishuai
21 | * @since 1.0.0
22 | */
23 | @Configuration
24 | @RequiresElasticsearch
25 | package io.micronaut.elasticsearch;
26 |
27 | import io.micronaut.elasticsearch.conditon.RequiresElasticsearch;
28 | import io.micronaut.context.annotation.Configuration;
29 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Thanks for reporting an issue, please review the task list below before submitting the
2 | issue. Your issue report will be closed if the issue is incomplete and the below tasks not completed.
3 |
4 | NOTE: If you are unsure about something and the issue is more of a question a better place to ask questions is on Stack Overflow (https://stackoverflow.com/tags/micronaut) or Gitter (https://gitter.im/micronautfw/). DO NOT use the issue tracker to ask questions.
5 |
6 | ### Task List
7 |
8 | - [ ] Steps to reproduce provided
9 | - [ ] Stacktrace (if present) provided
10 | - [ ] Example that reproduces the problem uploaded to Github
11 | - [ ] Full description of the issue provided (see below)
12 |
13 | ### Steps to Reproduce
14 |
15 | 1. TODO
16 | 2. TODO
17 | 3. TODO
18 |
19 | ### Expected Behaviour
20 |
21 | Tell us what should happen
22 |
23 | ### Actual Behaviour
24 |
25 | Tell us what happens instead
26 |
27 | ### Environment Information
28 |
29 | - **Operating System**: TODO
30 | - **Micronaut Version:** TODO
31 | - **JDK Version:** TODO
32 |
33 | ### Example Application
34 |
35 | - TODO: link to github repository with example that reproduces the issue
36 |
37 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/ElasticsearchSettings.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch;
17 |
18 | import org.apache.http.HttpHost;
19 |
20 | /**
21 | * Common constants for Elasticsearch settings.
22 | *
23 | * @author lishuai
24 | * @since 1.0.0
25 | */
26 | public interface ElasticsearchSettings {
27 |
28 | /**
29 | * The prefix to use for all Elasticsearch settings.
30 | */
31 | String PREFIX = "elasticsearch";
32 |
33 | /**
34 | * Default Elasticsearch host.
35 | */
36 | HttpHost DEFAULT_HOST = new HttpHost("127.0.0.1", 9200, "http");
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/test-suite-java/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("io.micronaut.application")
3 | id("io.micronaut.test-resources")
4 | id("io.micronaut.build.internal.elasticsearch-native-tests")
5 | }
6 |
7 | micronaut {
8 | version libs.versions.micronaut.platform.get()
9 | coreVersion.set(libs.versions.micronaut.asProvider().get())
10 | testRuntime "junit5"
11 | enableNativeImage false
12 | processing {
13 | incremental(true)
14 | annotations("helloworld.*")
15 | }
16 | }
17 |
18 | configurations.all {
19 | resolutionStrategy.dependencySubstitution {
20 | substitute module('io.micronaut.elasticsearch:micronaut-elasticsearch') using project(':micronaut-elasticsearch')
21 | }
22 | }
23 |
24 | dependencies {
25 | annotationProcessor("io.micronaut.validation:micronaut-validation-processor")
26 | implementation(mn.micronaut.context)
27 | implementation(mn.micronaut.jackson.databind)
28 | implementation("io.micronaut.validation:micronaut-validation")
29 | testImplementation(libs.awaitility)
30 | implementation(project(":micronaut-elasticsearch"))
31 | implementation(mn.snakeyaml)
32 | runtimeOnly(mnLogging.logback.classic)
33 | }
34 | micronaut {
35 | testResources {
36 | clientTimeout = 300
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/conditon/RequiresElasticsearch.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch.conditon;
17 |
18 | import io.micronaut.elasticsearch.ElasticsearchSettings;
19 | import io.micronaut.context.annotation.Requires;
20 | import org.elasticsearch.client.RestClient;
21 |
22 | import java.lang.annotation.*;
23 |
24 | /**
25 | * Meta annotation for Elasticsearch that can be added to any component that requires Elasticsearch to load.
26 | *
27 | * @author Puneet Behl
28 | * @since 1.0.0
29 | */
30 | @Documented
31 | @Retention(RetentionPolicy.RUNTIME)
32 | @Target({ElementType.PACKAGE, ElementType.TYPE})
33 | @Requires(property = ElasticsearchSettings.PREFIX)
34 | @Requires(classes = {RestClient.class})
35 | public @interface RequiresElasticsearch {
36 | }
37 |
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | micronaut-docs = "3.0.0"
3 | micronaut = "4.10.9"
4 | micronaut-platform = "4.10.1"
5 | micronaut-security = "4.16.0"
6 | micronaut-logging = "1.7.0"
7 | micronaut-test = "4.10.2"
8 | micronaut-test-resources="2.10.1"
9 | micronaut-gradle-plugin = "4.6.1"
10 | managed-elasticsearch = "8.19.5"
11 |
12 | graal-svm = "25.0.1"
13 | groovy = "4.0.15"
14 | spock = "2.3-groovy-4.0"
15 | awaitility = "4.3.0"
16 | apache-http-client = "4.5.14"
17 | apache-http-async-client = "4.1.5"
18 |
19 | [libraries]
20 | # Core
21 | micronaut-core = { module = 'io.micronaut:micronaut-core-bom', version.ref = 'micronaut' }
22 |
23 | micronaut-security = { module = "io.micronaut.security:micronaut-security-bom", version.ref = "micronaut-security" }
24 | micronaut-test-resources = { module = "io.micronaut.testresources:micronaut-test-resources-bom", version.ref = "micronaut-test-resources" }
25 |
26 | managed-elasticsearch-java = { module = "co.elastic.clients:elasticsearch-java", version.ref = "managed-elasticsearch" }
27 | managed-elasticsearch-rest-client = { module = "org.elasticsearch.client:elasticsearch-rest-client", version.ref = "managed-elasticsearch" }
28 | apache-http-client = { module = "org.apache.httpcomponents:httpclient", version.ref = "apache-http-client" }
29 | apache-http-async-client = { module = "org.apache.httpcomponents:httpasyncclient", version.ref = "apache-http-async-client" }
30 | graal-svm = { module = "org.graalvm.nativeimage:svm", version.ref = "graal-svm" }
31 |
32 | awaitility = { module = "org.awaitility:awaitility", version.ref = "awaitility" }
33 | gradle-micronaut = { module = "io.micronaut.gradle:micronaut-gradle-plugin", version.ref = "micronaut-gradle-plugin" }
34 |
--------------------------------------------------------------------------------
/.github/workflows/publish-snapshot.yml:
--------------------------------------------------------------------------------
1 | # WARNING: Do not edit this file directly. Instead, go to:
2 | #
3 | # https://github.com/micronaut-projects/micronaut-project-template/tree/master/.github/workflows
4 | #
5 | # and edit them there. Note that it will be sync'ed to all the Micronaut repos
6 | name: Publish snapshot release
7 | on: [workflow_dispatch]
8 | jobs:
9 | build:
10 | if: github.repository != 'micronaut-projects/micronaut-project-template'
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Remove system JDKs
14 | run: |
15 | sudo rm -rf /usr/lib/jvm/*
16 | unset JAVA_HOME
17 | export PATH=$(echo "$PATH" | tr ':' '\n' | grep -v '/usr/lib/jvm' | paste -sd:)
18 | - uses: actions/checkout@v6
19 | - uses: actions/cache@v4
20 | with:
21 | path: ~/.gradle/caches
22 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
23 | restore-keys: |
24 | ${{ runner.os }}-gradle-
25 | - name: Set up JDK
26 | uses: actions/setup-java@v5
27 | with:
28 | distribution: 'temurin'
29 | java-version: |
30 | 21
31 | 25
32 | - name: Publish to Sonatype Snapshots
33 | if: success()
34 | env:
35 | SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
36 | SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
37 | DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
38 | DEVELOCITY_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
39 | DEVELOCITY_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
40 | run: ./gradlew publishToSonatype --no-daemon
41 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/convert/StringToHttpHostConverter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch.convert;
17 |
18 | import io.micronaut.context.annotation.Requires;
19 | import io.micronaut.core.convert.ConversionContext;
20 | import io.micronaut.core.convert.TypeConverter;
21 | import org.apache.http.HttpHost;
22 | import org.elasticsearch.client.RestClientBuilder;
23 |
24 | import jakarta.inject.Singleton;
25 | import java.net.URI;
26 | import java.util.Optional;
27 |
28 | /**
29 | * Converts String to {@link HttpHost}.
30 | *
31 | * @author Puneet Behl
32 | * @since 1.0.0
33 | */
34 | @Singleton
35 | @Requires(classes = RestClientBuilder.class)
36 | public class StringToHttpHostConverter implements TypeConverter {
37 |
38 | @Override
39 | public Optional convert(CharSequence object, Class targetType, ConversionContext context) {
40 | String uriString = object.toString();
41 | URI uri = URI.create(uriString);
42 | return Optional.of(new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme()));
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/DefaultHttpAsyncClientBuilderFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch;
17 |
18 | import io.micronaut.context.annotation.Bean;
19 | import io.micronaut.context.annotation.Factory;
20 | import io.micronaut.context.annotation.Requires;
21 | import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
22 | import org.elasticsearch.client.RestClient;
23 | import jakarta.inject.Singleton;
24 |
25 | /**
26 | * The default factory used to create {@link HttpAsyncClientBuilder} for HTTP client configurations.
27 | *
28 | * @author Puneet Behl
29 | * @since 1.0.0
30 | */
31 | @Requires(classes = {RestClient.class})
32 | @Factory
33 | public class DefaultHttpAsyncClientBuilderFactory {
34 |
35 | /**
36 | * The http client configuration (e.g. encrypted communication over ssl, or anything that
37 | * the {@link HttpAsyncClientBuilder} allows to set).
38 | *
39 | * @return The {@link HttpAsyncClientBuilder} bean with default configurations.
40 | */
41 | @Bean
42 | @Singleton
43 | protected HttpAsyncClientBuilder httpAsyncClientBuilder() {
44 | return HttpAsyncClientBuilder.create();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/convert/StringToHeaderConverter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch.convert;
17 |
18 | import io.micronaut.context.annotation.Requires;
19 | import io.micronaut.core.convert.ConversionContext;
20 | import io.micronaut.core.convert.TypeConverter;
21 | import org.apache.http.Header;
22 | import org.apache.http.message.BasicHeader;
23 | import org.elasticsearch.client.RestClientBuilder;
24 |
25 | import jakarta.inject.Singleton;
26 | import java.util.Optional;
27 |
28 | /**
29 | * Converts String to {@link Header}.
30 | *
31 | * @author Puneet Behl
32 | * @since 1.0.0
33 | */
34 | @Singleton
35 | @Requires(classes = RestClientBuilder.class)
36 | public class StringToHeaderConverter implements TypeConverter {
37 |
38 | @Override
39 | public Optional convert(CharSequence object, Class targetType, ConversionContext context) {
40 | String header = object.toString();
41 | if (header.contains(":")) {
42 | String[] nameAndValue = header.split(":");
43 | return Optional.of(new BasicHeader(nameAndValue[0], nameAndValue[1]));
44 | } else {
45 | return Optional.empty();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/.github/workflows/central-sync.yml:
--------------------------------------------------------------------------------
1 | # WARNING: Do not edit this file directly. Instead, go to:
2 | #
3 | # https://github.com/micronaut-projects/micronaut-project-template/tree/master/.github/workflows
4 | #
5 | # and edit them there. Note that it will be sync'ed to all the Micronaut repos
6 | name: Maven Central Sync
7 | on:
8 | workflow_dispatch:
9 | inputs:
10 | release_version:
11 | description: 'Release version (eg: 1.2.3)'
12 | required: true
13 | jobs:
14 | central-sync:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - name: Remove system JDKs
18 | run: |
19 | sudo rm -rf /usr/lib/jvm/*
20 | unset JAVA_HOME
21 | export PATH=$(echo "$PATH" | tr ':' '\n' | grep -v '/usr/lib/jvm' | paste -sd:)
22 | - name: Checkout repository
23 | uses: actions/checkout@v6
24 | with:
25 | ref: v${{ github.event.inputs.release_version }}
26 | - uses: gradle/actions/wrapper-validation@v5
27 | - name: Set up JDK
28 | uses: actions/setup-java@v5
29 | with:
30 | distribution: 'temurin'
31 | java-version: |
32 | 21
33 | 25
34 | - name: Publish to Sonatype OSSRH
35 | env:
36 | SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
37 | SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
38 | GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
39 | GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }}
40 | GPG_FILE: ${{ secrets.GPG_FILE }}
41 | DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
42 | DEVELOCITY_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
43 | DEVELOCITY_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
44 | run: |
45 | echo $GPG_FILE | base64 -d > secring.gpg
46 | ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
47 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/convert/StringToNodeSelectorConverter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch.convert;
17 |
18 | import io.micronaut.context.annotation.Requires;
19 | import io.micronaut.core.convert.ConversionContext;
20 | import io.micronaut.core.convert.TypeConverter;
21 | import org.elasticsearch.client.NodeSelector;
22 | import org.elasticsearch.client.RestClientBuilder;
23 |
24 | import jakarta.inject.Singleton;
25 | import java.util.Locale;
26 | import java.util.Optional;
27 |
28 | /**
29 | * Converts String to {@link NodeSelector}.
30 | *
31 | * @author Puneet Behl
32 | * @since 1.0.0
33 | */
34 | @Singleton
35 | @Requires(classes = RestClientBuilder.class)
36 | public class StringToNodeSelectorConverter implements TypeConverter {
37 |
38 | @Override
39 | public Optional convert(CharSequence object, Class targetType, ConversionContext context) {
40 | String nodeSelector = object.toString().toUpperCase(Locale.ENGLISH);
41 | switch (nodeSelector) {
42 | case "SKIP_DEDICATED_MASTERS":
43 | return Optional.of(NodeSelector.SKIP_DEDICATED_MASTERS);
44 | case "ANY":
45 | return Optional.of(NodeSelector.ANY);
46 | default:
47 | return Optional.empty();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/convert/StringToInetAddressConverter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch.convert;
17 |
18 | import io.micronaut.context.annotation.Requires;
19 | import io.micronaut.core.convert.ConversionContext;
20 | import io.micronaut.core.convert.TypeConverter;
21 | import org.elasticsearch.client.RestClientBuilder;
22 | import org.slf4j.Logger;
23 | import org.slf4j.LoggerFactory;
24 |
25 | import jakarta.inject.Singleton;
26 | import java.net.InetAddress;
27 | import java.net.UnknownHostException;
28 | import java.util.Optional;
29 |
30 | /**
31 | * Converts String to {@link InetAddress}.
32 | *
33 | * @author Puneet Behl
34 | * @since 1.0.0
35 | */
36 | @Singleton
37 | @Requires(classes = RestClientBuilder.class)
38 | public class StringToInetAddressConverter implements TypeConverter {
39 |
40 | private static final Logger LOG = LoggerFactory.getLogger(StringToInetAddressConverter.class);
41 |
42 | @Override
43 | public Optional convert(CharSequence object, Class targetType, ConversionContext context) {
44 | String address = object.toString();
45 | try {
46 | return Optional.of(InetAddress.getByName(address));
47 | } catch (UnknownHostException e) {
48 | LOG.error(e.getMessage(), e);
49 | return Optional.empty();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yaml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: File a bug report
3 | body:
4 | - type: markdown
5 | attributes:
6 | value: |
7 | Thanks for reporting an issue, please review the task list below before submitting the issue. Your issue report will be closed if the issue is incomplete and the below tasks not completed.
8 |
9 | NOTE: If you are unsure about something and the issue is more of a question a better place to ask questions is on Github Discussions :arrow_up:, [Stack Overflow](https://stackoverflow.com/tags/micronaut) or [Gitter](https://gitter.im/micronautfw/).
10 | - type: textarea
11 | attributes:
12 | label: Expected Behavior
13 | description: A concise description of what you expected to happen.
14 | placeholder: Tell us what should happen
15 | validations:
16 | required: false
17 | - type: textarea
18 | attributes:
19 | label: Actual Behaviour
20 | description: A concise description of what you're experiencing.
21 | placeholder: Tell us what happens instead
22 | validations:
23 | required: false
24 | - type: textarea
25 | attributes:
26 | label: Steps To Reproduce
27 | description: Steps to reproduce the behavior.
28 | placeholder: |
29 | 1. In this environment...
30 | 2. With this config...
31 | 3. Run '...'
32 | 4. See error...
33 | validations:
34 | required: false
35 | - type: textarea
36 | attributes:
37 | label: Environment Information
38 | description: Environment information where the problem occurs.
39 | placeholder: |
40 | - Operating System:
41 | - JDK Version:
42 | validations:
43 | required: false
44 | - type: input
45 | id: example
46 | attributes:
47 | label: Example Application
48 | description: Example application link.
49 | placeholder: |
50 | Link to GitHub repository with an example that reproduces the issue
51 | validations:
52 | required: false
53 | - type: input
54 | id: version
55 | attributes:
56 | label: Version
57 | description: Micronaut version
58 | validations:
59 | required: true
60 |
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Micronaut Elasticsearch Configuration
2 |
3 | [](https://search.maven.org/search?q=g:%22io.micronaut.elasticsearch%22%20AND%20a:%22micronaut-elasticsearch%22)
4 | [](https://github.com/micronaut-projects/micronaut-elasticsearch/actions)
5 | [](https://ge.micronaut.io/scans)
6 |
7 | Micronaut Elasticsearch includes integration between [Micronaut](https://micronaut.io/) and [Elasticsearch](https://www.elastic.co/).
8 |
9 | ## Documentation
10 |
11 | See the [Documentation](https://micronaut-projects.github.io/micronaut-elasticsearch/latest/guide/) for more information.
12 |
13 | See the [Snapshot Documentation](https://micronaut-projects.github.io/micronaut-elasticsearch/snapshot/guide/) for the current development docs.
14 |
15 | ## Snapshots and Releases
16 |
17 | Snapshots are automatically published to [Sonatype Snapshots](https://s01.oss.sonatype.org/content/repositories/snapshots/io/micronaut/) using [Github Actions](https://github.com/micronaut-projects/micronaut-elasticsearch/actions).
18 |
19 | See the documentation in the [Micronaut Docs](https://docs.micronaut.io/latest/guide/index.html#usingsnapshots) for how to configure your build to use snapshots.
20 |
21 | Releases are published to Maven Central via [Github Actions](https://github.com/micronaut-projects/micronaut-elasticsearch/actions).
22 |
23 | Releases are completely automated. To perform a release use the following steps:
24 |
25 | * [Publish the draft release](https://github.com/micronaut-projects/micronaut-elasticsearch/releases). There should be already a draft release created, edit and publish it. The Git Tag should start with `v`. For example `v1.0.0`.
26 | * [Monitor the Workflow](https://github.com/micronaut-projects/micronaut-elasticsearch/actions?query=workflow%3ARelease) to check it passed successfully.
27 | * If everything went fine, [publish to Maven Central](https://github.com/micronaut-projects/micronaut-elasticsearch/actions?query=workflow%3A"Maven+Central+Sync").
28 | * Celebrate!
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/DefaultElasticsearchConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch;
17 |
18 | import org.apache.http.Header;
19 | import org.apache.http.HttpHost;
20 | import org.apache.http.client.config.RequestConfig;
21 | import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
22 | import org.elasticsearch.client.NodeSelector;
23 |
24 | /**
25 | * Elasticsearch Configuration.
26 | *
27 | * @author Puneet Behl
28 | * @since 1.0.0
29 | */
30 | public interface DefaultElasticsearchConfiguration {
31 |
32 | /**
33 | * The one or more hosts that the client will communicate with, provided as instances of {@link HttpHost}.
34 | *
35 | * @return An array of {@link HttpHost}
36 | */
37 | HttpHost[] getHttpHosts();
38 |
39 | /**
40 | * The default headers that need to be sent with each request, to prevent having to
41 | * specify them with each single request.
42 | *
43 | * @return An array of {@link Header}.
44 | */
45 | Header[] getDefaultHeaders();
46 |
47 | /**
48 | * The timeout that should be honoured in case multiple attempts are made for the same request.
49 | * The default value is 30 seconds.
50 | *
51 | * @return The maximum retry timeout in millis.
52 | */
53 | int getMaxRetryTimeoutMillis();
54 |
55 | /**
56 | * The node selector to be used to filter the nodes the client will send requests to among the
57 | * ones that are set to the client itself. By default the client sends requests to every configured node.
58 | *
59 | * @return The {@link NodeSelector} to be used.
60 | */
61 | NodeSelector getNodeSelector();
62 |
63 | /**
64 | * @return The builder to create default request configurations.
65 | */
66 | RequestConfig.Builder getRequestConfigBuilder();
67 |
68 | /**
69 | * The http client configuration (e.g. encrypted communication over ssl, or anything that
70 | * the {@link HttpAsyncClientBuilder} allows to set).
71 | *
72 | * @return The {@link HttpAsyncClientBuilder} bean
73 | */
74 | HttpAsyncClientBuilder getHttpAsyncClientBuilder();
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/test-suite-java/src/test/java/micronaut/example/service/MovieServiceImpl.java:
--------------------------------------------------------------------------------
1 | package micronaut.example.service;
2 |
3 | import java.util.Iterator;
4 |
5 | import co.elastic.clients.elasticsearch.ElasticsearchClient;
6 | import co.elastic.clients.elasticsearch.core.IndexRequest;
7 | import co.elastic.clients.elasticsearch.core.IndexResponse;
8 | import co.elastic.clients.elasticsearch.core.SearchResponse;
9 | import co.elastic.clients.elasticsearch.core.search.Hit;
10 | import io.micronaut.context.annotation.Value;
11 | import jakarta.inject.Singleton;
12 | import micronaut.example.exception.MovieServiceException;
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | @Singleton
17 | public class MovieServiceImpl implements MovieService {
18 |
19 | private static final Logger LOG = LoggerFactory.getLogger(MovieServiceImpl.class);
20 |
21 | @Value("${elasticsearch.indexes.movies}")
22 | String moviesIndex;
23 |
24 | private final ElasticsearchClient client;
25 |
26 | public MovieServiceImpl(ElasticsearchClient client) {
27 | this.client = client;
28 | }
29 |
30 | @Override
31 | public String saveMovie(Movie movie) {
32 | try {
33 | IndexRequest indexRequest = new IndexRequest.Builder()
34 | .index(moviesIndex)
35 | .document(movie)
36 | .build();
37 |
38 | IndexResponse indexResponse = client.index(indexRequest);
39 | String id = indexResponse.id();
40 |
41 | LOG.info("Document for '{}' {} successfully in ES. The id is: {}", movie, indexResponse.result(), id);
42 | return id;
43 | } catch (Exception e) {
44 | String errorMessage = String.format("An exception occurred while indexing '%s'", movie);
45 | LOG.error(errorMessage);
46 | throw new MovieServiceException(errorMessage, e);
47 | }
48 | }
49 |
50 | @Override
51 | public Movie searchMovies(String title) {
52 | try {
53 | SearchResponse searchResponse = client.search((s) ->
54 | s.index(moviesIndex)
55 | .query(q -> q.match(m ->
56 | m.field("title")
57 | .query(title)
58 | )), Movie.class
59 | );
60 | LOG.info("Searching for '{}' took {} and found {}", title, searchResponse.took(), searchResponse.hits().total().value());
61 |
62 | Iterator> hits = searchResponse.hits().hits().iterator();
63 | if (hits.hasNext()) {
64 | return hits.next().source();
65 | }
66 | return null;
67 |
68 | } catch (Exception e) {
69 | String errorMessage = String.format("An exception occurred while searching for title '%s'", title);
70 | LOG.error(errorMessage);
71 | throw new MovieServiceException(errorMessage, e);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/.github/workflows/graalvm-latest.yml:
--------------------------------------------------------------------------------
1 | # WARNING: Do not edit this file directly. Instead, go to:
2 | #
3 | # https://github.com/micronaut-projects/micronaut-project-template/tree/master/.github/workflows
4 | #
5 | # and edit them there. Note that it will be sync'ed to all the Micronaut repos
6 | name: GraalVM Latest CI
7 | on:
8 | push:
9 | branches:
10 | - master
11 | - '[0-9]+.[0-9]+.x'
12 | pull_request:
13 | branches:
14 | - master
15 | - '[0-9]+.[0-9]+.x'
16 | jobs:
17 | build_matrix:
18 | if: github.repository != 'micronaut-projects/micronaut-project-template'
19 | runs-on: ubuntu-latest
20 | env:
21 | DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
22 | DEVELOCITY_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
23 | DEVELOCITY_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
24 | outputs:
25 | matrix: ${{ steps.build-matrix.outputs.matrix }}
26 | steps:
27 | - uses: actions/checkout@v6
28 | - name: Build Matrix
29 | uses: micronaut-projects/github-actions/graalvm/build-matrix@master
30 | id: build-matrix
31 | with:
32 | java-version: '21'
33 | build:
34 | needs: build_matrix
35 | if: github.repository != 'micronaut-projects/micronaut-project-template'
36 | runs-on: ubuntu-latest
37 | strategy:
38 | max-parallel: 6
39 | matrix:
40 | java: ['21']
41 | native_test_task: ${{ fromJson(needs.build_matrix.outputs.matrix).native_test_task }}
42 | env:
43 | DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
44 | DEVELOCITY_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
45 | DEVELOCITY_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
46 | steps:
47 | - name: Remove system JDKs
48 | run: |
49 | sudo rm -rf /usr/lib/jvm/*
50 | unset JAVA_HOME
51 | export PATH=$(echo "$PATH" | tr ':' '\n' | grep -v '/usr/lib/jvm' | paste -sd:)
52 | - uses: actions/checkout@v6
53 | - name: Pre-Build Steps
54 | uses: micronaut-projects/github-actions/graalvm/pre-build@master
55 | id: pre-build
56 | with:
57 | distribution: 'graalvm'
58 | gradle-java: '21'
59 | java: ${{ matrix.java }}
60 | nativeTestTask: ${{ matrix.native_test_task }}
61 | - name: Build Steps
62 | uses: micronaut-projects/github-actions/graalvm/build@master
63 | id: build
64 | env:
65 | GH_TOKEN_PUBLIC_REPOS_READONLY: ${{ secrets.GH_TOKEN_PUBLIC_REPOS_READONLY }}
66 | GH_USERNAME: ${{ secrets.GH_USERNAME }}
67 | GRAALVM_QUICK_BUILD: true
68 | with:
69 | nativeTestTask: ${{ matrix.native_test_task }}
70 | - name: Post-Build Steps
71 | uses: micronaut-projects/github-actions/graalvm/post-build@master
72 | id: post-build
73 | with:
74 | java: ${{ matrix.java }}
75 |
--------------------------------------------------------------------------------
/.clinerules/docs.md:
--------------------------------------------------------------------------------
1 | ## Brief overview
2 | - Documentation for the Micronaut modules is primarily written in Asciidoc format, focusing on user guides, API references, and integration examples. The documentation emphasizes clarity, completeness, and practical examples to help developers integrate Micronaut modules effectively. Insights from the codebase show a focus on modular documentation aligned with subprojects, including setup instructions, usage examples, and troubleshooting tips.
3 | - All the files are within `src/main/docs/guide`. In that directory, there is a `toc.yml` file that is used to generate the table of contents and decide which `.adoc` files are to be included.
4 |
5 | ## Development workflow
6 | - Write documentation in Asciidoc: Place source files in the appropriate `src/main/docs` directory.
7 | - Build and assemble the documentation guide: Use `./gradlew docs` from the root directory to generate HTML documentation. Since the output of this task may be huge, ignore the output and check the last process exit code to tell if it works. Otherwise, ask the user. If it works, verify the output for formatting and content accuracy.
8 | - Once assembled, the guide will be at `build/docs/`.
9 | - Include examples: Create and reference code examples from the doc-examples/ directory, ensuring they are testable and up-to-date with the latest service versions.
10 | - Test documentation: Run builds regularly and check for broken links or outdated information. Integrate doc checks into CI pipelines using Gradle tasks.
11 | - Review and update: Conduct peer reviews for new documentation or changes, ensuring alignment with coding standards and project updates.
12 |
13 | ## Documentation best practices
14 | - Follow Asciidoc conventions: Use consistent headings, lists, code blocks, and admonitions (e.g., NOTE, TIP, WARNING) for better readability.
15 | - Provide comprehensive coverage: Include installation instructions, configuration details, usage examples, error handling, and performance tips for each service.
16 | - Use practical examples: Incorporate runnable code snippets from doc-examples/ to demonstrate real-world usage, with clear explanations and expected outputs.
17 | - Ensure accessibility: Use descriptive alt text for images, maintain logical structure, and avoid jargon without explanations.
18 | - Version control: Document version-specific changes and maintain backward compatibility notes.
19 | - Security and best practices: Highlight secure usage patterns, such as proper authentication and data handling.
20 |
21 | ## Project context
22 | - Focus on Micronaut-specific integration that this project is providing, emphasizing GraalVM compatibility, annotation-driven configurations, and modular design.
23 | - Prioritize user-centric content: Guides should facilitate quick starts, advanced customizations, and troubleshooting for developers building Micronaut applications.
24 | - Align with coding guidelines: Documentation should complement code by explaining architectural decisions, such as the use of factories, interceptors, and annotation processors.
25 |
--------------------------------------------------------------------------------
/.github/instructions/docs.instructions.md:
--------------------------------------------------------------------------------
1 | ## Brief overview
2 | - Documentation for the Micronaut modules is primarily written in Asciidoc format, focusing on user guides, API references, and integration examples. The documentation emphasizes clarity, completeness, and practical examples to help developers integrate Micronaut modules effectively. Insights from the codebase show a focus on modular documentation aligned with subprojects, including setup instructions, usage examples, and troubleshooting tips.
3 | - All the files are within `src/main/docs/guide`. In that directory, there is a `toc.yml` file that is used to generate the table of contents and decide which `.adoc` files are to be included.
4 |
5 | ## Development workflow
6 | - Write documentation in Asciidoc: Place source files in the appropriate `src/main/docs` directory.
7 | - Build and assemble the documentation guide: Use `./gradlew docs` from the root directory to generate HTML documentation. Since the output of this task may be huge, ignore the output and check the last process exit code to tell if it works. Otherwise, ask the user. If it works, verify the output for formatting and content accuracy.
8 | - Once assembled, the guide will be at `build/docs/`.
9 | - Include examples: Create and reference code examples from the doc-examples/ directory, ensuring they are testable and up-to-date with the latest service versions.
10 | - Test documentation: Run builds regularly and check for broken links or outdated information. Integrate doc checks into CI pipelines using Gradle tasks.
11 | - Review and update: Conduct peer reviews for new documentation or changes, ensuring alignment with coding standards and project updates.
12 |
13 | ## Documentation best practices
14 | - Follow Asciidoc conventions: Use consistent headings, lists, code blocks, and admonitions (e.g., NOTE, TIP, WARNING) for better readability.
15 | - Provide comprehensive coverage: Include installation instructions, configuration details, usage examples, error handling, and performance tips for each service.
16 | - Use practical examples: Incorporate runnable code snippets from doc-examples/ to demonstrate real-world usage, with clear explanations and expected outputs.
17 | - Ensure accessibility: Use descriptive alt text for images, maintain logical structure, and avoid jargon without explanations.
18 | - Version control: Document version-specific changes and maintain backward compatibility notes.
19 | - Security and best practices: Highlight secure usage patterns, such as proper authentication and data handling.
20 |
21 | ## Project context
22 | - Focus on Micronaut-specific integration that this project is providing, emphasizing GraalVM compatibility, annotation-driven configurations, and modular design.
23 | - Prioritize user-centric content: Guides should facilitate quick starts, advanced customizations, and troubleshooting for developers building Micronaut applications.
24 | - Align with coding guidelines: Documentation should complement code by explaining architectural decisions, such as the use of factories, interceptors, and annotation processors.
25 |
--------------------------------------------------------------------------------
/.github/workflows/graalvm-dev.yml:
--------------------------------------------------------------------------------
1 | # WARNING: Do not edit this file directly. Instead, go to:
2 | #
3 | # https://github.com/micronaut-projects/micronaut-project-template/tree/master/.github/workflows
4 | #
5 | # and edit them there. Note that it will be sync'ed to all the Micronaut repos
6 | name: GraalVM Dev CI
7 | on:
8 | schedule:
9 | - cron: "0 1 * * 1-5" # Mon-Fri at 1am UTC
10 | jobs:
11 | build_matrix:
12 | if: github.repository != 'micronaut-projects/micronaut-project-template'
13 | runs-on: ubuntu-latest
14 | env:
15 | DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
16 | DEVELOCITY_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
17 | DEVELOCITY_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
18 | outputs:
19 | matrix: ${{ steps.build-matrix.outputs.matrix }}
20 | steps:
21 | - uses: actions/checkout@v6
22 | - name: Build Matrix
23 | uses: micronaut-projects/github-actions/graalvm/build-matrix@master
24 | id: build-matrix
25 | build:
26 | needs: build_matrix
27 | if: github.repository != 'micronaut-projects/micronaut-project-template'
28 | runs-on: ubuntu-latest
29 | strategy:
30 | max-parallel: 6
31 | matrix:
32 | java: ['dev', 'latest-ea']
33 | distribution: ['graalvm-community', 'graalvm']
34 | native_test_task: ${{ fromJson(needs.build_matrix.outputs.matrix).native_test_task }}
35 | exclude:
36 | - java: 'dev'
37 | distribution: 'graalvm'
38 | - java: 'latest-ea'
39 | distribution: 'graalvm-community'
40 | env:
41 | DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
42 | DEVELOCITY_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
43 | DEVELOCITY_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
44 | steps:
45 | - name: Remove system JDKs
46 | run: |
47 | sudo rm -rf /usr/lib/jvm/*
48 | unset JAVA_HOME
49 | export PATH=$(echo "$PATH" | tr ':' '\n' | grep -v '/usr/lib/jvm' | paste -sd:)
50 | - uses: actions/checkout@v6
51 | - name: Pre-Build Steps
52 | uses: micronaut-projects/github-actions/graalvm/pre-build@master
53 | id: pre-build
54 | with:
55 | java: ${{ matrix.java }}
56 | distribution: ${{ matrix.distribution }}
57 | nativeTestTask: ${{ matrix.native_test_task }}
58 | - name: Build Steps
59 | uses: micronaut-projects/github-actions/graalvm/build@master
60 | id: build
61 | env:
62 | GH_TOKEN_PUBLIC_REPOS_READONLY: ${{ secrets.GH_TOKEN_PUBLIC_REPOS_READONLY }}
63 | GH_USERNAME: ${{ secrets.GH_USERNAME }}
64 | GRAALVM_QUICK_BUILD: true
65 | with:
66 | nativeTestTask: ${{ matrix.native_test_task }}
67 | - name: Post-Build Steps
68 | uses: micronaut-projects/github-actions/graalvm/post-build@master
69 | id: post-build
70 | with:
71 | java: ${{ matrix.java }}
72 |
--------------------------------------------------------------------------------
/elasticsearch/src/test/groovy/io/micronaut/elasticsearch/ElasticsearchAuthorizationSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2018 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch
17 |
18 | import co.elastic.clients.elasticsearch.ElasticsearchClient
19 | import co.elastic.clients.elasticsearch.core.InfoResponse
20 | import io.micronaut.context.ApplicationContext
21 | import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy
22 | import org.testcontainers.elasticsearch.ElasticsearchContainer
23 | import spock.lang.Requires
24 | import spock.lang.Specification
25 |
26 | @Requires({ sys['elasticsearch.version'] })
27 | class ElasticsearchAuthorizationSpec extends Specification {
28 |
29 | static final String ELASTICSEARCH_VERSION = System.getProperty("elasticsearch.version")
30 | static final String ELASTICSEARCH_USERNAME = "elastic"
31 | static final String ELASTICSEARCH_PASSWORD = "changeme"
32 | static final ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:$ELASTICSEARCH_VERSION")
33 | .withExposedPorts(9200)
34 | .withEnv("xpack.security.enabled", "false")
35 | .withPassword(ELASTICSEARCH_PASSWORD)
36 | .waitingFor(new LogMessageWaitStrategy().withRegEx(".*\"message\":\"started.*"))
37 |
38 | void setupSpec() {
39 | container.start()
40 | }
41 |
42 | void cleanupSpec() {
43 | container.stop()
44 | }
45 |
46 | void "Test Elasticsearch authorization"() {
47 |
48 | given:
49 |
50 | String token = new String(Base64.getEncoder().encode((ELASTICSEARCH_USERNAME + ':' + ELASTICSEARCH_PASSWORD).getBytes()))
51 |
52 | ApplicationContext applicationContext = ApplicationContext.run(
53 | 'elasticsearch.httpHosts': "http://${container.httpHostAddress}",
54 | 'elasticsearch.default-headers': "Authorization:Basic $token"
55 | )
56 |
57 | expect:
58 | applicationContext.containsBean(ElasticsearchClient)
59 | applicationContext.getBean(ElasticsearchClient).ping()
60 | InfoResponse response = applicationContext.getBean(ElasticsearchClient).info()
61 | System.out.println(String.format("cluster: %s, node: %s, version: %s %s", response.clusterName(), response.name(), response.version().number(), response.version().buildDate()))
62 |
63 | cleanup:
64 | applicationContext.close()
65 |
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 |
74 |
75 | @rem Execute Gradle
76 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
77 |
78 | :end
79 | @rem End local scope for the variables with windows NT shell
80 | if %ERRORLEVEL% equ 0 goto mainEnd
81 |
82 | :fail
83 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
84 | rem the _cmd.exe /c_ return code!
85 | set EXIT_CODE=%ERRORLEVEL%
86 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
87 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
88 | exit /b %EXIT_CODE%
89 |
90 | :mainEnd
91 | if "%OS%"=="Windows_NT" endlocal
92 |
93 | :omega
94 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Code or Documentation to Micronaut
2 |
3 | Sign the [Contributor License Agreement (CLA)](https://cla-assistant.io/micronaut-projects/micronaut-project-template). This is required before any of your code or pull-requests are accepted.
4 |
5 | ## Finding Issues to Work on
6 |
7 | If you are interested in contributing to Micronaut and are looking for issues to work on, take a look at the issues tagged with [help wanted](https://github.com/micronaut-projects/micronaut-elasticsearch/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+help+wanted%22).
8 |
9 | ## JDK Setup
10 |
11 | Micronaut Elasticsearch currently requires JDK 8.
12 |
13 | ## IDE Setup
14 |
15 | Micronaut Elasticsearch can be imported into IntelliJ IDEA by opening the `build.gradle` file.
16 |
17 | ## Docker Setup
18 |
19 | Micronaut Elasticsearch tests currently require Docker to be installed.
20 |
21 | ## Running Tests
22 |
23 | To run the tests, use `./gradlew check`.
24 |
25 | ## Building Documentation
26 |
27 | The documentation sources are located at `src/main/docs/guide`.
28 |
29 | To build the documentation, run `./gradlew publishGuide` (or `./gradlew pG`), then open `build/docs/index.html`
30 |
31 | To also build the Javadocs, run `./gradlew docs`.
32 |
33 | ## Working on the code base
34 |
35 | If you use IntelliJ IDEA, you can import the project using the Intellij Gradle Tooling ("File / Import Project" and selecting the "settings.gradle" file).
36 |
37 | To get a local development version of Micronaut Elasticsearch working, first run the `publishToMavenLocal` task.
38 |
39 | ```
40 | ./gradlew pTML
41 | ```
42 |
43 | You can then reference the version specified with `projectVersion` in `gradle.properties` in a test project's `build.gradle` or `pom.xml`. If you use Gradle, add the `mavenLocal` repository (Maven automatically does this):
44 |
45 | ```
46 | repositories {
47 | mavenLocal()
48 | mavenCentral()
49 | }
50 | ```
51 |
52 | ## Creating a pull request
53 |
54 | Once you are satisfied with your changes:
55 |
56 | - Commit your changes in your local branch
57 | - Push your changes to your remote branch on GitHub
58 | - Send us a [pull request](https://help.github.com/articles/creating-a-pull-request)
59 |
60 | ## Checkstyle
61 |
62 | We want to keep the code clean, following good practices about organization, Javadoc, and style as much as possible.
63 |
64 | Micronaut Elasticsearch uses [Checkstyle](https://checkstyle.sourceforge.io/) to make sure that the code follows those standards. The configuration is defined in `config/checkstyle/checkstyle.xml`. To execute Checkstyle, run:
65 |
66 | ```
67 | ./gradlew :checkstyleMain
68 | ```
69 |
70 | Before starting to contribute new code we recommended that you install the IntelliJ [CheckStyle-IDEA](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea) plugin and configure it to use Micronaut's checkstyle configuration file.
71 |
72 | IntelliJ will mark in red the issues Checkstyle finds. For example:
73 |
74 | 
75 |
76 | In this case, to fix the issues, we need to:
77 |
78 | - Add one empty line before `package` in line 16
79 | - Add the Javadoc for the constructor in line 27
80 | - Add an space after `if` in line 34
81 |
82 | The plugin also adds a new tab in the bottom of the IDE to run Checkstyle and show errors and warnings. We recommend that you run the report and fix all issues before submitting a pull request.
83 |
--------------------------------------------------------------------------------
/elasticsearch/src/test/groovy/io/micronaut/elasticsearch/health/ElasticsearchClientHealthIndicatorSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2018 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.micronaut.elasticsearch.health
18 |
19 | import groovy.json.JsonSlurper
20 | import io.micronaut.context.ApplicationContext
21 | import io.micronaut.context.exceptions.NoSuchBeanException
22 | import io.micronaut.elasticsearch.DefaultElasticsearchConfigurationProperties
23 | import io.micronaut.health.HealthStatus
24 | import io.micronaut.management.health.indicator.HealthResult
25 | import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy
26 | import org.testcontainers.elasticsearch.ElasticsearchContainer
27 | import reactor.core.publisher.Flux
28 | import spock.lang.Requires
29 | import spock.lang.Specification
30 | /**
31 | * @author Puneet Behl
32 | * @since 1.0.0
33 | */
34 | @Requires({ sys['elasticsearch.version'] })
35 | class ElasticsearchClientHealthIndicatorSpec extends Specification {
36 |
37 | final static String ELASTICSEARCH_VERSION = System.getProperty("elasticsearch.version")
38 |
39 | void "test elasticsearch health indicator"() {
40 | given:
41 | ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:$ELASTICSEARCH_VERSION")
42 | .withExposedPorts(9200)
43 | .withEnv("xpack.security.enabled", "false")
44 | .waitingFor(new LogMessageWaitStrategy().withRegEx(".*\"message\":\"started.*"))
45 | container.start()
46 |
47 | ApplicationContext applicationContext = ApplicationContext.run('elasticsearch.httpHosts': "http://$container.httpHostAddress")
48 |
49 | expect:
50 | applicationContext.containsBean(DefaultElasticsearchConfigurationProperties)
51 |
52 | when:
53 | ElasticsearchClientHealthIndicator indicator = applicationContext.getBean(ElasticsearchClientHealthIndicator)
54 | HealthResult result = Flux.from(indicator.getResult()).blockFirst()
55 |
56 | then:
57 | result.status == HealthStatus.UP
58 | new JsonSlurper().parseText((String) result.details).status == co.elastic.clients.elasticsearch._types.HealthStatus.Green.name().toLowerCase(Locale.ENGLISH)
59 |
60 | when:
61 | container.stop()
62 | result = Flux.from(indicator.getResult()).blockFirst()
63 |
64 | then:
65 | result.status == HealthStatus.DOWN
66 |
67 | cleanup:
68 | applicationContext?.stop()
69 | container.stop()
70 | }
71 |
72 | void "test that ElasticsearchClientHealthIndicator is not created when the endpoints.health.elasticsearch.rest.high.level.enabled is set to false "() {
73 | ApplicationContext applicationContext = ApplicationContext.run(
74 | 'elasticsearch.httpHosts': "http://localhost:9200",
75 | 'endpoints.health.elasticsearch.enabled': "false"
76 | )
77 |
78 | when:
79 | applicationContext.getBean(ElasticsearchClientHealthIndicator)
80 |
81 | then:
82 | thrown(NoSuchBeanException)
83 |
84 | cleanup:
85 | applicationContext?.stop()
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/docs/guide/configuration.adoc:
--------------------------------------------------------------------------------
1 | == Configuring the Elasticsearch Client
2 | [TIP]
3 | .Using the CLI
4 | ====
5 | If you are creating your project using the Micronaut CLI, supply the `elasticsearch` feature to configure the https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html[ElasticsearchClient^] in your project:
6 | ----
7 | $ mn create-app my-app --features elasticsearch
8 | ----
9 | ====
10 |
11 | To configure the https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html[ElasticsearchClient^] you should first add `elasticsearch` module to your classpath:
12 |
13 | [source,groovy]
14 | .build.gradle
15 | ----
16 | implementation("io.micronaut.elasticsearch:micronaut-elasticsearch")
17 | ----
18 |
19 | You should then configure the `httpHosts` of the Elasticsearch server you wish to communicate with in `application.yml` as:
20 |
21 | [source,yaml]
22 | .application.yml
23 | ----
24 | elasticsearch:
25 | httpHosts: "http://localhost:9200,http://127.0.0.2:9200"
26 | ----
27 |
28 | See the API for api:elasticsearch.DefaultElasticsearchConfigurationProperties[] for more information on the available configuration options.
29 |
30 | Once you have the above configuration in place then you can inject the `co.elastic.clients.elasticsearch.ElasticsearchClient`, the `co.elastic.clients.elasticsearch.ElasticsearchAsyncClient` or the `org.elasticsearch.client.RestClient` bean. The following is the simplest way to get Elasticsearch information using the ElasticsearchClient:
31 |
32 | [source,groovy]
33 | ----
34 | include::test-suite-groovy/src/test/groovy/io/micronaut/docs/configuration/elasticsearch/ElasticsearchSpec.groovy[tags=query,indent=0]
35 | ----
36 |
37 | <1> `client` is an instance of the `co.elastic.clients.elasticsearch.ElasticsearchClient` bean.
38 |
39 | For more information on executing different operations using ElasticsearchClient please read the https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html[Elasticsearch Documentation^].
40 |
41 | == Modify the Default Request Configurations
42 |
43 | Often times you want to change the default configurations. To achieve this Micronaut, includes the ability to change the default request configurations. You can set the default request configurations under key `elasticsearch.request.default` as:
44 |
45 | [source,yaml]
46 | .application.yml
47 | ----
48 | elasticsearch:
49 | httpHosts: http://localhost:9200,http://127.0.0.2:9200
50 | request:
51 | default:
52 | expectContinueEnabled: true
53 | localAddress: 198.57.151.22
54 | ----
55 |
56 | See the API https://hc.apache.org/httpcomponents-client-5.2.x/current/httpclient5/apidocs/org/apache/hc/client5/http/config/RequestConfig.Builder.html[RequestConfig.Builder^] for more information on the available configuration options.
57 |
58 | == Modify the HTTP Client Configurations
59 |
60 | To modify the HTTP Client configurations (e.g. request timeouts, authentication, or anything that the https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.html[HttpAsyncClientBuilder^] allows to set). You can define a bean using https://docs.micronaut.io/latest/api/io/micronaut/context/annotation/Factory.html[Factory] which replaces `org.apache.http.impl.nio.client.HttpAsyncClientBuilder`.
61 |
62 | Following is an example to change the default credentials provider:
63 |
64 | [source,groovy]
65 | ----
66 | include::test-suite-groovy/src/test/groovy/io/micronaut/docs/configuration/elasticsearch/ElasticsearchSpec.groovy[tags=httpClientFactoryImports,indent=0]
67 | include::test-suite-groovy/src/test/groovy/io/micronaut/docs/configuration/elasticsearch/ElasticsearchSpec.groovy[tags=singletonImports,indent=0]
68 | include::test-suite-groovy/src/test/groovy/io/micronaut/docs/configuration/elasticsearch/ElasticsearchSpec.groovy[tags=httpClientFactory,indent=0]
69 | ----
70 |
71 | === Logging
72 |
73 | Elasticsearch uses log4j for logging but Micronaut uses slf4j with Logback. To make it work properly, add the following dependency:
74 |
75 | dependency:org.slf4j:log4j-over-slf4j[version="1.7.30", scope="runtimeOnly"]
76 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/DefaultElasticsearchConfigurationProperties.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch;
17 |
18 | import io.micronaut.context.annotation.ConfigurationBuilder;
19 | import io.micronaut.context.annotation.ConfigurationProperties;
20 | import io.micronaut.context.annotation.Requires;
21 | import org.apache.http.Header;
22 | import org.apache.http.HttpHost;
23 | import org.apache.http.client.config.RequestConfig;
24 | import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
25 | import org.elasticsearch.client.NodeSelector;
26 | import org.elasticsearch.client.RestClientBuilder;
27 |
28 | import jakarta.inject.Inject;
29 | import java.util.Collections;
30 |
31 | /**
32 | * Default configurations for Elasticsearch.
33 | *
34 | * @author lishuai
35 | * @author Puneet Behl
36 | * @since 1.0.0
37 | */
38 | @Requires(classes = RestClientBuilder.class)
39 | @ConfigurationProperties(ElasticsearchSettings.PREFIX)
40 | public class DefaultElasticsearchConfigurationProperties implements DefaultElasticsearchConfiguration {
41 |
42 | @SuppressWarnings("WeakerAccess")
43 | protected HttpAsyncClientBuilder httpAsyncClientBuilder;
44 |
45 | /**
46 | * The default request configurations.
47 | */
48 | @ConfigurationBuilder(configurationPrefix = "request.default")
49 | @SuppressWarnings("WeakerAccess")
50 | protected RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
51 |
52 | private int maxRetryTimeoutMillis;
53 | private NodeSelector nodeSelector;
54 | private HttpHost[] httpHosts = Collections.singletonList(ElasticsearchSettings.DEFAULT_HOST).toArray(new HttpHost[1]);
55 | private Header[] defaultHeaders;
56 |
57 | @Override
58 | public HttpHost[] getHttpHosts() {
59 | return this.httpHosts;
60 | }
61 |
62 | @Override
63 | public Header[] getDefaultHeaders() {
64 | return this.defaultHeaders;
65 | }
66 |
67 | @Override
68 | public int getMaxRetryTimeoutMillis() {
69 | return this.maxRetryTimeoutMillis;
70 | }
71 |
72 | @Override
73 | public NodeSelector getNodeSelector() {
74 | return this.nodeSelector;
75 | }
76 |
77 | @Override
78 | public RequestConfig.Builder getRequestConfigBuilder() {
79 | return this.requestConfigBuilder;
80 | }
81 |
82 | @Override
83 | public HttpAsyncClientBuilder getHttpAsyncClientBuilder() {
84 | return httpAsyncClientBuilder;
85 | }
86 |
87 | /**
88 | * @param httpHosts One or more hosts that client will connect to.
89 | */
90 | public void setHttpHosts(HttpHost[] httpHosts) {
91 | this.httpHosts = httpHosts;
92 | }
93 |
94 | /**
95 | * @param defaultHeaders The defaults {@link Header} to sent with each request.
96 | */
97 | public void setDefaultHeaders(Header[] defaultHeaders) {
98 | this.defaultHeaders = defaultHeaders;
99 | }
100 |
101 | /**
102 | * @param maxRetryTimeoutMillis The maximum retry timeout in millis.
103 | */
104 | public void setMaxRetryTimeoutMillis(int maxRetryTimeoutMillis) {
105 | this.maxRetryTimeoutMillis = maxRetryTimeoutMillis;
106 | }
107 |
108 | /**
109 | * @param nodeSelector The {@link NodeSelector} to be used, in case of multiple nodes.
110 | */
111 | public void setNodeSelector(NodeSelector nodeSelector) {
112 | this.nodeSelector = nodeSelector;
113 | }
114 |
115 | /**
116 | * @param httpAsyncClientBuilder The {@link HttpAsyncClientBuilder} bean
117 | */
118 | @Inject
119 | public void setHttpAsyncClientBuilder(HttpAsyncClientBuilder httpAsyncClientBuilder) {
120 | this.httpAsyncClientBuilder = httpAsyncClientBuilder;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/DefaultElasticsearchClientFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch;
17 |
18 | import io.micronaut.context.annotation.Bean;
19 | import io.micronaut.context.annotation.Factory;
20 | import io.micronaut.context.annotation.Requires;
21 | import io.micronaut.core.util.ArrayUtils;
22 | import jakarta.inject.Singleton;
23 |
24 | import com.fasterxml.jackson.databind.ObjectMapper;
25 |
26 | import org.elasticsearch.client.RestClient;
27 | import org.elasticsearch.client.RestClientBuilder;
28 |
29 | import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
30 | import co.elastic.clients.elasticsearch.ElasticsearchClient;
31 | import co.elastic.clients.json.jackson.JacksonJsonpMapper;
32 | import co.elastic.clients.transport.ElasticsearchTransport;
33 | import co.elastic.clients.transport.rest_client.RestClientTransport;
34 |
35 | /**
36 | * The default Factory for creating Elasticsearch client.
37 | *
38 | * @author lishuai
39 | * @author Puneet Behl
40 | * @since 1.0.0
41 | */
42 | @Requires(beans = DefaultElasticsearchConfigurationProperties.class)
43 | @Factory
44 | public class DefaultElasticsearchClientFactory {
45 |
46 | /**
47 | * @param elasticsearchConfiguration The {@link DefaultElasticsearchConfigurationProperties} object
48 | * @return The Elasticsearch Rest Client
49 | */
50 | @Bean(preDestroy = "close")
51 | RestClient restClient(DefaultElasticsearchConfigurationProperties elasticsearchConfiguration) {
52 | return restClientBuilder(elasticsearchConfiguration).build();
53 | }
54 |
55 | /**
56 | * @param transport The {@link ElasticsearchTransport} object.
57 | * @return The ElasticsearchClient.
58 | * @since 4.2.0
59 | */
60 | @Singleton
61 | ElasticsearchClient elasticsearchClient(ElasticsearchTransport transport) {
62 | return new ElasticsearchClient(transport);
63 | }
64 |
65 | /**
66 | * @param transport The {@link ElasticsearchTransport} object.
67 | * @return The ElasticsearchAsyncClient.
68 | * @since 4.2.0
69 | */
70 | @Singleton
71 | ElasticsearchAsyncClient elasticsearchAsyncClient(ElasticsearchTransport transport) {
72 | return new ElasticsearchAsyncClient(transport);
73 | }
74 |
75 | /**
76 | * @param elasticsearchConfiguration The {@link DefaultElasticsearchConfigurationProperties} object.
77 | * @param objectMapper The {@link ObjectMapper} object.
78 | * @return The {@link ElasticsearchTransport}.
79 | * @since 4.2.0
80 | */
81 | @Singleton
82 | @Bean(preDestroy = "close")
83 | ElasticsearchTransport elasticsearchTransport(DefaultElasticsearchConfigurationProperties elasticsearchConfiguration, ObjectMapper objectMapper) {
84 | RestClient restClient = restClientBuilder(elasticsearchConfiguration).build();
85 |
86 | ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper(objectMapper));
87 | return transport;
88 | }
89 |
90 | /**
91 | * @param elasticsearchConfiguration The {@link DefaultElasticsearchConfigurationProperties} object
92 | * @return The {@link RestClientBuilder}
93 | */
94 | protected RestClientBuilder restClientBuilder(DefaultElasticsearchConfigurationProperties elasticsearchConfiguration) {
95 | RestClientBuilder builder = RestClient.builder(elasticsearchConfiguration.getHttpHosts())
96 | .setRequestConfigCallback(requestConfigBuilder -> {
97 | requestConfigBuilder = elasticsearchConfiguration.requestConfigBuilder;
98 | return requestConfigBuilder;
99 | })
100 | .setHttpClientConfigCallback(httpClientBuilder -> {
101 | httpClientBuilder = elasticsearchConfiguration.httpAsyncClientBuilder;
102 | return httpClientBuilder;
103 | });
104 |
105 | if (ArrayUtils.isNotEmpty(elasticsearchConfiguration.getDefaultHeaders())) {
106 | builder.setDefaultHeaders(elasticsearchConfiguration.getDefaultHeaders());
107 | }
108 |
109 | return builder;
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/.github/workflows/gradle.yml:
--------------------------------------------------------------------------------
1 | # WARNING: Do not edit this file directly. Instead, go to:
2 | #
3 | # https://github.com/micronaut-projects/micronaut-project-template/tree/master/.github/workflows
4 | #
5 | # and edit them there. Note that it will be sync'ed to all the Micronaut repos
6 | name: Java CI
7 | on:
8 | push:
9 | branches:
10 | - master
11 | - '[0-9]+.[0-9]+.x'
12 | pull_request:
13 | branches:
14 | - master
15 | - '[0-9]+.[0-9]+.x'
16 | jobs:
17 | build:
18 | if: github.repository != 'micronaut-projects/micronaut-project-template'
19 | runs-on: ubuntu-latest
20 | strategy:
21 | matrix:
22 | java: ['21', '25']
23 | env:
24 | DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
25 | DEVELOCITY_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
26 | DEVELOCITY_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
27 | GH_TOKEN_PUBLIC_REPOS_READONLY: ${{ secrets.GH_TOKEN_PUBLIC_REPOS_READONLY }}
28 | GH_USERNAME: ${{ secrets.GH_USERNAME }}
29 | TESTCONTAINERS_RYUK_DISABLED: true
30 | PREDICTIVE_TEST_SELECTION: "${{ github.event_name == 'pull_request' && 'true' || 'false' }}"
31 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33 | OSS_INDEX_USERNAME: ${{ secrets.OSS_INDEX_USERNAME }}
34 | OSS_INDEX_PASSWORD: ${{ secrets.OSS_INDEX_PASSWORD }}
35 | steps:
36 | # https://github.com/actions/virtual-environments/issues/709
37 | - name: Remove system JDKs
38 | run: |
39 | sudo rm -rf /usr/lib/jvm/*
40 | unset JAVA_HOME
41 | export PATH=$(echo "$PATH" | tr ':' '\n' | grep -v '/usr/lib/jvm' | paste -sd:)
42 | - name: "🗑 Free disk space"
43 | run: |
44 | sudo rm -rf "/usr/local/share/boost"
45 | sudo rm -rf "$AGENT_TOOLSDIRECTORY"
46 | sudo apt-get clean
47 | df -h
48 |
49 | - name: "📥 Checkout repository"
50 | uses: actions/checkout@v6
51 | with:
52 | fetch-depth: 0
53 |
54 | - name: "🔧 Setup GraalVM CE"
55 | uses: graalvm/setup-graalvm@v1.4.4
56 | with:
57 | distribution: 'graalvm'
58 | java-version: ${{ matrix.java }}
59 | github-token: ${{ secrets.GITHUB_TOKEN }}
60 |
61 | - name: "🔧 Setup Gradle"
62 | uses: gradle/actions/setup-gradle@v5
63 |
64 | - name: "❓ Optional setup step"
65 | run: |
66 | [ -f ./setup.sh ] && ./setup.sh || [ ! -f ./setup.sh ]
67 |
68 | - name: "🚔 Sonatype Scan"
69 | if: env.OSS_INDEX_PASSWORD != '' && matrix.java == '21'
70 | id: sonatypescan
71 | run: |
72 | ./gradlew ossIndexAudit --no-parallel --info
73 |
74 | - name: "🛠 Build with Gradle"
75 | id: gradle
76 | run: |
77 | ./gradlew check jacocoReport --no-daemon --continue
78 |
79 | - name: "🔎 Run static analysis"
80 | if: env.SONAR_TOKEN != '' && matrix.java == '21'
81 | run: |
82 | ./gradlew sonar --no-parallel --continue
83 |
84 | - name: "📊 Publish Test Report"
85 | if: always()
86 | uses: mikepenz/action-junit-report@v6
87 | with:
88 | check_name: Java CI / Test Report (${{ matrix.java }})
89 | report_paths: '**/build/test-results/test/TEST-*.xml'
90 | check_retries: 'true'
91 |
92 | - name: "📜 Upload binary compatibility check results"
93 | if: matrix.java == '21'
94 | uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
95 | with:
96 | name: binary-compatibility-reports
97 | path: "**/build/reports/binary-compatibility-*.html"
98 |
99 | - name: "📦 Publish to Sonatype Snapshots"
100 | if: success() && github.event_name == 'push' && matrix.java == '21'
101 | env:
102 | SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
103 | SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
104 | run: ./gradlew publishToSonatype docs --no-daemon
105 |
106 | - name: "❓ Determine docs target repository"
107 | uses: haya14busa/action-cond@v1
108 | id: docs_target
109 | with:
110 | cond: ${{ github.repository == 'micronaut-projects/micronaut-core' }}
111 | if_true: "micronaut-projects/micronaut-docs"
112 | if_false: ${{ github.repository }}
113 |
114 | - name: "📑 Publish to Github Pages"
115 | if: success() && github.event_name == 'push' && matrix.java == '21'
116 | uses: micronaut-projects/github-pages-deploy-action@master
117 | env:
118 | TARGET_REPOSITORY: ${{ steps.docs_target.outputs.value }}
119 | GH_TOKEN: ${{ secrets.GH_TOKEN }}
120 | BRANCH: gh-pages
121 | FOLDER: build/docs
122 |
123 | - name: "❓ Optional cleanup step"
124 | run: |
125 | [ -f ./cleanup.sh ] && ./cleanup.sh || [ ! -f ./cleanup.sh ]
126 |
--------------------------------------------------------------------------------
/elasticsearch/src/main/java/io/micronaut/elasticsearch/health/ElasticsearchClientHealthIndicator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.micronaut.elasticsearch.health;
17 |
18 | import io.micronaut.context.annotation.Requires;
19 | import io.micronaut.health.HealthStatus;
20 | import io.micronaut.management.endpoint.health.HealthEndpoint;
21 | import io.micronaut.management.health.indicator.HealthIndicator;
22 | import io.micronaut.management.health.indicator.HealthResult;
23 | import org.reactivestreams.Publisher;
24 |
25 | import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
26 | import co.elastic.clients.elasticsearch.cluster.HealthResponse;
27 | import jakarta.inject.Singleton;
28 |
29 | import static io.micronaut.health.HealthStatus.DOWN;
30 | import static io.micronaut.health.HealthStatus.UP;
31 | import java.util.Locale;
32 |
33 | /**
34 | * A {@link HealthIndicator} for Elasticsearch that uses an automatically-configured high-level REST client, injected as a dependency, to communicate
35 | * with Elasticsearch.
36 | *
37 | * @author Puneet Behl
38 | * @author Robyn Dalgleish
39 | * @since 1.0.0
40 | */
41 | @Requires(beans = HealthEndpoint.class)
42 | @Requires(property = HealthEndpoint.PREFIX + ".elasticsearch.enabled", notEquals = "false")
43 | @Singleton
44 | public class ElasticsearchClientHealthIndicator implements HealthIndicator {
45 |
46 | private static final String NAME = "elasticsearchclient";
47 |
48 | private final ElasticsearchAsyncClient client;
49 |
50 | /**
51 | * Constructor.
52 | *
53 | * @param client The Elasticsearch high level REST client.
54 | */
55 | public ElasticsearchClientHealthIndicator(ElasticsearchAsyncClient client) {
56 | this.client = client;
57 | }
58 |
59 | /**
60 | * Tries to call the cluster info API on Elasticsearch to obtain information about the cluster. If the call succeeds, the Elasticsearch cluster
61 | * health status (GREEN / YELLOW / RED) will be included in the health indicator details.
62 | *
63 | * @return A positive health result UP if the cluster can be communicated with and is in either GREEN or YELLOW status. A negative health result
64 | * DOWN if the cluster cannot be communicated with or is in RED status.
65 | */
66 | @Override
67 | public Publisher getResult() {
68 | return (subscriber -> client.cluster().health()
69 | .handle((health, exception) -> {
70 | final HealthResult.Builder resultBuilder = HealthResult.builder(NAME);
71 | if (exception != null) {
72 | subscriber.onNext(resultBuilder.status(DOWN).exception(exception).build());
73 | subscriber.onComplete();
74 | } else {
75 | HealthStatus status = health.status() == co.elastic.clients.elasticsearch._types.HealthStatus.Red ? DOWN : UP;
76 | subscriber.onNext(resultBuilder.status(status).details(healthResultDetails(health)).build());
77 | subscriber.onComplete();
78 | }
79 | return health;
80 | }));
81 | }
82 |
83 | private String healthResultDetails(HealthResponse response) {
84 | return "{"
85 | + "\"cluster_name\":\"" + response.clusterName() + "\","
86 | + "\"status\":\"" + response.status().name().toLowerCase(Locale.ENGLISH) + "\","
87 | + "\"timed_out\":" + response.timedOut() + ","
88 | + "\"number_of_nodes\":" + response.numberOfNodes() + ","
89 | + "\"number_of_data_nodes\":" + response.numberOfDataNodes() + ","
90 | + "\"number_of_pending_tasks\":" + response.numberOfPendingTasks() + ","
91 | + "\"number_of_in_flight_fetch\":" + response.numberOfInFlightFetch() + ","
92 | + "\"task_max_waiting_in_queue\":\"" + response.taskMaxWaitingInQueueMillis() + "\","
93 | + "\"task_max_waiting_in_queue_millis\":" + response.taskMaxWaitingInQueueMillis() + ","
94 | + "\"active_shards_percent_as_number\":\"" + response.activeShardsPercentAsNumber() + "\","
95 | + "\"active_primary_shards\":" + response.activePrimaryShards() + ","
96 | + "\"active_shards\":" + response.activeShards() + ","
97 | + "\"relocating_shards\":" + response.relocatingShards() + ","
98 | + "\"initializing_shards\":" + response.initializingShards() + ","
99 | + "\"unassigned_shards\":" + response.unassignedShards() + ","
100 | + "\"delayed_unassigned_shards\":" + response.delayedUnassignedShards()
101 | + "}";
102 | }
103 | }
104 |
105 |
106 |
--------------------------------------------------------------------------------
/test-suite-groovy/src/test/groovy/io/micronaut/docs/configuration/elasticsearch/ElasticsearchSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2018 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.micronaut.docs.configuration.elasticsearch
18 |
19 | import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient
20 | import co.elastic.clients.elasticsearch.ElasticsearchClient
21 | import co.elastic.clients.elasticsearch.core.InfoResponse
22 | import io.micronaut.context.ApplicationContext
23 | import io.micronaut.context.annotation.Factory
24 | import io.micronaut.context.annotation.Replaces
25 | import io.micronaut.elasticsearch.DefaultElasticsearchConfigurationProperties
26 | //tag::httpClientFactoryImports[]
27 |
28 | import jakarta.inject.Singleton
29 | import org.apache.http.auth.AuthScope
30 | //end::httpClientFactoryImports[]
31 |
32 | import org.apache.http.auth.UsernamePasswordCredentials
33 | import org.apache.http.client.CredentialsProvider
34 | import org.apache.http.impl.client.BasicCredentialsProvider
35 | import org.apache.http.impl.nio.client.HttpAsyncClientBuilder
36 | import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy
37 | import org.testcontainers.elasticsearch.ElasticsearchContainer
38 | import spock.lang.Requires
39 | import spock.lang.Shared
40 | import spock.lang.Specification
41 | //tag::singletonImports[]
42 | //end::singletonImports[]
43 | /**
44 | * @author Puneet Behl
45 | * @since 1.0.0
46 | */
47 | @Requires({ sys['elasticsearch.version'] })
48 | class ElasticsearchSpec extends Specification {
49 |
50 | // tag::es-testcontainer[]
51 | final static String ELASTICSEARCH_VERSION = System.getProperty("elasticsearch.version")
52 |
53 | @Shared
54 | static final ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:$ELASTICSEARCH_VERSION")
55 | .withExposedPorts(9200)
56 | .withEnv("xpack.security.enabled", "false")
57 | .waitingFor(new LogMessageWaitStrategy().withRegEx(".*\"message\":\"started.*"))
58 | // end::es-testcontainer[]
59 |
60 | void setupSpec() {
61 | container.start()
62 | }
63 |
64 | void cleanupSpec() {
65 | container.stop()
66 | }
67 |
68 | void "Test simple info for Elasticsearch stats using the ElasticsearchClient"() {
69 | given:
70 | ApplicationContext applicationContext = ApplicationContext.run("elasticsearch.httpHosts": "http://$container.httpHostAddress", "test")
71 | String stats
72 |
73 | when:
74 | ElasticsearchClient client = applicationContext.getBean(ElasticsearchClient)
75 | //tag::query[]
76 | InfoResponse response =
77 | client.info() // <1>
78 | //end::query[]
79 |
80 | then:
81 | "docker-cluster" == response.clusterName()
82 | ELASTICSEARCH_VERSION == response.version().number()
83 |
84 | cleanup:
85 | applicationContext.close()
86 | }
87 |
88 | void "Test simple info for Elasticsearch stats using the ElasticsearchAsyncClient"() {
89 | given:
90 | ApplicationContext applicationContext = ApplicationContext.run("elasticsearch.httpHosts": "http://$container.httpHostAddress", "test")
91 | String stats
92 |
93 | when:
94 | ElasticsearchAsyncClient client = applicationContext.getBean(ElasticsearchAsyncClient)
95 | InfoResponse response =
96 | client.info().get() // <1>
97 |
98 | then:
99 | "docker-cluster" == response.clusterName()
100 | ELASTICSEARCH_VERSION == response.version().number()
101 |
102 | cleanup:
103 | applicationContext.close()
104 | }
105 |
106 | void "Test overiding HttpAsyncClientBuilder bean"() {
107 |
108 | when:
109 | ApplicationContext applicationContext = ApplicationContext.run("elasticsearch.httpHosts": "http://127.0.0.1:9200,http://127.0.1.1:9200")
110 |
111 | then:
112 | applicationContext.containsBean(HttpAsyncClientBuilder)
113 | applicationContext.getBean(DefaultElasticsearchConfigurationProperties).httpAsyncClientBuilder
114 |
115 | cleanup:
116 | applicationContext.close()
117 |
118 | }
119 |
120 | //tag::httpClientFactory[]
121 | @Factory
122 | static class HttpAsyncClientBuilderFactory {
123 |
124 | @Replaces(HttpAsyncClientBuilder.class)
125 | @Singleton
126 | HttpAsyncClientBuilder builder() {
127 | final CredentialsProvider credentialsProvider = new BasicCredentialsProvider()
128 | credentialsProvider.setCredentials(AuthScope.ANY,
129 | new UsernamePasswordCredentials("user", "password"))
130 |
131 | return HttpAsyncClientBuilder.create()
132 | .setDefaultCredentialsProvider(credentialsProvider)
133 | }
134 | }
135 | //end::httpClientFactory[]
136 | }
137 |
--------------------------------------------------------------------------------
/elasticsearch/src/test/groovy/io/micronaut/elasticsearch/ElasticsearchMappingSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2018 original authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.micronaut.elasticsearch
18 |
19 | import co.elastic.clients.elasticsearch.ElasticsearchClient
20 | import co.elastic.clients.elasticsearch._types.Result
21 | import co.elastic.clients.elasticsearch.core.*
22 | import co.elastic.clients.elasticsearch.indices.ExistsRequest
23 | import io.micronaut.context.ApplicationContext
24 | import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy
25 | import org.testcontainers.elasticsearch.ElasticsearchContainer
26 | import spock.lang.Requires
27 | import spock.lang.Specification
28 |
29 | /**
30 | * @author lishuai
31 | * @author Puneet Behl
32 | * @since 1.0.1
33 | */
34 | @Requires({ sys['elasticsearch.version'] })
35 | class ElasticsearchMappingSpec extends Specification {
36 |
37 | final static String ELASTICSEARCH_VERSION = System.getProperty("elasticsearch.version")
38 | static final ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:$ELASTICSEARCH_VERSION")
39 | .withExposedPorts(9200)
40 | .withEnv("xpack.security.enabled", "false")
41 | .waitingFor(new LogMessageWaitStrategy().withRegEx(".*\"message\":\"started.*"))
42 |
43 | void setupSpec() {
44 | container.start()
45 | }
46 |
47 | void cleanupSpec() {
48 | container.stop()
49 | }
50 |
51 |
52 | void "Test Elasticsearch connection"() {
53 | given:
54 | ApplicationContext applicationContext = ApplicationContext.run('elasticsearch.httpHosts': 'http://' + container.httpHostAddress)
55 |
56 | expect:
57 | applicationContext.containsBean(ElasticsearchClient)
58 | applicationContext.getBean(ElasticsearchClient).ping()
59 | InfoResponse response = applicationContext.getBean(ElasticsearchClient).info()
60 | System.out.println(String.format("cluser: %s, node: %s, version: %s %s", response.clusterName(), response.name(), response.version().number(), response.version().buildDate()))
61 |
62 | cleanup:
63 | applicationContext.close()
64 | }
65 |
66 | void "Test Elasticsearch(8.x) Mapping API"() {
67 | given:
68 | ApplicationContext applicationContext = ApplicationContext.run('elasticsearch.httpHosts': 'http://' + container.getHttpHostAddress())
69 | ElasticsearchClient client = applicationContext.getBean(ElasticsearchClient)
70 |
71 | expect: "Make sure the version of ES is up to date because these tests may cause unexpected results"
72 | ELASTICSEARCH_VERSION == client.info().version().number()
73 |
74 | when:
75 | ExistsRequest existsRequest = new ExistsRequest.Builder().index("posts").build()
76 |
77 | then: "index does not exists"
78 | !client.indices().exists(existsRequest).value()
79 |
80 | when: "create index request"
81 | IndexRequest.Builder> requestBuilder = new IndexRequest.Builder<>()
82 | .index("posts")
83 | .id("1")
84 |
85 | Map document = new HashMap<>()
86 | document.put("user", "kimchy")
87 | document.put("postDate", "2013-01-30")
88 | document.put("message", "trying out Elasticsearch")
89 | requestBuilder.document(document)
90 |
91 | IndexResponse response = client.index(requestBuilder.build())
92 |
93 | then: "verify version and result"
94 | response.index() == "posts"
95 | response.version() == 1
96 | response.result() == Result.Created
97 |
98 | when: "update index request"
99 | requestBuilder = new IndexRequest.Builder<>()
100 | .index("posts")
101 | .id("1")
102 |
103 | document = new HashMap<>()
104 | document.put("user", "kimchy1")
105 | document.put("postDate", "2018-10-30")
106 | document.put("message", "Trying out Elasticsearch6")
107 | requestBuilder.document(document)
108 |
109 | response = client.index(requestBuilder.build())
110 |
111 | then: "verify version and result"
112 | response.index() == "posts"
113 | response.version() == 2
114 | response.result() == Result.Updated
115 |
116 | when: "get request"
117 | GetRequest getRequest = new GetRequest.Builder()
118 | .index("posts")
119 | .id("1")
120 | .sourceIncludes("message", "*Date")
121 | .build()
122 |
123 | GetResponse