diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index f8c9c70c6804f..630e1ad416c5a 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -1378,6 +1378,16 @@
quarkus-mongodb-panache-common-deployment
${project.version}
+
+ io.quarkus
+ quarkus-hibernate-search-backend-elasticsearch-common
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-hibernate-search-backend-elasticsearch-common-deployment
+ ${project.version}
+
io.quarkus
quarkus-hibernate-search-orm-elasticsearch
diff --git a/devtools/bom-descriptor-json/pom.xml b/devtools/bom-descriptor-json/pom.xml
index 95fd35896d6c3..d93441834129b 100644
--- a/devtools/bom-descriptor-json/pom.xml
+++ b/devtools/bom-descriptor-json/pom.xml
@@ -954,6 +954,19 @@
+
+ io.quarkus
+ quarkus-hibernate-search-backend-elasticsearch-common
+ ${project.version}
+ pom
+ test
+
+
+ *
+ *
+
+
+
io.quarkus
quarkus-hibernate-search-orm-elasticsearch
diff --git a/docs/pom.xml b/docs/pom.xml
index d5e96e352d096..25280e567b7c7 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -965,6 +965,19 @@
+
+ io.quarkus
+ quarkus-hibernate-search-backend-elasticsearch-common-deployment
+ ${project.version}
+ pom
+ test
+
+
+ *
+ *
+
+
+
io.quarkus
quarkus-hibernate-search-orm-elasticsearch-deployment
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/deployment/pom.xml b/extensions/hibernate-search-backend-elasticsearch-common/deployment/pom.xml
new file mode 100644
index 0000000000000..e0633ca755425
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/deployment/pom.xml
@@ -0,0 +1,52 @@
+
+
+
+ quarkus-hibernate-search-backend-elasticsearch-common-parent
+ io.quarkus
+ 999-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-hibernate-search-backend-elasticsearch-common-deployment
+ Quarkus - Hibernate Search - Elasticsearch - Deployment
+
+
+
+ io.quarkus
+ quarkus-core-deployment
+
+
+ io.quarkus
+ quarkus-elasticsearch-rest-client-common-deployment
+
+
+ io.quarkus
+ quarkus-hibernate-search-backend-elasticsearch-common
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/deployment/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/deployment/HibernateSearchBackendElasticsearchEnabledBuildItem.java b/extensions/hibernate-search-backend-elasticsearch-common/deployment/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/deployment/HibernateSearchBackendElasticsearchEnabledBuildItem.java
new file mode 100644
index 0000000000000..9a2b8b4d037a6
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/deployment/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/deployment/HibernateSearchBackendElasticsearchEnabledBuildItem.java
@@ -0,0 +1,28 @@
+package io.quarkus.hibernate.search.backend.elasticsearch.common.deployment;
+
+import java.util.Map;
+
+import io.quarkus.builder.item.MultiBuildItem;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchBackendElasticsearchBuildTimeConfig;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.MapperContext;
+
+public final class HibernateSearchBackendElasticsearchEnabledBuildItem extends MultiBuildItem {
+
+ private final MapperContext mapperContext;
+ private final Map buildTimeConfig;
+
+ public HibernateSearchBackendElasticsearchEnabledBuildItem(MapperContext mapperContext,
+ Map buildTimeConfig) {
+ this.mapperContext = mapperContext;
+ this.buildTimeConfig = buildTimeConfig;
+ }
+
+ public MapperContext getMapperContext() {
+ return mapperContext;
+ }
+
+ public Map getBuildTimeConfig() {
+ return buildTimeConfig;
+ }
+
+}
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/deployment/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/deployment/HibernateSearchBackendElasticsearchProcessor.java b/extensions/hibernate-search-backend-elasticsearch-common/deployment/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/deployment/HibernateSearchBackendElasticsearchProcessor.java
new file mode 100644
index 0000000000000..92cde248d1126
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/deployment/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/deployment/HibernateSearchBackendElasticsearchProcessor.java
@@ -0,0 +1,153 @@
+package io.quarkus.hibernate.search.backend.elasticsearch.common.deployment;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+
+import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer;
+import org.hibernate.search.backend.elasticsearch.gson.spi.GsonClasses;
+import org.hibernate.search.backend.elasticsearch.index.layout.IndexLayoutStrategy;
+
+import io.quarkus.arc.deployment.UnremovableBeanBuildItem;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.BuildSteps;
+import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem;
+import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchBackendElasticsearchBuildTimeConfig;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.MapperContext;
+import io.quarkus.runtime.configuration.ConfigurationException;
+
+@BuildSteps
+class HibernateSearchBackendElasticsearchProcessor {
+
+ @BuildStep
+ void registerBeans(List enabled,
+ BuildProducer unremovableBean) {
+ if (enabled.isEmpty()) {
+ return;
+ }
+ // Some user-injectable beans are retrieved programmatically and shouldn't be removed
+ unremovableBean.produce(UnremovableBeanBuildItem.beanTypes(ElasticsearchAnalysisConfigurer.class,
+ IndexLayoutStrategy.class));
+ }
+
+ @BuildStep
+ void registerReflectionForGson(List enabled,
+ BuildProducer reflectiveClass) {
+ if (enabled.isEmpty()) {
+ return;
+ }
+ String[] reflectiveClasses = GsonClasses.typesRequiringReflection().toArray(String[]::new);
+ reflectiveClass.produce(ReflectiveClassBuildItem.builder(reflectiveClasses)
+ .reason(getClass().getName())
+ .methods().fields().build());
+ }
+
+ @BuildStep
+ void processBuildTimeConfig(List enabled,
+ ApplicationArchivesBuildItem applicationArchivesBuildItem,
+ BuildProducer nativeImageResources,
+ BuildProducer hotDeploymentWatchedFiles) {
+ if (enabled.isEmpty()) {
+ return;
+ }
+ for (HibernateSearchBackendElasticsearchEnabledBuildItem enabledItem : enabled) {
+ processBuildTimeConfig(enabledItem, applicationArchivesBuildItem, nativeImageResources,
+ hotDeploymentWatchedFiles);
+ }
+ }
+
+ private void processBuildTimeConfig(HibernateSearchBackendElasticsearchEnabledBuildItem enabled,
+ ApplicationArchivesBuildItem applicationArchivesBuildItem,
+ BuildProducer nativeImageResources,
+ BuildProducer hotDeploymentWatchedFiles) {
+ Set propertyKeysWithNoVersion = new LinkedHashSet<>();
+ var buildTimeConfig = enabled.getBuildTimeConfig();
+
+ var mapperContext = enabled.getMapperContext();
+ Set allBackendNames = new LinkedHashSet<>(mapperContext.getBackendNamesForIndexedEntities());
+ allBackendNames.addAll(buildTimeConfig.keySet());
+ // For all backends referenced either through @Indexed(backend = ...) or configuration...
+ for (String backendName : allBackendNames) {
+ HibernateSearchBackendElasticsearchBuildTimeConfig backendConfig = buildTimeConfig.get(backendName);
+ // ... we validate that the backend is configured and the version is present
+ if (backendConfig == null || backendConfig.version().isEmpty()) {
+ propertyKeysWithNoVersion.add(mapperContext.backendPropertyKey(backendName, null, "version"));
+ }
+ if (backendConfig == null) {
+ continue;
+ }
+ // ... we register files referenced from backends configuration
+ registerClasspathFilesFromBackendConfig(mapperContext, backendName, backendConfig,
+ applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
+ }
+ if (!propertyKeysWithNoVersion.isEmpty()) {
+ throw new ConfigurationException(
+ "The Elasticsearch version needs to be defined via properties: "
+ + String.join(", ", propertyKeysWithNoVersion) + ".",
+ propertyKeysWithNoVersion);
+ }
+ }
+
+ private static void registerClasspathFilesFromBackendConfig(MapperContext mapperContext, String backendName,
+ HibernateSearchBackendElasticsearchBuildTimeConfig backendConfig,
+ ApplicationArchivesBuildItem applicationArchivesBuildItem,
+ BuildProducer nativeImageResources,
+ BuildProducer hotDeploymentWatchedFiles) {
+ registerClasspathFilesFromIndexConfig(mapperContext, backendName, null, backendConfig.indexDefaults(),
+ applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
+ for (Entry entry : backendConfig.indexes()
+ .entrySet()) {
+ String indexName = entry.getKey();
+ HibernateSearchBackendElasticsearchBuildTimeConfig.IndexConfig indexConfig = entry.getValue();
+ registerClasspathFilesFromIndexConfig(mapperContext, backendName, indexName, indexConfig,
+ applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
+ }
+ }
+
+ private static void registerClasspathFilesFromIndexConfig(MapperContext mapperContext, String backendName, String indexName,
+ HibernateSearchBackendElasticsearchBuildTimeConfig.IndexConfig indexConfig,
+ ApplicationArchivesBuildItem applicationArchivesBuildItem,
+ BuildProducer nativeImageResources,
+ BuildProducer hotDeploymentWatchedFiles) {
+ registerClasspathFileFromConfig(mapperContext, backendName, indexName, "schema-management.settings-file",
+ indexConfig.schemaManagement().settingsFile(),
+ applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
+ registerClasspathFileFromConfig(mapperContext, backendName, indexName, "schema-management.mapping-file",
+ indexConfig.schemaManagement().mappingFile(),
+ applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
+ }
+
+ private static void registerClasspathFileFromConfig(MapperContext mapperContext, String backendName, String indexName,
+ String propertyKeyRadical,
+ Optional classpathFileOptional,
+ ApplicationArchivesBuildItem applicationArchivesBuildItem,
+ BuildProducer nativeImageResources,
+ BuildProducer hotDeploymentWatchedFiles) {
+ if (!classpathFileOptional.isPresent()) {
+ return;
+ }
+ String classpathFile = classpathFileOptional.get();
+
+ Path existingPath = applicationArchivesBuildItem.getRootArchive().getChildPath(classpathFile);
+
+ if (existingPath == null || Files.isDirectory(existingPath)) {
+ //raise exception if explicit file is not present (i.e. not the default)
+ throw new ConfigurationException(
+ "Unable to find file referenced in '"
+ + mapperContext.backendPropertyKey(backendName, indexName, propertyKeyRadical) + "="
+ + classpathFile
+ + "'. Remove property or add file to your path.");
+ }
+ nativeImageResources.produce(new NativeImageResourceBuildItem(classpathFile));
+ hotDeploymentWatchedFiles.produce(new HotDeploymentWatchedFileBuildItem(classpathFile));
+ }
+
+}
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/pom.xml b/extensions/hibernate-search-backend-elasticsearch-common/pom.xml
new file mode 100644
index 0000000000000..6b16ca71abe6c
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ quarkus-extensions-parent
+ io.quarkus
+ 999-SNAPSHOT
+ ../pom.xml
+
+ 4.0.0
+
+ quarkus-hibernate-search-backend-elasticsearch-common-parent
+ Quarkus - Hibernate Search - Elasticsearch
+ pom
+
+ deployment
+ runtime
+
+
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/runtime/pom.xml b/extensions/hibernate-search-backend-elasticsearch-common/runtime/pom.xml
new file mode 100644
index 0000000000000..5479128e11b0b
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/runtime/pom.xml
@@ -0,0 +1,55 @@
+
+
+
+ quarkus-hibernate-search-backend-elasticsearch-common-parent
+ io.quarkus
+ 999-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-hibernate-search-backend-elasticsearch-common
+ Quarkus - Hibernate Search - Elasticsearch - Runtime
+ Elasticsearch/OpenSearch backend for use in other Hibernate Search extensions
+
+
+ io.quarkus
+ quarkus-core
+
+
+ io.quarkus
+ quarkus-elasticsearch-rest-client-common
+
+
+ org.hibernate.search
+ hibernate-search-backend-elasticsearch
+
+
+ org.graalvm.sdk
+ graal-sdk
+ provided
+
+
+
+
+
+
+ io.quarkus
+ quarkus-extension-maven-plugin
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/ElasticsearchVersionSubstitution.java b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/ElasticsearchVersionSubstitution.java
similarity index 86%
rename from extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/ElasticsearchVersionSubstitution.java
rename to extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/ElasticsearchVersionSubstitution.java
index 1bd9dfd6e900d..5f519234d3329 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/ElasticsearchVersionSubstitution.java
+++ b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/ElasticsearchVersionSubstitution.java
@@ -1,4 +1,4 @@
-package io.quarkus.hibernate.search.orm.elasticsearch.runtime;
+package io.quarkus.hibernate.search.backend.elasticsearch.common.runtime;
import org.hibernate.search.backend.elasticsearch.ElasticsearchVersion;
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchBackendElasticsearchBuildTimeConfig.java b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchBackendElasticsearchBuildTimeConfig.java
new file mode 100644
index 0000000000000..97310b905c87e
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchBackendElasticsearchBuildTimeConfig.java
@@ -0,0 +1,123 @@
+package io.quarkus.hibernate.search.backend.elasticsearch.common.runtime;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.hibernate.search.backend.elasticsearch.ElasticsearchVersion;
+
+import io.quarkus.runtime.annotations.ConfigDocMapKey;
+import io.quarkus.runtime.annotations.ConfigDocSection;
+import io.quarkus.runtime.annotations.ConfigGroup;
+import io.smallrye.config.WithParentName;
+
+@ConfigGroup
+public interface HibernateSearchBackendElasticsearchBuildTimeConfig {
+ /**
+ * The version of Elasticsearch used in the cluster.
+ *
+ * As the schema is generated without a connection to the server, this item is mandatory.
+ *
+ * It doesn't have to be the exact version (it can be `7` or `7.1` for instance) but it has to be sufficiently precise
+ * to choose a model dialect (the one used to generate the schema) compatible with the protocol dialect (the one used
+ * to communicate with Elasticsearch).
+ *
+ * There's no rule of thumb here as it depends on the schema incompatibilities introduced by Elasticsearch versions. In
+ * any case, if there is a problem, you will have an error when Hibernate Search tries to connect to the cluster.
+ *
+ * @asciidoclet
+ */
+ Optional version();
+
+ /**
+ * The default configuration for the Elasticsearch indexes.
+ */
+ @WithParentName
+ IndexConfig indexDefaults();
+
+ /**
+ * Per-index configuration overrides.
+ */
+ @ConfigDocSection
+ @ConfigDocMapKey("index-name")
+ Map indexes();
+
+ @ConfigGroup
+ interface IndexConfig {
+ /**
+ * Configuration for automatic creation and validation of the Elasticsearch schema:
+ * indexes, their mapping, their settings.
+ */
+ SchemaManagementConfig schemaManagement();
+
+ /**
+ * Configuration for full-text analysis.
+ */
+ AnalysisConfig analysis();
+ }
+
+ @ConfigGroup
+ interface SchemaManagementConfig {
+
+ // @formatter:off
+ /**
+ * Path to a file in the classpath holding custom index settings to be included in the index definition
+ * when creating an Elasticsearch index.
+ *
+ * The provided settings will be merged with those generated by Hibernate Search, including analyzer definitions.
+ * When analysis is configured both through an analysis configurer and these custom settings, the behavior is undefined;
+ * it should not be relied upon.
+ *
+ * See link:{hibernate-search-docs-url}#backend-elasticsearch-configuration-index-settings[this section of the reference documentation]
+ * for more information.
+ *
+ * @asciidoclet
+ */
+ // @formatter:on
+ Optional settingsFile();
+
+ // @formatter:off
+ /**
+ * Path to a file in the classpath holding a custom index mapping to be included in the index definition
+ * when creating an Elasticsearch index.
+ *
+ * The file does not need to (and generally shouldn't) contain the full mapping:
+ * Hibernate Search will automatically inject missing properties (index fields) in the given mapping.
+ *
+ * See link:{hibernate-search-docs-url}#backend-elasticsearch-mapping-custom[this section of the reference documentation]
+ * for more information.
+ *
+ * @asciidoclet
+ */
+ // @formatter:on
+ Optional mappingFile();
+
+ }
+
+ @ConfigGroup
+ interface AnalysisConfig {
+ /**
+ * One or more xref:#bean-reference-note-anchor[bean references]
+ * to the component(s) used to configure full text analysis (e.g. analyzers, normalizers).
+ *
+ * The referenced beans must implement `ElasticsearchAnalysisConfigurer`.
+ *
+ * See xref:#analysis-configurer[Setting up the analyzers] for more
+ * information.
+ *
+ * [NOTE]
+ * ====
+ * Instead of setting this configuration property,
+ * you can simply annotate your custom `ElasticsearchAnalysisConfigurer` implementations with `@SearchExtension`
+ * and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically.
+ * See xref:#plugging-in-custom-components[this section]
+ * for more information.
+ *
+ * If this configuration property is set, it takes precedence over any `@SearchExtension` annotation.
+ * ====
+ *
+ * @asciidoclet
+ */
+ Optional> configurer();
+ }
+}
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchBackendElasticsearchConfigHandler.java b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchBackendElasticsearchConfigHandler.java
new file mode 100644
index 0000000000000..062d61c186ad6
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchBackendElasticsearchConfigHandler.java
@@ -0,0 +1,195 @@
+package io.quarkus.hibernate.search.backend.elasticsearch.common.runtime;
+
+import static io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchConfigUtil.addBackendConfig;
+import static io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchConfigUtil.addBackendIndexConfig;
+import static io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchConfigUtil.mergeInto;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer;
+import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchBackendSettings;
+import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchIndexSettings;
+import org.hibernate.search.backend.elasticsearch.index.layout.IndexLayoutStrategy;
+import org.hibernate.search.engine.cfg.BackendSettings;
+
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchBackendElasticsearchBuildTimeConfig.IndexConfig;
+
+public final class HibernateSearchBackendElasticsearchConfigHandler {
+
+ public static void contributeBackendBuildTimeProperties(BiConsumer propertyCollector,
+ MapperContext mapperContext,
+ Map backendConfigs) {
+ // We need this weird collecting of names from both @SearchExtension and the configuration properties
+ // because a backend/index could potentially be configured exclusively through configuration properties,
+ // or exclusively through @SearchExtension.
+ // (Well maybe not for backends, but... let's keep it simple.)
+ Map> backendAndIndexNames = new LinkedHashMap<>();
+ mergeInto(backendAndIndexNames, mapperContext.getBackendAndIndexNamesForSearchExtensions());
+ for (Entry entry : backendConfigs.entrySet()) {
+ mergeInto(backendAndIndexNames, entry.getKey(), entry.getValue().indexes().keySet());
+ }
+
+ for (Entry> entry : backendAndIndexNames.entrySet()) {
+ String backendName = entry.getKey();
+ Set indexNames = entry.getValue();
+ contributeBackendBuildTimeProperties(propertyCollector, mapperContext, backendName, indexNames,
+ backendConfigs.get(backendName));
+ }
+ }
+
+ private static void contributeBackendBuildTimeProperties(BiConsumer propertyCollector,
+ MapperContext mapperContext,
+ String backendName, Set indexNames,
+ HibernateSearchBackendElasticsearchBuildTimeConfig elasticsearchBackendConfig) {
+ addBackendConfig(propertyCollector, backendName, BackendSettings.TYPE,
+ ElasticsearchBackendSettings.TYPE_NAME);
+ if (elasticsearchBackendConfig != null) {
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.VERSION,
+ elasticsearchBackendConfig.version());
+ }
+
+ // Settings that may default to a @SearchExtension-annotated-bean
+ //
+
+ // Index defaults at the backend level
+ contributeBackendIndexBuildTimeProperties(propertyCollector, mapperContext, backendName, null,
+ elasticsearchBackendConfig == null ? null : elasticsearchBackendConfig.indexDefaults());
+
+ // Per-index properties
+ for (String indexName : indexNames) {
+ IndexConfig indexConfig = elasticsearchBackendConfig == null ? null
+ : elasticsearchBackendConfig.indexes().get(indexName);
+ contributeBackendIndexBuildTimeProperties(propertyCollector, mapperContext, backendName, indexName, indexConfig);
+ }
+ }
+
+ private static void contributeBackendIndexBuildTimeProperties(BiConsumer propertyCollector,
+ MapperContext mapperContext,
+ String backendName, String indexName, IndexConfig indexConfig) {
+ if (indexConfig != null) {
+ addBackendIndexConfig(propertyCollector, backendName, indexName,
+ ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_SETTINGS_FILE,
+ indexConfig.schemaManagement().settingsFile());
+ addBackendIndexConfig(propertyCollector, backendName, indexName,
+ ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MAPPING_FILE,
+ indexConfig.schemaManagement().mappingFile());
+ }
+
+ // Settings that may default to a @SearchExtension-annotated-bean
+ addBackendIndexConfig(propertyCollector, backendName, indexName,
+ ElasticsearchIndexSettings.ANALYSIS_CONFIGURER,
+ mapperContext.multiExtensionBeanReferencesFor(
+ indexConfig == null ? Optional.empty() : indexConfig.analysis().configurer(),
+ ElasticsearchAnalysisConfigurer.class, backendName, indexName));
+ }
+
+ public static void contributeBackendRuntimeProperties(BiConsumer propertyCollector,
+ MapperContext mapperContext,
+ Map backendConfigs) {
+ // We need this weird collecting of names from both @SearchExtension and the configuration properties
+ // because a backend/index could potentially be configured exclusively through configuration properties,
+ // or exclusively through @SearchExtension.
+ // (Well maybe not for backends, but... let's keep it simple.)
+ Map> backendAndIndexNames = new LinkedHashMap<>();
+ mergeInto(backendAndIndexNames, mapperContext.getBackendAndIndexNamesForSearchExtensions());
+ for (Entry entry : backendConfigs.entrySet()) {
+ mergeInto(backendAndIndexNames, entry.getKey(), entry.getValue().indexes().keySet());
+ }
+
+ for (Entry> entry : backendAndIndexNames.entrySet()) {
+ String backendName = entry.getKey();
+ Set indexNames = entry.getValue();
+ contributeBackendRuntimeProperties(propertyCollector, mapperContext, backendName, indexNames,
+ backendConfigs.get(backendName));
+ }
+ }
+
+ private static void contributeBackendRuntimeProperties(BiConsumer propertyCollector,
+ MapperContext mapperContext,
+ String backendName, Set indexNames,
+ HibernateSearchBackendElasticsearchRuntimeConfig elasticsearchBackendConfig) {
+ if (elasticsearchBackendConfig != null) {
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.HOSTS,
+ elasticsearchBackendConfig.hosts());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.PROTOCOL,
+ elasticsearchBackendConfig.protocol().getHibernateSearchString());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.USERNAME,
+ elasticsearchBackendConfig.username());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.PASSWORD,
+ elasticsearchBackendConfig.password());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.CONNECTION_TIMEOUT,
+ elasticsearchBackendConfig.connectionTimeout().toMillis());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.READ_TIMEOUT,
+ elasticsearchBackendConfig.readTimeout().toMillis());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.REQUEST_TIMEOUT,
+ elasticsearchBackendConfig.requestTimeout(), Optional::isPresent, d -> d.get().toMillis());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.MAX_CONNECTIONS,
+ elasticsearchBackendConfig.maxConnections());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.MAX_CONNECTIONS_PER_ROUTE,
+ elasticsearchBackendConfig.maxConnectionsPerRoute());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.THREAD_POOL_SIZE,
+ elasticsearchBackendConfig.threadPool().size());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.VERSION_CHECK_ENABLED,
+ elasticsearchBackendConfig.versionCheck().enabled());
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.QUERY_SHARD_FAILURE_IGNORE,
+ elasticsearchBackendConfig.query().shardFailure().ignore());
+
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.DISCOVERY_ENABLED,
+ elasticsearchBackendConfig.discovery().enabled());
+ if (elasticsearchBackendConfig.discovery().enabled()) {
+ addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.DISCOVERY_REFRESH_INTERVAL,
+ elasticsearchBackendConfig.discovery().refreshInterval().getSeconds());
+ }
+ }
+
+ // Settings that may default to a @SearchExtension-annotated-bean
+ addBackendConfig(propertyCollector, backendName,
+ ElasticsearchBackendSettings.LAYOUT_STRATEGY,
+ mapperContext.singleExtensionBeanReferenceFor(
+ elasticsearchBackendConfig == null ? Optional.empty()
+ : elasticsearchBackendConfig.layout().strategy(),
+ IndexLayoutStrategy.class, backendName, null));
+
+ // Index defaults at the backend level
+ contributeBackendIndexRuntimeProperties(propertyCollector, mapperContext, backendName, null,
+ elasticsearchBackendConfig == null ? null : elasticsearchBackendConfig.indexDefaults());
+
+ // Per-index properties
+ for (String indexName : indexNames) {
+ HibernateSearchBackendElasticsearchRuntimeConfig.IndexConfig indexConfig = elasticsearchBackendConfig == null ? null
+ : elasticsearchBackendConfig.indexes().get(indexName);
+ contributeBackendIndexRuntimeProperties(propertyCollector, mapperContext, backendName, indexName, indexConfig);
+ }
+ }
+
+ private static void contributeBackendIndexRuntimeProperties(BiConsumer propertyCollector,
+ MapperContext mapperContext,
+ String backendName, String indexName, HibernateSearchBackendElasticsearchRuntimeConfig.IndexConfig indexConfig) {
+ if (indexConfig != null) {
+ addBackendIndexConfig(propertyCollector, backendName, indexName,
+ ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MINIMAL_REQUIRED_STATUS,
+ indexConfig.schemaManagement().requiredStatus());
+ addBackendIndexConfig(propertyCollector, backendName, indexName,
+ ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MINIMAL_REQUIRED_STATUS_WAIT_TIMEOUT,
+ indexConfig.schemaManagement().requiredStatusWaitTimeout(), Optional::isPresent,
+ d -> d.get().toMillis());
+ addBackendIndexConfig(propertyCollector, backendName, indexName,
+ ElasticsearchIndexSettings.INDEXING_QUEUE_COUNT,
+ indexConfig.indexing().queueCount());
+ addBackendIndexConfig(propertyCollector, backendName, indexName,
+ ElasticsearchIndexSettings.INDEXING_QUEUE_SIZE,
+ indexConfig.indexing().queueSize());
+ addBackendIndexConfig(propertyCollector, backendName, indexName,
+ ElasticsearchIndexSettings.INDEXING_MAX_BULK_SIZE,
+ indexConfig.indexing().maxBulkSize());
+ }
+
+ // Settings that may default to a @SearchExtension-annotated-bean
+ //
+ }
+}
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchBackendElasticsearchRuntimeConfig.java b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchBackendElasticsearchRuntimeConfig.java
new file mode 100644
index 0000000000000..0125788d74225
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchBackendElasticsearchRuntimeConfig.java
@@ -0,0 +1,351 @@
+package io.quarkus.hibernate.search.backend.elasticsearch.common.runtime;
+
+import java.time.Duration;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalInt;
+
+import org.hibernate.search.backend.elasticsearch.index.IndexStatus;
+import org.hibernate.search.engine.cfg.spi.ParseUtils;
+import org.hibernate.search.util.common.SearchException;
+
+import io.quarkus.runtime.annotations.ConfigDocDefault;
+import io.quarkus.runtime.annotations.ConfigDocMapKey;
+import io.quarkus.runtime.annotations.ConfigDocSection;
+import io.quarkus.runtime.annotations.ConfigGroup;
+import io.smallrye.config.WithDefault;
+import io.smallrye.config.WithParentName;
+
+@ConfigGroup
+public interface HibernateSearchBackendElasticsearchRuntimeConfig {
+ /**
+ * The list of hosts of the Elasticsearch servers.
+ */
+ @WithDefault("localhost:9200")
+ List hosts();
+
+ /**
+ * The protocol to use when contacting Elasticsearch servers.
+ * Set to "https" to enable SSL/TLS.
+ */
+ @WithDefault("http")
+ ElasticsearchClientProtocol protocol();
+
+ /**
+ * The username used for authentication.
+ */
+ Optional username();
+
+ /**
+ * The password used for authentication.
+ */
+ Optional password();
+
+ /**
+ * The timeout when establishing a connection to an Elasticsearch server.
+ */
+ @WithDefault("1S")
+ Duration connectionTimeout();
+
+ /**
+ * The timeout when reading responses from an Elasticsearch server.
+ */
+ @WithDefault("30S")
+ Duration readTimeout();
+
+ /**
+ * The timeout when executing a request to an Elasticsearch server.
+ *
+ * This includes the time needed to wait for a connection to be available,
+ * send the request and read the response.
+ *
+ * @asciidoclet
+ */
+ Optional requestTimeout();
+
+ /**
+ * The maximum number of connections to all the Elasticsearch servers.
+ */
+ @WithDefault("20")
+ int maxConnections();
+
+ /**
+ * The maximum number of connections per Elasticsearch server.
+ */
+ @WithDefault("10")
+ int maxConnectionsPerRoute();
+
+ /**
+ * Configuration for the automatic discovery of new Elasticsearch nodes.
+ */
+ DiscoveryConfig discovery();
+
+ /**
+ * Configuration for the thread pool assigned to the backend.
+ */
+ ThreadPoolConfig threadPool();
+
+ /**
+ * Configuration for search queries to this backend.
+ */
+ QueryConfig query();
+
+ /**
+ * Configuration for version checks on this backend.
+ */
+ VersionCheckConfig versionCheck();
+
+ /**
+ * The default configuration for the Elasticsearch indexes.
+ */
+ @WithParentName
+ IndexConfig indexDefaults();
+
+ /**
+ * Per-index configuration overrides.
+ */
+ @ConfigDocSection
+ @ConfigDocMapKey("index-name")
+ Map indexes();
+
+ /**
+ * Configuration for the index layout.
+ */
+ LayoutConfig layout();
+
+ enum ElasticsearchClientProtocol {
+ /**
+ * Use clear-text HTTP, with SSL/TLS disabled.
+ */
+ HTTP("http"),
+ /**
+ * Use HTTPS, with SSL/TLS enabled.
+ */
+ HTTPS("https");
+
+ public static ElasticsearchClientProtocol of(String value) {
+ return ParseUtils.parseDiscreteValues(
+ values(),
+ ElasticsearchClientProtocol::getHibernateSearchString,
+ (invalidValue, validValues) -> new SearchException(
+ String.format(
+ Locale.ROOT,
+ "Invalid protocol: '%1$s'. Valid protocols are: %2$s.",
+ invalidValue,
+ validValues)),
+ value);
+ }
+
+ private final String hibernateSearchString;
+
+ ElasticsearchClientProtocol(String hibernateSearchString) {
+ this.hibernateSearchString = hibernateSearchString;
+ }
+
+ public String getHibernateSearchString() {
+ return hibernateSearchString;
+ }
+ }
+
+ @ConfigGroup
+ interface VersionCheckConfig {
+ /**
+ * Whether Hibernate Search should check the version of the Elasticsearch cluster on startup.
+ *
+ * Set to `false` if the Elasticsearch cluster may not be available on startup.
+ *
+ * @asciidoclet
+ */
+ @WithDefault("true")
+ boolean enabled();
+ }
+
+ @ConfigGroup
+ interface IndexConfig {
+ /**
+ * Configuration for the schema management of the indexes.
+ */
+ SchemaManagementConfig schemaManagement();
+
+ /**
+ * Configuration for the indexing process that creates, updates and deletes documents.
+ */
+ IndexingConfig indexing();
+ }
+
+ @ConfigGroup
+ interface DiscoveryConfig {
+
+ /**
+ * Defines if automatic discovery is enabled.
+ */
+ @WithDefault("false")
+ Boolean enabled();
+
+ /**
+ * Refresh interval of the node list.
+ */
+ @WithDefault("10S")
+ Duration refreshInterval();
+
+ }
+
+ @ConfigGroup
+ interface ThreadPoolConfig {
+ /**
+ * The size of the thread pool assigned to the backend.
+ *
+ * Note that number is **per backend**, not per index.
+ * Adding more indexes will not add more threads.
+ *
+ * As all operations happening in this thread-pool are non-blocking,
+ * raising its size above the number of processor cores available to the JVM will not bring noticeable performance
+ * benefit.
+ * The only reason to alter this setting would be to reduce the number of threads;
+ * for example, in an application with a single index with a single indexing queue,
+ * running on a machine with 64 processor cores,
+ * you might want to bring down the number of threads.
+ *
+ * Defaults to the number of processor cores available to the JVM on startup.
+ *
+ * @asciidoclet
+ */
+ // We can't set an actual default value here: see comment on this class.
+ OptionalInt size();
+ }
+
+ @ConfigGroup
+ interface QueryConfig {
+ /**
+ * Configuration for the behavior on shard failure.
+ */
+ QueryShardFailureConfig shardFailure();
+ }
+
+ @ConfigGroup
+ interface QueryShardFailureConfig {
+ /**
+ * Whether partial shard failures are ignored (`true`)
+ * or lead to Hibernate Search throwing an exception (`false`).
+ */
+ @WithDefault("false")
+ boolean ignore();
+ }
+
+ // We can't set actual default values in this section,
+ // otherwise "quarkus.hibernate-search-orm.elasticsearch.index-defaults" will be ignored.
+ @ConfigGroup
+ interface SchemaManagementConfig {
+ /**
+ * The minimal https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster-health.html[Elasticsearch cluster
+ * status] required on startup.
+ *
+ * @asciidoclet
+ */
+ // We can't set an actual default value here: see comment on this class.
+ @ConfigDocDefault("yellow")
+ Optional requiredStatus();
+
+ /**
+ * How long we should wait for the status before failing the bootstrap.
+ */
+ // We can't set an actual default value here: see comment on this class.
+ @ConfigDocDefault("10S")
+ Optional requiredStatusWaitTimeout();
+ }
+
+ // We can't set actual default values in this section,
+ // otherwise "quarkus.hibernate-search-orm.elasticsearch.index-defaults" will be ignored.
+ @ConfigGroup
+ interface IndexingConfig {
+ /**
+ * The number of indexing queues assigned to each index.
+ *
+ * Higher values will lead to more connections being used in parallel,
+ * which may lead to higher indexing throughput,
+ * but incurs a risk of overloading Elasticsearch,
+ * i.e. of overflowing its HTTP request buffers and tripping
+ * https://www.elastic.co/guide/en/elasticsearch/reference/7.9/circuit-breaker.html[circuit breakers],
+ * leading to Elasticsearch giving up on some request and resulting in indexing failures.
+ *
+ * @asciidoclet
+ */
+ // We can't set an actual default value here: see comment on this class.
+ @ConfigDocDefault("10")
+ OptionalInt queueCount();
+
+ /**
+ * The size of indexing queues.
+ *
+ * Lower values may lead to lower memory usage, especially if there are many queues,
+ * but values that are too low will reduce the likeliness of reaching the max bulk size
+ * and increase the likeliness of application threads blocking because the queue is full,
+ * which may lead to lower indexing throughput.
+ *
+ * @asciidoclet
+ */
+ // We can't set an actual default value here: see comment on this class.
+ @ConfigDocDefault("1000")
+ OptionalInt queueSize();
+
+ /**
+ * The maximum size of bulk requests created when processing indexing queues.
+ *
+ * Higher values will lead to more documents being sent in each HTTP request sent to Elasticsearch,
+ * which may lead to higher indexing throughput,
+ * but incurs a risk of overloading Elasticsearch,
+ * i.e. of overflowing its HTTP request buffers and tripping
+ * https://www.elastic.co/guide/en/elasticsearch/reference/7.9/circuit-breaker.html[circuit breakers],
+ * leading to Elasticsearch giving up on some request and resulting in indexing failures.
+ *
+ * Note that raising this number above the queue size has no effect,
+ * as bulks cannot include more requests than are contained in the queue.
+ *
+ * @asciidoclet
+ */
+ // We can't set an actual default value here: see comment on this class.
+ @ConfigDocDefault("100")
+ OptionalInt maxBulkSize();
+ }
+
+ @ConfigGroup
+ interface LayoutConfig {
+ /**
+ * A xref:#bean-reference-note-anchor[bean reference] to the component
+ * used to configure the Elasticsearch layout: index names, index aliases, ...
+ *
+ * The referenced bean must implement `IndexLayoutStrategy`.
+ *
+ * Available built-in implementations:
+ *
+ * `simple`::
+ * The default, future-proof strategy: if the index name in Hibernate Search is `myIndex`,
+ * this strategy will create an index named `myindex-000001`, an alias for write operations named `myindex-write`,
+ * and an alias for read operations named `myindex-read`.
+ * `no-alias`::
+ * A strategy without index aliases, mostly useful on legacy clusters:
+ * if the index name in Hibernate Search is `myIndex`,
+ * this strategy will create an index named `myindex`, and will not use any alias.
+ *
+ * See
+ * link:{hibernate-search-docs-url}#backend-elasticsearch-indexlayout[this section of the reference documentation]
+ * for more information.
+ *
+ * [NOTE]
+ * ====
+ * Instead of setting this configuration property,
+ * you can simply annotate your custom `IndexLayoutStrategy` implementation with `@SearchExtension`
+ * and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically.
+ * See xref:#plugging-in-custom-components[this section]
+ * for more information.
+ *
+ * If this configuration property is set, it takes precedence over any `@SearchExtension` annotation.
+ * ====
+ *
+ * @asciidoclet
+ */
+ Optional strategy();
+ }
+}
diff --git a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchConfigUtil.java b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchConfigUtil.java
similarity index 83%
rename from extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchConfigUtil.java
rename to extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchConfigUtil.java
index ca3a721bd8e05..46518474b082c 100644
--- a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchConfigUtil.java
+++ b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/HibernateSearchConfigUtil.java
@@ -1,7 +1,10 @@
-package io.quarkus.hibernate.search.standalone.elasticsearch.runtime;
+package io.quarkus.hibernate.search.backend.elasticsearch.common.runtime;
+import java.util.LinkedHashSet;
+import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
+import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;
@@ -66,4 +69,15 @@ public static void addBackendIndexConfig(BiConsumer property
}
}
}
+
+ public static void mergeInto(Map> target, Map> source) {
+ for (Map.Entry> entry : source.entrySet()) {
+ mergeInto(target, entry.getKey(), entry.getValue());
+ }
+ }
+
+ public static void mergeInto(Map> target, String key, Set values) {
+ target.computeIfAbsent(key, ignored -> new LinkedHashSet<>())
+ .addAll(values);
+ }
}
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/MapperContext.java b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/MapperContext.java
new file mode 100644
index 0000000000000..91bf5a46b55d4
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/java/io/quarkus/hibernate/search/backend/elasticsearch/common/runtime/MapperContext.java
@@ -0,0 +1,26 @@
+package io.quarkus.hibernate.search.backend.elasticsearch.common.runtime;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import org.hibernate.search.engine.environment.bean.BeanReference;
+
+public interface MapperContext {
+
+ String toString();
+
+ Set getBackendNamesForIndexedEntities();
+
+ Map> getBackendAndIndexNamesForSearchExtensions();
+
+ String backendPropertyKey(String backendName, String indexName, String propertyKeyRadical);
+
+ Optional> singleExtensionBeanReferenceFor(Optional override, Class beanType,
+ String backendName, String indexName);
+
+ Optional>> multiExtensionBeanReferencesFor(Optional> override,
+ Class beanType,
+ String backendName, String indexName);
+}
diff --git a/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 0000000000000..f9e341e387569
--- /dev/null
+++ b/extensions/hibernate-search-backend-elasticsearch-common/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,6 @@
+---
+artifact: ${project.groupId}:${project.artifactId}:${project.version}
+name: "Hibernate Search + Elasticsearch"
+metadata:
+ unlisted: true
+ status: "stable"
\ No newline at end of file
diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/pom.xml b/extensions/hibernate-search-orm-elasticsearch/deployment/pom.xml
index 6862482c6010a..3bc1b3c964d42 100644
--- a/extensions/hibernate-search-orm-elasticsearch/deployment/pom.xml
+++ b/extensions/hibernate-search-orm-elasticsearch/deployment/pom.xml
@@ -25,6 +25,10 @@
io.quarkus
quarkus-elasticsearch-rest-client-common-deployment
+
+ io.quarkus
+ quarkus-hibernate-search-backend-elasticsearch-common-deployment
+
io.quarkus
quarkus-hibernate-search-orm-elasticsearch
diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem.java b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem.java
index 715865766f37f..6d29fec23da46 100644
--- a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem.java
+++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem.java
@@ -1,49 +1,31 @@
package io.quarkus.hibernate.search.orm.elasticsearch.deployment;
-import java.util.Map;
-import java.util.Set;
-
import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit;
+import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchOrmElasticsearchMapperContext;
public final class HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem extends MultiBuildItem {
- private final String persistenceUnitName;
+ public final HibernateSearchOrmElasticsearchMapperContext mapperContext;
private final HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit buildTimeConfig;
- private final Set backendNamesForIndexedEntities;
- private Map> backendAndIndexNamesForSearchExtensions;
- public HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem(String persistenceUnitName,
- HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit buildTimeConfig,
- Set backendNamesForIndexedEntities,
- Map> backendAndIndexNamesForSearchExtensions) {
- if (persistenceUnitName == null) {
- throw new IllegalArgumentException("persistenceUnitName cannot be null");
- }
- this.persistenceUnitName = persistenceUnitName;
+ public HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem(
+ HibernateSearchOrmElasticsearchMapperContext mapperContext,
+ HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit buildTimeConfig) {
+ this.mapperContext = mapperContext;
this.buildTimeConfig = buildTimeConfig;
- this.backendNamesForIndexedEntities = backendNamesForIndexedEntities;
- this.backendAndIndexNamesForSearchExtensions = backendAndIndexNamesForSearchExtensions;
}
public String getPersistenceUnitName() {
- return persistenceUnitName;
+ return mapperContext.persistenceUnitName;
}
public HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit getBuildTimeConfig() {
return buildTimeConfig;
}
- public Set getBackendNamesForIndexedEntities() {
- return backendNamesForIndexedEntities;
- }
-
- public Map> getBackendAndIndexNamesForSearchExtensions() {
- return backendAndIndexNamesForSearchExtensions;
- }
-
@Override
public String toString() {
- return getClass().getSimpleName() + " [" + persistenceUnitName + "]";
+ return getClass().getSimpleName() + " [" + getPersistenceUnitName() + "]";
}
}
diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchProcessor.java b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchProcessor.java
index 417947ff23bea..72d3945b3d6c5 100644
--- a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchProcessor.java
+++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchProcessor.java
@@ -5,12 +5,9 @@
import static io.quarkus.hibernate.search.orm.elasticsearch.deployment.ClassNames.ROOT_MAPPING;
import static io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfig.backendPropertyKey;
import static io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfig.defaultBackendPropertyKeys;
-import static io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfig.elasticsearchVersionPropertyKey;
import static io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfig.mapperPropertyKey;
import static io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfig.mapperPropertyKeys;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -18,14 +15,10 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import org.hibernate.search.backend.elasticsearch.ElasticsearchVersion;
-import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer;
-import org.hibernate.search.backend.elasticsearch.gson.spi.GsonClasses;
-import org.hibernate.search.backend.elasticsearch.index.layout.IndexLayoutStrategy;
import org.hibernate.search.engine.reporting.FailureHandler;
import org.hibernate.search.mapper.orm.automaticindexing.session.AutomaticIndexingSynchronizationStrategy;
import org.hibernate.search.mapper.pojo.work.IndexingPlanSynchronizationStrategy;
@@ -42,12 +35,10 @@
import io.quarkus.deployment.annotations.BuildSteps;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
-import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.DevServicesAdditionalConfigBuildItem;
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
-import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.recording.RecorderContext;
import io.quarkus.deployment.util.JandexUtil;
import io.quarkus.elasticsearch.restclient.common.deployment.DevservicesElasticsearchBuildItem;
@@ -58,15 +49,14 @@
import io.quarkus.hibernate.orm.runtime.PersistenceUnitUtil;
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrationRuntimeInitListener;
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrationStaticInitListener;
-import io.quarkus.hibernate.search.orm.elasticsearch.runtime.ElasticsearchVersionSubstitution;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.deployment.HibernateSearchBackendElasticsearchEnabledBuildItem;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.ElasticsearchVersionSubstitution;
import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchBuildTimeConfig;
import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit;
-import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit.ElasticsearchBackendBuildTimeConfig;
-import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit.ElasticsearchIndexBuildTimeConfig;
import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRecorder;
import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfig;
+import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchOrmElasticsearchMapperContext;
import io.quarkus.runtime.configuration.ConfigUtils;
-import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.vertx.http.deployment.spi.RouteBuildItem;
@BuildSteps(onlyIf = HibernateSearchEnabled.class)
@@ -82,7 +72,6 @@ public void build(HibernateSearchElasticsearchRecorder recorder,
CombinedIndexBuildItem combinedIndexBuildItem,
HibernateSearchElasticsearchBuildTimeConfig buildTimeConfig,
List persistenceUnitDescriptorBuildItems,
- BuildProducer reflectiveClass,
BuildProducer configuredPersistenceUnits,
BuildProducer staticIntegrations,
BuildProducer runtimeIntegrations,
@@ -112,8 +101,6 @@ public void build(HibernateSearchElasticsearchRecorder recorder,
backendAndIndexNamesForSearchExtensions,
configuredPersistenceUnits, staticIntegrations, runtimeIntegrations);
}
-
- reflectiveClass.produce(registerReflectionForGson());
}
private static Map>> collectPersistenceUnitAndBackendAndIndexNamesForSearchExtensions(
@@ -161,8 +148,20 @@ private void buildForPersistenceUnit(HibernateSearchElasticsearchRecorder record
}
configuredPersistenceUnits
- .produce(new HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem(persistenceUnitName, puConfig,
- backendNamesForIndexedEntities, backendAndIndexNamesForSearchExtensions));
+ .produce(new HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem(
+ new HibernateSearchOrmElasticsearchMapperContext(persistenceUnitName,
+ backendNamesForIndexedEntities, backendAndIndexNamesForSearchExtensions),
+ puConfig));
+ }
+
+ @BuildStep
+ void enableBackend(List enabledPUs,
+ BuildProducer elasticsearchEnabled) {
+ for (HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem enabled : enabledPUs) {
+ var buildTimeConfig = enabled.getBuildTimeConfig();
+ elasticsearchEnabled.produce(new HibernateSearchBackendElasticsearchEnabledBuildItem(enabled.mapperContext,
+ buildTimeConfig == null ? Collections.emptyMap() : buildTimeConfig.backends()));
+ }
}
@BuildStep
@@ -174,8 +173,7 @@ void registerBeans(List configuredPersistenceUnits,
- ApplicationArchivesBuildItem applicationArchivesBuildItem,
- BuildProducer nativeImageResources,
- BuildProducer hotDeploymentWatchedFiles) {
- for (HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem configuredPersistenceUnit : configuredPersistenceUnits) {
- processPersistenceUnitBuildTimeConfig(configuredPersistenceUnit, applicationArchivesBuildItem, nativeImageResources,
- hotDeploymentWatchedFiles);
- }
- }
-
- private void processPersistenceUnitBuildTimeConfig(
- HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem configuredPersistenceUnit,
- ApplicationArchivesBuildItem applicationArchivesBuildItem,
- BuildProducer nativeImageResources,
- BuildProducer hotDeploymentWatchedFiles) {
- String persistenceUnitName = configuredPersistenceUnit.getPersistenceUnitName();
- HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit buildTimeConfig = configuredPersistenceUnit
- .getBuildTimeConfig();
-
- Set propertyKeysWithNoVersion = new LinkedHashSet<>();
- Map backends = buildTimeConfig != null
- ? buildTimeConfig.backends()
- : Collections.emptyMap();
-
- Set allBackendNames = new LinkedHashSet<>(configuredPersistenceUnit.getBackendNamesForIndexedEntities());
- allBackendNames.addAll(backends.keySet());
- // For all backends referenced either through @Indexed(backend = ...) or configuration...
- for (String backendName : allBackendNames) {
- ElasticsearchBackendBuildTimeConfig backendConfig = backends.get(backendName);
- // ... we validate that the backend is configured and the version is present
- if (backendConfig == null || backendConfig.version().isEmpty()) {
- propertyKeysWithNoVersion.add(elasticsearchVersionPropertyKey(persistenceUnitName, backendName));
- }
- // ... we register files referenced from backends configuration
- if (backendConfig != null) {
- registerClasspathFileFromBackendConfig(persistenceUnitName, backendName, backendConfig,
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- }
+ recorder.createRuntimeInitListener(configuredPersistenceUnit.mapperContext,
+ runtimeConfig, integrationRuntimeInitListeners)));
}
- if (!propertyKeysWithNoVersion.isEmpty()) {
- throw new ConfigurationException(
- "The Elasticsearch version needs to be defined via properties: "
- + String.join(", ", propertyKeysWithNoVersion) + ".",
- propertyKeysWithNoVersion);
- }
- }
-
- private static void registerClasspathFileFromBackendConfig(String persistenceUnitName, String backendName,
- ElasticsearchBackendBuildTimeConfig backendConfig,
- ApplicationArchivesBuildItem applicationArchivesBuildItem,
- BuildProducer nativeImageResources,
- BuildProducer hotDeploymentWatchedFiles) {
- registerClasspathFileFromIndexConfig(persistenceUnitName, backendName, null, backendConfig.indexDefaults(),
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- for (Entry entry : backendConfig.indexes().entrySet()) {
- String indexName = entry.getKey();
- ElasticsearchIndexBuildTimeConfig indexConfig = entry.getValue();
- registerClasspathFileFromIndexConfig(persistenceUnitName, backendName, indexName, indexConfig,
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- }
- }
-
- private static void registerClasspathFileFromIndexConfig(String persistenceUnitName, String backendName, String indexName,
- ElasticsearchIndexBuildTimeConfig indexConfig,
- ApplicationArchivesBuildItem applicationArchivesBuildItem,
- BuildProducer nativeImageResources,
- BuildProducer hotDeploymentWatchedFiles) {
- registerClasspathFileFromConfig(persistenceUnitName, backendName, indexName, "schema-management.settings-file",
- indexConfig.schemaManagement().settingsFile(),
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- registerClasspathFileFromConfig(persistenceUnitName, backendName, indexName, "schema-management.mapping-file",
- indexConfig.schemaManagement().mappingFile(),
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- }
-
- private static void registerClasspathFileFromConfig(String persistenceUnitName, String backendName, String indexName,
- String propertyKeyRadical,
- Optional classpathFileOptional,
- ApplicationArchivesBuildItem applicationArchivesBuildItem,
- BuildProducer nativeImageResources,
- BuildProducer hotDeploymentWatchedFiles) {
- if (!classpathFileOptional.isPresent()) {
- return;
- }
- String classpathFile = classpathFileOptional.get();
-
- Path existingPath = applicationArchivesBuildItem.getRootArchive().getChildPath(classpathFile);
-
- if (existingPath == null || Files.isDirectory(existingPath)) {
- //raise exception if explicit file is not present (i.e. not the default)
- throw new ConfigurationException(
- "Unable to find file referenced in '"
- + backendPropertyKey(persistenceUnitName, backendName, indexName, propertyKeyRadical) + "="
- + classpathFile
- + "'. Remove property or add file to your path.");
- }
- nativeImageResources.produce(new NativeImageResourceBuildItem(classpathFile));
- hotDeploymentWatchedFiles.produce(new HotDeploymentWatchedFileBuildItem(classpathFile));
- }
-
- private ReflectiveClassBuildItem registerReflectionForGson() {
- String[] reflectiveClasses = GsonClasses.typesRequiringReflection().toArray(String[]::new);
- return ReflectiveClassBuildItem.builder(reflectiveClasses)
- .reason(getClass().getName())
- .methods().fields().build();
}
@BuildStep(onlyIfNot = IsNormal.class)
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/pom.xml b/extensions/hibernate-search-orm-elasticsearch/runtime/pom.xml
index 12b6c1e1dd0b0..4653413c7abb8 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/pom.xml
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/pom.xml
@@ -26,8 +26,8 @@
quarkus-elasticsearch-rest-client-common
- org.hibernate.search
- hibernate-search-backend-elasticsearch
+ io.quarkus
+ quarkus-hibernate-search-backend-elasticsearch-common
org.hibernate.search
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchConfigUtil.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchConfigUtil.java
index fbd368e354c38..90ce860706171 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchConfigUtil.java
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchConfigUtil.java
@@ -8,6 +8,10 @@
import org.hibernate.search.engine.cfg.BackendSettings;
import org.hibernate.search.engine.cfg.IndexSettings;
+/**
+ * @deprecated Use {@link io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchConfigUtil} instead.
+ */
+@Deprecated
public class HibernateSearchConfigUtil {
public static void addConfig(BiConsumer propertyCollector, String configPath, T value) {
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit.java
index 6970ffb3363eb..965cf0bc1bdee 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit.java
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit.java
@@ -4,27 +4,25 @@
import java.util.Map;
import java.util.Optional;
-import org.hibernate.search.backend.elasticsearch.ElasticsearchVersion;
-
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchBackendElasticsearchBuildTimeConfig;
import io.quarkus.runtime.annotations.ConfigDocDefault;
import io.quarkus.runtime.annotations.ConfigDocMapKey;
import io.quarkus.runtime.annotations.ConfigDocSection;
import io.quarkus.runtime.annotations.ConfigGroup;
import io.smallrye.config.WithName;
-import io.smallrye.config.WithParentName;
import io.smallrye.config.WithUnnamedKey;
@ConfigGroup
public interface HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit {
/**
- * Configuration for backends.
+ * Configuration for Elasticsearch/OpenSearch backends.
*/
@ConfigDocSection
@WithName("elasticsearch")
@WithUnnamedKey // The default backend has the null key
@ConfigDocMapKey("backend-name")
- Map backends();
+ Map backends();
/**
* A xref:hibernate-search-orm-elasticsearch.adoc#bean-reference-note-anchor[bean reference] to a component
@@ -62,117 +60,6 @@ public interface HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit {
*/
MappingConfig mapping();
- @ConfigGroup
- interface ElasticsearchBackendBuildTimeConfig {
- /**
- * The version of Elasticsearch used in the cluster.
- *
- * As the schema is generated without a connection to the server, this item is mandatory.
- *
- * It doesn't have to be the exact version (it can be `7` or `7.1` for instance) but it has to be sufficiently precise
- * to choose a model dialect (the one used to generate the schema) compatible with the protocol dialect (the one used
- * to communicate with Elasticsearch).
- *
- * There's no rule of thumb here as it depends on the schema incompatibilities introduced by Elasticsearch versions. In
- * any case, if there is a problem, you will have an error when Hibernate Search tries to connect to the cluster.
- *
- * @asciidoclet
- */
- Optional version();
-
- /**
- * The default configuration for the Elasticsearch indexes.
- */
- @WithParentName
- ElasticsearchIndexBuildTimeConfig indexDefaults();
-
- /**
- * Per-index configuration overrides.
- */
- @ConfigDocSection
- @ConfigDocMapKey("index-name")
- Map indexes();
- }
-
- @ConfigGroup
- interface ElasticsearchIndexBuildTimeConfig {
- /**
- * Configuration for automatic creation and validation of the Elasticsearch schema:
- * indexes, their mapping, their settings.
- */
- SchemaManagementConfig schemaManagement();
-
- /**
- * Configuration for full-text analysis.
- */
- AnalysisConfig analysis();
- }
-
- @ConfigGroup
- interface SchemaManagementConfig {
-
- // @formatter:off
- /**
- * Path to a file in the classpath holding custom index settings to be included in the index definition
- * when creating an Elasticsearch index.
- *
- * The provided settings will be merged with those generated by Hibernate Search, including analyzer definitions.
- * When analysis is configured both through an analysis configurer and these custom settings, the behavior is undefined;
- * it should not be relied upon.
- *
- * See link:{hibernate-search-docs-url}#backend-elasticsearch-configuration-index-settings[this section of the reference documentation]
- * for more information.
- *
- * @asciidoclet
- */
- // @formatter:on
- Optional settingsFile();
-
- // @formatter:off
- /**
- * Path to a file in the classpath holding a custom index mapping to be included in the index definition
- * when creating an Elasticsearch index.
- *
- * The file does not need to (and generally shouldn't) contain the full mapping:
- * Hibernate Search will automatically inject missing properties (index fields) in the given mapping.
- *
- * See link:{hibernate-search-docs-url}#backend-elasticsearch-mapping-custom[this section of the reference documentation]
- * for more information.
- *
- * @asciidoclet
- */
- // @formatter:on
- Optional mappingFile();
-
- }
-
- @ConfigGroup
- interface AnalysisConfig {
- /**
- * One or more xref:hibernate-search-orm-elasticsearch.adoc#bean-reference-note-anchor[bean references]
- * to the component(s) used to configure full text analysis (e.g. analyzers, normalizers).
- *
- * The referenced beans must implement `ElasticsearchAnalysisConfigurer`.
- *
- * See xref:hibernate-search-orm-elasticsearch.adoc#analysis-configurer[Setting up the analyzers] for more
- * information.
- *
- * [NOTE]
- * ====
- * Instead of setting this configuration property,
- * you can simply annotate your custom `ElasticsearchAnalysisConfigurer` implementations with `@SearchExtension`
- * and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically.
- * See xref:hibernate-search-orm-elasticsearch.adoc#plugging-in-custom-components[this section]
- * for more information.
- *
- * If this configuration property is set, it takes precedence over any `@SearchExtension` annotation.
- * ====
- *
- * @asciidoclet
- */
- Optional> configurer();
- }
-
@ConfigGroup
interface CoordinationConfig {
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRecorder.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRecorder.java
index 62431de35b455..09a44b25e8aec 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRecorder.java
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRecorder.java
@@ -1,12 +1,9 @@
package io.quarkus.hibernate.search.orm.elasticsearch.runtime;
-import static io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchConfigUtil.addBackendConfig;
-import static io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchConfigUtil.addBackendIndexConfig;
-import static io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchConfigUtil.addConfig;
+import static io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchConfigUtil.addConfig;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -23,11 +20,6 @@
import org.hibernate.boot.Metadata;
import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.spi.BootstrapContext;
-import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer;
-import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchBackendSettings;
-import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchIndexSettings;
-import org.hibernate.search.backend.elasticsearch.index.layout.IndexLayoutStrategy;
-import org.hibernate.search.engine.cfg.BackendSettings;
import org.hibernate.search.engine.cfg.EngineSettings;
import org.hibernate.search.engine.environment.bean.BeanReference;
import org.hibernate.search.engine.reporting.FailureHandler;
@@ -46,10 +38,7 @@
import io.quarkus.arc.Arc;
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrationRuntimeInitListener;
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrationStaticInitListener;
-import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit.ElasticsearchBackendBuildTimeConfig;
-import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit.ElasticsearchIndexBuildTimeConfig;
-import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfigPersistenceUnit.ElasticsearchBackendRuntimeConfig;
-import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfigPersistenceUnit.ElasticsearchIndexRuntimeConfig;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchBackendElasticsearchConfigHandler;
import io.quarkus.hibernate.search.orm.elasticsearch.runtime.bean.HibernateSearchBeanUtil;
import io.quarkus.hibernate.search.orm.elasticsearch.runtime.management.HibernateSearchManagementHandler;
import io.quarkus.hibernate.search.orm.elasticsearch.runtime.mapping.QuarkusHibernateOrmSearchMappingConfigurer;
@@ -62,8 +51,8 @@
public class HibernateSearchElasticsearchRecorder {
public HibernateOrmIntegrationStaticInitListener createStaticInitListener(
- String persistenceUnitName, HibernateSearchElasticsearchBuildTimeConfig buildTimeConfig,
- Map> backendAndIndexNamesForSearchExtensions,
+ HibernateSearchOrmElasticsearchMapperContext mapperContext,
+ HibernateSearchElasticsearchBuildTimeConfig buildTimeConfig,
Set rootAnnotationMappedClassNames,
List integrationStaticInitListeners) {
Set> rootAnnotationMappedClasses = new LinkedHashSet<>();
@@ -75,9 +64,9 @@ public HibernateOrmIntegrationStaticInitListener createStaticInitListener(
throw new IllegalStateException("Could not initialize mapped class " + className, e);
}
}
- return new HibernateSearchIntegrationStaticInitListener(persistenceUnitName,
- buildTimeConfig.persistenceUnits().get(persistenceUnitName),
- backendAndIndexNamesForSearchExtensions, rootAnnotationMappedClasses,
+ return new HibernateSearchIntegrationStaticInitListener(mapperContext,
+ buildTimeConfig.persistenceUnits().get(mapperContext.persistenceUnitName),
+ rootAnnotationMappedClasses,
integrationStaticInitListeners);
}
@@ -86,13 +75,13 @@ public HibernateOrmIntegrationStaticInitListener createStaticInitInactiveListene
}
public HibernateOrmIntegrationRuntimeInitListener createRuntimeInitListener(
- HibernateSearchElasticsearchRuntimeConfig runtimeConfig, String persistenceUnitName,
- Map> backendAndIndexNamesForSearchExtensions,
+ HibernateSearchOrmElasticsearchMapperContext mapperContext,
+ HibernateSearchElasticsearchRuntimeConfig runtimeConfig,
List integrationRuntimeInitListeners) {
HibernateSearchElasticsearchRuntimeConfigPersistenceUnit puConfig = runtimeConfig.persistenceUnits()
- .get(persistenceUnitName);
- return new HibernateSearchIntegrationRuntimeInitListener(persistenceUnitName, puConfig,
- backendAndIndexNamesForSearchExtensions, integrationRuntimeInitListeners);
+ .get(mapperContext.persistenceUnitName);
+ return new HibernateSearchIntegrationRuntimeInitListener(mapperContext, puConfig,
+ integrationRuntimeInitListeners);
}
public void checkNoExplicitActiveTrue(HibernateSearchElasticsearchRuntimeConfig runtimeConfig) {
@@ -191,20 +180,19 @@ public void onMetadataInitialized(Metadata metadata, BootstrapContext bootstrapC
private static final class HibernateSearchIntegrationStaticInitListener
implements HibernateOrmIntegrationStaticInitListener {
+ private final HibernateSearchOrmElasticsearchMapperContext mapperContext;
private final String persistenceUnitName;
private final HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit buildTimeConfig;
- private final Map> backendAndIndexNamesForSearchExtensions;
private final Set> rootAnnotationMappedClasses;
private final List integrationStaticInitListeners;
- private HibernateSearchIntegrationStaticInitListener(String persistenceUnitName,
+ private HibernateSearchIntegrationStaticInitListener(HibernateSearchOrmElasticsearchMapperContext mapperContext,
HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit buildTimeConfig,
- Map> backendAndIndexNamesForSearchExtensions,
Set> rootAnnotationMappedClasses,
List integrationStaticInitListeners) {
- this.persistenceUnitName = persistenceUnitName;
+ this.mapperContext = mapperContext;
+ this.persistenceUnitName = mapperContext.persistenceUnitName;
this.buildTimeConfig = buildTimeConfig;
- this.backendAndIndexNamesForSearchExtensions = backendAndIndexNamesForSearchExtensions;
this.rootAnnotationMappedClasses = rootAnnotationMappedClasses;
this.integrationStaticInitListeners = integrationStaticInitListeners;
}
@@ -227,25 +215,9 @@ public void contributeBootProperties(BiConsumer propertyCollecto
buildTimeConfig == null ? Optional.empty() : buildTimeConfig.coordination().strategy(),
CoordinationStrategy.class, persistenceUnitName, null, null));
- // We need this weird collecting of names from both @SearchExtension and the configuration properties
- // because a backend/index could potentially be configured exclusively through configuration properties,
- // or exclusively through @SearchExtension.
- // (Well maybe not for backends, but... let's keep it simple.)
- Map backendConfigs = buildTimeConfig == null
- ? Collections.emptyMap()
- : buildTimeConfig.backends();
- Map> backendAndIndexNames = new LinkedHashMap<>();
- mergeInto(backendAndIndexNames, backendAndIndexNamesForSearchExtensions);
- for (Entry entry : backendConfigs.entrySet()) {
- mergeInto(backendAndIndexNames, entry.getKey(), entry.getValue().indexes().keySet());
- }
-
- for (Entry> entry : backendAndIndexNames.entrySet()) {
- String backendName = entry.getKey();
- Set indexNames = entry.getValue();
- contributeBackendBuildTimeProperties(propertyCollector, backendName, indexNames,
- backendConfigs.get(backendName));
- }
+ HibernateSearchBackendElasticsearchConfigHandler.contributeBackendBuildTimeProperties(
+ propertyCollector, mapperContext,
+ buildTimeConfig == null ? Collections.emptyMap() : buildTimeConfig.backends());
for (HibernateOrmIntegrationStaticInitListener listener : integrationStaticInitListeners) {
listener.contributeBootProperties(propertyCollector);
@@ -283,47 +255,6 @@ public void onMetadataInitialized(Metadata metadata, BootstrapContext bootstrapC
listener.onMetadataInitialized(metadata, bootstrapContext, propertyCollector);
}
}
-
- private void contributeBackendBuildTimeProperties(BiConsumer propertyCollector, String backendName,
- Set indexNames,
- ElasticsearchBackendBuildTimeConfig elasticsearchBackendConfig) {
- addBackendConfig(propertyCollector, backendName, BackendSettings.TYPE,
- ElasticsearchBackendSettings.TYPE_NAME);
- if (elasticsearchBackendConfig != null) {
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.VERSION,
- elasticsearchBackendConfig.version());
- }
-
- // Index defaults at the backend level
- contributeBackendIndexBuildTimeProperties(propertyCollector, backendName, null,
- elasticsearchBackendConfig == null ? null : elasticsearchBackendConfig.indexDefaults());
-
- // Per-index properties
- for (String indexName : indexNames) {
- ElasticsearchIndexBuildTimeConfig indexConfig = elasticsearchBackendConfig == null ? null
- : elasticsearchBackendConfig.indexes().get(indexName);
- contributeBackendIndexBuildTimeProperties(propertyCollector, backendName, indexName, indexConfig);
- }
- }
-
- private void contributeBackendIndexBuildTimeProperties(BiConsumer propertyCollector,
- String backendName, String indexName, ElasticsearchIndexBuildTimeConfig indexConfig) {
- if (indexConfig != null) {
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_SETTINGS_FILE,
- indexConfig.schemaManagement().settingsFile());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MAPPING_FILE,
- indexConfig.schemaManagement().mappingFile());
- }
-
- // Settings that may default to a @SearchExtension-annotated-bean
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.ANALYSIS_CONFIGURER,
- HibernateSearchBeanUtil.multiExtensionBeanReferencesFor(
- indexConfig == null ? Optional.empty() : indexConfig.analysis().configurer(),
- ElasticsearchAnalysisConfigurer.class, persistenceUnitName, backendName, indexName));
- }
}
private static final class HibernateSearchIntegrationRuntimeInitInactiveListener
@@ -351,18 +282,17 @@ public List> contributeServiceInitiators() {
private static final class HibernateSearchIntegrationRuntimeInitListener
implements HibernateOrmIntegrationRuntimeInitListener {
+ private final HibernateSearchOrmElasticsearchMapperContext mapperContext;
private final String persistenceUnitName;
private final HibernateSearchElasticsearchRuntimeConfigPersistenceUnit runtimeConfig;
- private final Map> backendAndIndexNamesForSearchExtensions;
private final List integrationRuntimeInitListeners;
- private HibernateSearchIntegrationRuntimeInitListener(String persistenceUnitName,
+ private HibernateSearchIntegrationRuntimeInitListener(HibernateSearchOrmElasticsearchMapperContext mapperContext,
HibernateSearchElasticsearchRuntimeConfigPersistenceUnit runtimeConfig,
- Map> backendAndIndexNamesForSearchExtensions,
List integrationRuntimeInitListeners) {
- this.persistenceUnitName = persistenceUnitName;
+ this.mapperContext = mapperContext;
+ this.persistenceUnitName = mapperContext.persistenceUnitName;
this.runtimeConfig = runtimeConfig;
- this.backendAndIndexNamesForSearchExtensions = backendAndIndexNamesForSearchExtensions;
this.integrationRuntimeInitListeners = integrationRuntimeInitListeners;
}
@@ -405,113 +335,15 @@ public void contributeRuntimeProperties(BiConsumer propertyColle
: runtimeConfig.automaticIndexing().synchronization().strategy(),
AutomaticIndexingSynchronizationStrategy.class, persistenceUnitName, null, null));
- // We need this weird collecting of names from both @SearchExtension and the configuration properties
- // because a backend/index could potentially be configured exclusively through configuration properties,
- // or exclusively through @SearchExtension.
- // (Well maybe not for backends, but... let's keep it simple.)
- Map backendConfigs = runtimeConfig == null
- ? Collections.emptyMap()
- : runtimeConfig.backends();
- Map> backendAndIndexNames = new LinkedHashMap<>();
- mergeInto(backendAndIndexNames, backendAndIndexNamesForSearchExtensions);
- for (Entry entry : backendConfigs.entrySet()) {
- mergeInto(backendAndIndexNames, entry.getKey(), entry.getValue().indexes().keySet());
- }
-
- for (Entry> entry : backendAndIndexNames.entrySet()) {
- String backendName = entry.getKey();
- Set indexNames = entry.getValue();
- contributeBackendRuntimeProperties(propertyCollector, backendName, indexNames,
- backendConfigs.get(backendName));
- }
+ HibernateSearchBackendElasticsearchConfigHandler.contributeBackendRuntimeProperties(
+ propertyCollector, mapperContext,
+ runtimeConfig == null ? Collections.emptyMap() : runtimeConfig.backends());
for (HibernateOrmIntegrationRuntimeInitListener integrationRuntimeInitListener : integrationRuntimeInitListeners) {
integrationRuntimeInitListener.contributeRuntimeProperties(propertyCollector);
}
}
- private void contributeBackendRuntimeProperties(BiConsumer propertyCollector, String backendName,
- Set indexNames, ElasticsearchBackendRuntimeConfig elasticsearchBackendConfig) {
- if (elasticsearchBackendConfig != null) {
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.HOSTS,
- elasticsearchBackendConfig.hosts());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.PROTOCOL,
- elasticsearchBackendConfig.protocol().getHibernateSearchString());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.USERNAME,
- elasticsearchBackendConfig.username());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.PASSWORD,
- elasticsearchBackendConfig.password());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.CONNECTION_TIMEOUT,
- elasticsearchBackendConfig.connectionTimeout().toMillis());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.READ_TIMEOUT,
- elasticsearchBackendConfig.readTimeout().toMillis());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.REQUEST_TIMEOUT,
- elasticsearchBackendConfig.requestTimeout(), Optional::isPresent, d -> d.get().toMillis());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.MAX_CONNECTIONS,
- elasticsearchBackendConfig.maxConnections());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.MAX_CONNECTIONS_PER_ROUTE,
- elasticsearchBackendConfig.maxConnectionsPerRoute());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.THREAD_POOL_SIZE,
- elasticsearchBackendConfig.threadPool().size());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.VERSION_CHECK_ENABLED,
- elasticsearchBackendConfig.versionCheck().enabled());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.QUERY_SHARD_FAILURE_IGNORE,
- elasticsearchBackendConfig.query().shardFailure().ignore());
-
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.DISCOVERY_ENABLED,
- elasticsearchBackendConfig.discovery().enabled());
- if (elasticsearchBackendConfig.discovery().enabled()) {
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.DISCOVERY_REFRESH_INTERVAL,
- elasticsearchBackendConfig.discovery().refreshInterval().getSeconds());
- }
- // Settings that may default to a @SearchExtension-annotated-bean
- addBackendConfig(propertyCollector, backendName,
- ElasticsearchBackendSettings.LAYOUT_STRATEGY,
- HibernateSearchBeanUtil.singleExtensionBeanReferenceFor(
- elasticsearchBackendConfig.layout().strategy(),
- IndexLayoutStrategy.class, persistenceUnitName, backendName, null));
- }
-
- // Settings that may default to a @SearchExtension-annotated-bean
- //
-
- // Index defaults at the backend level
- contributeBackendIndexRuntimeProperties(propertyCollector, backendName, null,
- elasticsearchBackendConfig == null ? null : elasticsearchBackendConfig.indexDefaults());
-
- // Per-index properties
- for (String indexName : indexNames) {
- ElasticsearchIndexRuntimeConfig indexConfig = elasticsearchBackendConfig == null ? null
- : elasticsearchBackendConfig.indexes().get(indexName);
- contributeBackendIndexRuntimeProperties(propertyCollector, backendName, indexName, indexConfig);
- }
- }
-
- private void contributeBackendIndexRuntimeProperties(BiConsumer propertyCollector,
- String backendName, String indexName, ElasticsearchIndexRuntimeConfig indexConfig) {
- if (indexConfig != null) {
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MINIMAL_REQUIRED_STATUS,
- indexConfig.schemaManagement().requiredStatus());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MINIMAL_REQUIRED_STATUS_WAIT_TIMEOUT,
- indexConfig.schemaManagement().requiredStatusWaitTimeout(), Optional::isPresent,
- d -> d.get().toMillis());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.INDEXING_QUEUE_COUNT,
- indexConfig.indexing().queueCount());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.INDEXING_QUEUE_SIZE,
- indexConfig.indexing().queueSize());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.INDEXING_MAX_BULK_SIZE,
- indexConfig.indexing().maxBulkSize());
- }
-
- // Settings that may default to a @SearchExtension-annotated-bean
- //
- }
-
@Override
public List> contributeServiceInitiators() {
return List.of(
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRuntimeConfigPersistenceUnit.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRuntimeConfigPersistenceUnit.java
index 4de16e8e61bc0..6817febb71aee 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRuntimeConfigPersistenceUnit.java
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRuntimeConfigPersistenceUnit.java
@@ -1,25 +1,19 @@
package io.quarkus.hibernate.search.orm.elasticsearch.runtime;
-import java.time.Duration;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Optional;
-import java.util.OptionalInt;
-import org.hibernate.search.backend.elasticsearch.index.IndexStatus;
-import org.hibernate.search.engine.cfg.spi.ParseUtils;
import org.hibernate.search.mapper.orm.schema.management.SchemaManagementStrategyName;
import org.hibernate.search.mapper.orm.search.loading.EntityLoadingCacheLookupStrategy;
-import org.hibernate.search.util.common.SearchException;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchBackendElasticsearchRuntimeConfig;
import io.quarkus.runtime.annotations.ConfigDocDefault;
import io.quarkus.runtime.annotations.ConfigDocMapKey;
import io.quarkus.runtime.annotations.ConfigDocSection;
import io.quarkus.runtime.annotations.ConfigGroup;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithName;
-import io.smallrye.config.WithParentName;
import io.smallrye.config.WithUnnamedKey;
@ConfigGroup
@@ -41,13 +35,13 @@ public interface HibernateSearchElasticsearchRuntimeConfigPersistenceUnit {
Optional active();
/**
- * Configuration for backends.
+ * Configuration for Elasticsearch/OpenSearch backends.
*/
@ConfigDocSection
@WithName("elasticsearch")
@WithUnnamedKey // The default backend has the null key
@ConfigDocMapKey("backend-name")
- Map backends();
+ Map backends();
/**
* Configuration for automatic creation and validation of the Elasticsearch schema:
@@ -79,181 +73,6 @@ public interface HibernateSearchElasticsearchRuntimeConfigPersistenceUnit {
*/
MultiTenancyConfig multiTenancy();
- @ConfigGroup
- interface ElasticsearchBackendRuntimeConfig {
- /**
- * The list of hosts of the Elasticsearch servers.
- */
- @WithDefault("localhost:9200")
- List hosts();
-
- /**
- * The protocol to use when contacting Elasticsearch servers.
- * Set to "https" to enable SSL/TLS.
- */
- @WithDefault("http")
- ElasticsearchClientProtocol protocol();
-
- /**
- * The username used for authentication.
- */
- Optional username();
-
- /**
- * The password used for authentication.
- */
- Optional password();
-
- /**
- * The timeout when establishing a connection to an Elasticsearch server.
- */
- @WithDefault("1S")
- Duration connectionTimeout();
-
- /**
- * The timeout when reading responses from an Elasticsearch server.
- */
- @WithDefault("30S")
- Duration readTimeout();
-
- /**
- * The timeout when executing a request to an Elasticsearch server.
- *
- * This includes the time needed to wait for a connection to be available,
- * send the request and read the response.
- *
- * @asciidoclet
- */
- Optional requestTimeout();
-
- /**
- * The maximum number of connections to all the Elasticsearch servers.
- */
- @WithDefault("20")
- int maxConnections();
-
- /**
- * The maximum number of connections per Elasticsearch server.
- */
- @WithDefault("10")
- int maxConnectionsPerRoute();
-
- /**
- * Configuration for the automatic discovery of new Elasticsearch nodes.
- */
- DiscoveryConfig discovery();
-
- /**
- * Configuration for the thread pool assigned to the backend.
- */
- ThreadPoolConfig threadPool();
-
- /**
- * Configuration for search queries to this backend.
- */
- ElasticsearchQueryConfig query();
-
- /**
- * Configuration for version checks on this backend.
- */
- ElasticsearchVersionCheckConfig versionCheck();
-
- /**
- * The default configuration for the Elasticsearch indexes.
- */
- @WithParentName
- ElasticsearchIndexRuntimeConfig indexDefaults();
-
- /**
- * Per-index configuration overrides.
- */
- @ConfigDocSection
- @ConfigDocMapKey("index-name")
- Map indexes();
-
- /**
- * Configuration for the index layout.
- */
- LayoutConfig layout();
- }
-
- enum ElasticsearchClientProtocol {
- /**
- * Use clear-text HTTP, with SSL/TLS disabled.
- */
- HTTP("http"),
- /**
- * Use HTTPS, with SSL/TLS enabled.
- */
- HTTPS("https");
-
- public static ElasticsearchClientProtocol of(String value) {
- return ParseUtils.parseDiscreteValues(
- values(),
- ElasticsearchClientProtocol::getHibernateSearchString,
- (invalidValue, validValues) -> new SearchException(
- String.format(
- Locale.ROOT,
- "Invalid protocol: '%1$s'. Valid protocols are: %2$s.",
- invalidValue,
- validValues)),
- value);
- }
-
- private final String hibernateSearchString;
-
- ElasticsearchClientProtocol(String hibernateSearchString) {
- this.hibernateSearchString = hibernateSearchString;
- }
-
- public String getHibernateSearchString() {
- return hibernateSearchString;
- }
- }
-
- @ConfigGroup
- interface ElasticsearchVersionCheckConfig {
- /**
- * Whether Hibernate Search should check the version of the Elasticsearch cluster on startup.
- *
- * Set to `false` if the Elasticsearch cluster may not be available on startup.
- *
- * @asciidoclet
- */
- @WithDefault("true")
- boolean enabled();
- }
-
- @ConfigGroup
- interface ElasticsearchIndexRuntimeConfig {
- /**
- * Configuration for the schema management of the indexes.
- */
- ElasticsearchIndexSchemaManagementConfig schemaManagement();
-
- /**
- * Configuration for the indexing process that creates, updates and deletes documents.
- */
- ElasticsearchIndexIndexingConfig indexing();
- }
-
- @ConfigGroup
- interface DiscoveryConfig {
-
- /**
- * Defines if automatic discovery is enabled.
- */
- @WithDefault("false")
- Boolean enabled();
-
- /**
- * Refresh interval of the node list.
- */
- @WithDefault("10S")
- Duration refreshInterval();
-
- }
-
@ConfigGroup
interface IndexingConfig {
@@ -501,124 +320,6 @@ interface SchemaManagementConfig {
}
- @ConfigGroup
- interface ThreadPoolConfig {
- /**
- * The size of the thread pool assigned to the backend.
- *
- * Note that number is **per backend**, not per index.
- * Adding more indexes will not add more threads.
- *
- * As all operations happening in this thread-pool are non-blocking,
- * raising its size above the number of processor cores available to the JVM will not bring noticeable performance
- * benefit.
- * The only reason to alter this setting would be to reduce the number of threads;
- * for example, in an application with a single index with a single indexing queue,
- * running on a machine with 64 processor cores,
- * you might want to bring down the number of threads.
- *
- * Defaults to the number of processor cores available to the JVM on startup.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- OptionalInt size();
- }
-
- @ConfigGroup
- interface ElasticsearchQueryConfig {
- /**
- * Configuration for the behavior on shard failure.
- */
- ElasticsearchQueryShardFailureConfig shardFailure();
- }
-
- @ConfigGroup
- interface ElasticsearchQueryShardFailureConfig {
- /**
- * Whether partial shard failures are ignored (`true`)
- * or lead to Hibernate Search throwing an exception (`false`).
- */
- @WithDefault("false")
- boolean ignore();
- }
-
- // We can't set actual default values in this section,
- // otherwise "quarkus.hibernate-search-orm.elasticsearch.index-defaults" will be ignored.
- @ConfigGroup
- interface ElasticsearchIndexSchemaManagementConfig {
- /**
- * The minimal https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster-health.html[Elasticsearch cluster
- * status] required on startup.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("yellow")
- Optional requiredStatus();
-
- /**
- * How long we should wait for the status before failing the bootstrap.
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("10S")
- Optional requiredStatusWaitTimeout();
- }
-
- // We can't set actual default values in this section,
- // otherwise "quarkus.hibernate-search-orm.elasticsearch.index-defaults" will be ignored.
- @ConfigGroup
- interface ElasticsearchIndexIndexingConfig {
- /**
- * The number of indexing queues assigned to each index.
- *
- * Higher values will lead to more connections being used in parallel,
- * which may lead to higher indexing throughput,
- * but incurs a risk of overloading Elasticsearch,
- * i.e. of overflowing its HTTP request buffers and tripping
- * https://www.elastic.co/guide/en/elasticsearch/reference/7.9/circuit-breaker.html[circuit breakers],
- * leading to Elasticsearch giving up on some request and resulting in indexing failures.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("10")
- OptionalInt queueCount();
-
- /**
- * The size of indexing queues.
- *
- * Lower values may lead to lower memory usage, especially if there are many queues,
- * but values that are too low will reduce the likeliness of reaching the max bulk size
- * and increase the likeliness of application threads blocking because the queue is full,
- * which may lead to lower indexing throughput.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("1000")
- OptionalInt queueSize();
-
- /**
- * The maximum size of bulk requests created when processing indexing queues.
- *
- * Higher values will lead to more documents being sent in each HTTP request sent to Elasticsearch,
- * which may lead to higher indexing throughput,
- * but incurs a risk of overloading Elasticsearch,
- * i.e. of overflowing its HTTP request buffers and tripping
- * https://www.elastic.co/guide/en/elasticsearch/reference/7.9/circuit-breaker.html[circuit breakers],
- * leading to Elasticsearch giving up on some request and resulting in indexing failures.
- *
- * Note that raising this number above the queue size has no effect,
- * as bulks cannot include more requests than are contained in the queue.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("100")
- OptionalInt maxBulkSize();
- }
-
@ConfigGroup
interface MultiTenancyConfig {
@@ -633,43 +334,4 @@ interface MultiTenancyConfig {
Optional> tenantIds();
}
-
- @ConfigGroup
- interface LayoutConfig {
- /**
- * A xref:hibernate-search-orm-elasticsearch.adoc#bean-reference-note-anchor[bean reference] to the component
- * used to configure the Elasticsearch layout: index names, index aliases, ...
- *
- * The referenced bean must implement `IndexLayoutStrategy`.
- *
- * Available built-in implementations:
- *
- * `simple`::
- * The default, future-proof strategy: if the index name in Hibernate Search is `myIndex`,
- * this strategy will create an index named `myindex-000001`, an alias for write operations named `myindex-write`,
- * and an alias for read operations named `myindex-read`.
- * `no-alias`::
- * A strategy without index aliases, mostly useful on legacy clusters:
- * if the index name in Hibernate Search is `myIndex`,
- * this strategy will create an index named `myindex`, and will not use any alias.
- *
- * See
- * link:{hibernate-search-docs-url}#backend-elasticsearch-indexlayout[this section of the reference documentation]
- * for more information.
- *
- * [NOTE]
- * ====
- * Instead of setting this configuration property,
- * you can simply annotate your custom `IndexLayoutStrategy` implementation with `@SearchExtension`
- * and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically.
- * See xref:hibernate-search-orm-elasticsearch.adoc#plugging-in-custom-components[this section]
- * for more information.
- *
- * If this configuration property is set, it takes precedence over any `@SearchExtension` annotation.
- * ====
- *
- * @asciidoclet
- */
- Optional strategy();
- }
}
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchOrmElasticsearchMapperContext.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchOrmElasticsearchMapperContext.java
new file mode 100644
index 0000000000000..df08b6028f206
--- /dev/null
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchOrmElasticsearchMapperContext.java
@@ -0,0 +1,66 @@
+package io.quarkus.hibernate.search.orm.elasticsearch.runtime;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import org.hibernate.search.engine.environment.bean.BeanReference;
+
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.MapperContext;
+import io.quarkus.hibernate.search.orm.elasticsearch.runtime.bean.HibernateSearchBeanUtil;
+import io.quarkus.runtime.annotations.RecordableConstructor;
+
+public final class HibernateSearchOrmElasticsearchMapperContext implements MapperContext {
+
+ public final String persistenceUnitName;
+ private final Set backendNamesForIndexedEntities;
+ private final Map> backendAndIndexNamesForSearchExtensions;
+
+ @RecordableConstructor
+ public HibernateSearchOrmElasticsearchMapperContext(String persistenceUnitName,
+ Set backendNamesForIndexedEntities,
+ Map> backendAndIndexNamesForSearchExtensions) {
+ if (persistenceUnitName == null) {
+ throw new IllegalArgumentException("persistenceUnitName cannot be null");
+ }
+ this.persistenceUnitName = persistenceUnitName;
+ this.backendNamesForIndexedEntities = backendNamesForIndexedEntities;
+ this.backendAndIndexNamesForSearchExtensions = backendAndIndexNamesForSearchExtensions;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + persistenceUnitName + "]";
+ }
+
+ @Override
+ public Set getBackendNamesForIndexedEntities() {
+ return backendNamesForIndexedEntities;
+ }
+
+ @Override
+ public Map> getBackendAndIndexNamesForSearchExtensions() {
+ return backendAndIndexNamesForSearchExtensions;
+ }
+
+ @Override
+ public String backendPropertyKey(String backendName, String indexName, String propertyKeyRadical) {
+ return HibernateSearchElasticsearchRuntimeConfig.backendPropertyKey(persistenceUnitName, backendName, indexName,
+ propertyKeyRadical);
+ }
+
+ @Override
+ public Optional> singleExtensionBeanReferenceFor(Optional override, Class beanType,
+ String backendName, String indexName) {
+ return HibernateSearchBeanUtil.singleExtensionBeanReferenceFor(override, beanType, persistenceUnitName, backendName,
+ indexName);
+ }
+
+ @Override
+ public Optional>> multiExtensionBeanReferencesFor(Optional> override,
+ Class beanType, String backendName, String indexName) {
+ return HibernateSearchBeanUtil.multiExtensionBeanReferencesFor(override, beanType, persistenceUnitName, backendName,
+ indexName);
+ }
+}
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/resources/META-INF/quarkus-extension.yaml
index 6c2d3dedc20f9..b19450a3ac1bd 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/resources/META-INF/quarkus-extension.yaml
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -1,6 +1,6 @@
---
artifact: ${project.groupId}:${project.artifactId}:${project.version}
-name: "Hibernate Search + Elasticsearch"
+name: "Hibernate Search ORM + Elasticsearch"
metadata:
keywords:
- "hibernate-search-orm-elasticsearch"
@@ -12,6 +12,7 @@ metadata:
- "hibernate-orm"
- "hibernate-search-orm"
- "elasticsearch"
+ - "opensearch"
guide: "https://quarkus.io/guides/hibernate-search-orm-elasticsearch"
categories:
- "data"
diff --git a/extensions/hibernate-search-standalone-elasticsearch/deployment/pom.xml b/extensions/hibernate-search-standalone-elasticsearch/deployment/pom.xml
index b4ad5c85ba44b..046916dc99544 100644
--- a/extensions/hibernate-search-standalone-elasticsearch/deployment/pom.xml
+++ b/extensions/hibernate-search-standalone-elasticsearch/deployment/pom.xml
@@ -21,6 +21,10 @@
io.quarkus
quarkus-elasticsearch-rest-client-common-deployment
+
+ io.quarkus
+ quarkus-hibernate-search-backend-elasticsearch-common-deployment
+
io.quarkus
quarkus-hibernate-search-standalone-elasticsearch
diff --git a/extensions/hibernate-search-standalone-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/deployment/HibernateSearchStandaloneEnabledBuildItem.java b/extensions/hibernate-search-standalone-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/deployment/HibernateSearchStandaloneEnabledBuildItem.java
index b2656fe55f899..bf86d0de6a4fe 100644
--- a/extensions/hibernate-search-standalone-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/deployment/HibernateSearchStandaloneEnabledBuildItem.java
+++ b/extensions/hibernate-search-standalone-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/deployment/HibernateSearchStandaloneEnabledBuildItem.java
@@ -1,32 +1,21 @@
package io.quarkus.hibernate.search.standalone.elasticsearch.deployment;
-import java.util.Map;
import java.util.Set;
import io.quarkus.builder.item.SimpleBuildItem;
+import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneElasticsearchMapperContext;
public final class HibernateSearchStandaloneEnabledBuildItem extends SimpleBuildItem {
- private final Set backendNamesForIndexedEntities;
- private final Map> backendAndIndexNamesForSearchExtensions;
+ final HibernateSearchStandaloneElasticsearchMapperContext mapperContext;
private final Set rootAnnotationMappedClassNames;
- public HibernateSearchStandaloneEnabledBuildItem(Set backendNamesForIndexedEntities,
- Map> backendAndIndexNamesForSearchExtensions,
+ public HibernateSearchStandaloneEnabledBuildItem(HibernateSearchStandaloneElasticsearchMapperContext mapperContext,
Set rootAnnotationMappedClassNames) {
- this.backendNamesForIndexedEntities = backendNamesForIndexedEntities;
- this.backendAndIndexNamesForSearchExtensions = backendAndIndexNamesForSearchExtensions;
+ this.mapperContext = mapperContext;
this.rootAnnotationMappedClassNames = rootAnnotationMappedClassNames;
}
- public Set getBackendNamesForIndexedEntities() {
- return backendNamesForIndexedEntities;
- }
-
- public Map> getBackendAndIndexNamesForSearchExtensions() {
- return backendAndIndexNamesForSearchExtensions;
- }
-
public Set getRootAnnotationMappedClassNames() {
return rootAnnotationMappedClassNames;
}
diff --git a/extensions/hibernate-search-standalone-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/deployment/HibernateSearchStandaloneProcessor.java b/extensions/hibernate-search-standalone-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/deployment/HibernateSearchStandaloneProcessor.java
index d2f67cc817f25..dc7dc6f88f6d8 100644
--- a/extensions/hibernate-search-standalone-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/deployment/HibernateSearchStandaloneProcessor.java
+++ b/extensions/hibernate-search-standalone-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/deployment/HibernateSearchStandaloneProcessor.java
@@ -5,19 +5,14 @@
import static io.quarkus.hibernate.search.standalone.elasticsearch.deployment.HibernateSearchTypes.ROOT_MAPPING;
import static io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneRuntimeConfig.backendPropertyKey;
import static io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneRuntimeConfig.defaultBackendPropertyKeys;
-import static io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneRuntimeConfig.elasticsearchVersionPropertyKey;
import static io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneRuntimeConfig.mapperPropertyKey;
import static io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneRuntimeConfig.mapperPropertyKeys;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.util.Collection;
-import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
@@ -25,7 +20,6 @@
import jakarta.enterprise.inject.Default;
import org.hibernate.search.backend.elasticsearch.ElasticsearchVersion;
-import org.hibernate.search.backend.elasticsearch.gson.spi.GsonClasses;
import org.hibernate.search.mapper.pojo.standalone.mapping.SearchMapping;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;
@@ -46,25 +40,21 @@
import io.quarkus.deployment.annotations.Consume;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
-import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.DevServicesAdditionalConfigBuildItem;
-import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
import io.quarkus.deployment.builditem.ServiceStartBuildItem;
-import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.recording.RecorderContext;
import io.quarkus.deployment.util.JandexUtil;
import io.quarkus.elasticsearch.restclient.common.deployment.DevservicesElasticsearchBuildItem;
import io.quarkus.elasticsearch.restclient.common.deployment.ElasticsearchCommonBuildTimeConfig.ElasticsearchDevServicesBuildTimeConfig.Distribution;
-import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.ElasticsearchVersionSubstitution;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.deployment.HibernateSearchBackendElasticsearchEnabledBuildItem;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.ElasticsearchVersionSubstitution;
import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneBuildTimeConfig;
-import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneBuildTimeConfig.ElasticsearchBackendBuildTimeConfig;
-import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneBuildTimeConfig.ElasticsearchIndexBuildTimeConfig;
+import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneElasticsearchMapperContext;
import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneRecorder;
import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneRuntimeConfig;
import io.quarkus.runtime.configuration.ConfigUtils;
-import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.vertx.http.deployment.spi.RouteBuildItem;
@BuildSteps(onlyIf = HibernateSearchStandaloneEnabled.class)
@@ -99,8 +89,6 @@ public void configure(CombinedIndexBuildItem combinedIndexBuildItem,
return;
}
- registerReflectionForGson(reflectiveClass);
-
Set backendNamesForIndexedEntities = new LinkedHashSet<>();
for (AnnotationInstance indexedAnnotation : indexedAnnotations) {
AnnotationValue backendNameValue = indexedAnnotation.value("backend");
@@ -113,8 +101,21 @@ public void configure(CombinedIndexBuildItem combinedIndexBuildItem,
Set rootAnnotationMappedClassNames = collectRootAnnotationMappedClassNames(index);
- enabled.produce(new HibernateSearchStandaloneEnabledBuildItem(backendNamesForIndexedEntities,
- backendAndIndexNamesForSearchExtensions, rootAnnotationMappedClassNames));
+ var mapperContext = new HibernateSearchStandaloneElasticsearchMapperContext(backendNamesForIndexedEntities,
+ backendAndIndexNamesForSearchExtensions);
+ enabled.produce(new HibernateSearchStandaloneEnabledBuildItem(mapperContext, rootAnnotationMappedClassNames));
+ }
+
+ @BuildStep
+ void enableBackend(Optional enabled,
+ HibernateSearchStandaloneBuildTimeConfig buildTimeConfig,
+ BuildProducer elasticsearchEnabled) {
+ if (!enabled.isPresent()) {
+ // No boot
+ return;
+ }
+ elasticsearchEnabled.produce(new HibernateSearchBackendElasticsearchEnabledBuildItem(enabled.get().mapperContext,
+ buildTimeConfig.backends()));
}
private static Map> collectBackendAndIndexNamesForSearchExtensions(
@@ -160,104 +161,6 @@ private static Set collectRootAnnotationMappedClassNames(IndexView index
return rootAnnotationMappedClassNames;
}
- @BuildStep
- public void processBuildTimeConfig(Optional enabled,
- HibernateSearchStandaloneBuildTimeConfig buildTimeConfig,
- ApplicationArchivesBuildItem applicationArchivesBuildItem,
- BuildProducer nativeImageResources,
- BuildProducer hotDeploymentWatchedFiles) {
- if (enabled.isEmpty()) {
- // Disabled => no config processing necessary
- return;
- }
- Set propertyKeysWithNoVersion = new LinkedHashSet<>();
- Map backends = buildTimeConfig != null
- ? buildTimeConfig.backends()
- : Collections.emptyMap();
-
- Set allBackendNames = new LinkedHashSet<>(enabled.get().getBackendNamesForIndexedEntities());
- allBackendNames.addAll(backends.keySet());
- // For all backends referenced either through @Indexed(backend = ...) or configuration...
- for (String backendName : allBackendNames) {
- ElasticsearchBackendBuildTimeConfig backendConfig = backends.get(backendName);
- // ... we validate that the backend is configured and the version is present
- if (backendConfig == null || backendConfig.version().isEmpty()) {
- propertyKeysWithNoVersion.add(elasticsearchVersionPropertyKey(backendName));
- }
- // ... we register files referenced from backends configuration
- if (backendConfig != null) {
- registerClasspathFileFromBackendConfig(backendName, backendConfig,
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- }
- }
- if (!propertyKeysWithNoVersion.isEmpty()) {
- throw new ConfigurationException(
- "The Elasticsearch version needs to be defined via properties: "
- + String.join(", ", propertyKeysWithNoVersion) + ".",
- propertyKeysWithNoVersion);
- }
- }
-
- private static void registerClasspathFileFromBackendConfig(String backendName,
- ElasticsearchBackendBuildTimeConfig backendConfig,
- ApplicationArchivesBuildItem applicationArchivesBuildItem,
- BuildProducer nativeImageResources,
- BuildProducer hotDeploymentWatchedFiles) {
- registerClasspathFileFromIndexConfig(backendName, null, backendConfig.indexDefaults(),
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- for (Entry entry : backendConfig.indexes().entrySet()) {
- String indexName = entry.getKey();
- ElasticsearchIndexBuildTimeConfig indexConfig = entry.getValue();
- registerClasspathFileFromIndexConfig(backendName, indexName, indexConfig,
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- }
- }
-
- private static void registerClasspathFileFromIndexConfig(String backendName, String indexName,
- ElasticsearchIndexBuildTimeConfig indexConfig,
- ApplicationArchivesBuildItem applicationArchivesBuildItem,
- BuildProducer nativeImageResources,
- BuildProducer hotDeploymentWatchedFiles) {
- registerClasspathFileFromConfig(backendName, indexName, "schema-management.settings-file",
- indexConfig.schemaManagement().settingsFile(),
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- registerClasspathFileFromConfig(backendName, indexName, "schema-management.mapping-file",
- indexConfig.schemaManagement().mappingFile(),
- applicationArchivesBuildItem, nativeImageResources, hotDeploymentWatchedFiles);
- }
-
- private static void registerClasspathFileFromConfig(String backendName, String indexName,
- String propertyKeyRadical,
- Optional classpathFileOptional,
- ApplicationArchivesBuildItem applicationArchivesBuildItem,
- BuildProducer nativeImageResources,
- BuildProducer hotDeploymentWatchedFiles) {
- if (!classpathFileOptional.isPresent()) {
- return;
- }
- String classpathFile = classpathFileOptional.get();
-
- Path existingPath = applicationArchivesBuildItem.getRootArchive().getChildPath(classpathFile);
-
- if (existingPath == null || Files.isDirectory(existingPath)) {
- //raise exception if explicit file is not present (i.e. not the default)
- throw new ConfigurationException(
- "Unable to find file referenced in '"
- + backendPropertyKey(backendName, indexName, propertyKeyRadical) + "="
- + classpathFile
- + "'. Remove property or add file to your path.");
- }
- nativeImageResources.produce(new NativeImageResourceBuildItem(classpathFile));
- hotDeploymentWatchedFiles.produce(new HotDeploymentWatchedFileBuildItem(classpathFile));
- }
-
- private void registerReflectionForGson(BuildProducer reflectiveClass) {
- String[] reflectiveClasses = GsonClasses.typesRequiringReflection().toArray(String[]::new);
- reflectiveClass.produce(ReflectiveClassBuildItem.builder(reflectiveClasses)
- .reason(getClass().getName())
- .methods().fields().build());
- }
-
@Record(ExecutionTime.RUNTIME_INIT)
@BuildStep
void defineSearchMappingBean(Optional enabled,
@@ -276,8 +179,7 @@ void defineSearchMappingBean(Optional
.unremovable()
.addQualifier(Default.class)
.setRuntimeInit()
- .createWith(recorder.createSearchMappingFunction(runtimeConfig,
- enabled.get().getBackendAndIndexNamesForSearchExtensions()))
+ .createWith(recorder.createSearchMappingFunction(enabled.get().mapperContext, runtimeConfig))
.destroyer(BeanDestroyer.AutoCloseableDestroyer.class)
.done());
}
@@ -297,7 +199,7 @@ public void preBoot(Optional enabled,
// Make it possible to record the settings as bytecode:
recorderContext.registerSubstitution(ElasticsearchVersion.class,
String.class, ElasticsearchVersionSubstitution.class);
- recorder.preBoot(buildTimeConfig, enabled.get().getBackendAndIndexNamesForSearchExtensions(),
+ recorder.preBoot(enabled.get().mapperContext, buildTimeConfig,
enabled.get().getRootAnnotationMappedClassNames());
}
diff --git a/extensions/hibernate-search-standalone-elasticsearch/runtime/pom.xml b/extensions/hibernate-search-standalone-elasticsearch/runtime/pom.xml
index d71267a449b66..14d0bf298bdd0 100644
--- a/extensions/hibernate-search-standalone-elasticsearch/runtime/pom.xml
+++ b/extensions/hibernate-search-standalone-elasticsearch/runtime/pom.xml
@@ -22,8 +22,8 @@
quarkus-elasticsearch-rest-client-common
- org.hibernate.search
- hibernate-search-backend-elasticsearch
+ io.quarkus
+ quarkus-hibernate-search-backend-elasticsearch-common
org.hibernate.search
diff --git a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/ElasticsearchVersionSubstitution.java b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/ElasticsearchVersionSubstitution.java
deleted file mode 100644
index fc2bb9f0e70cf..0000000000000
--- a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/ElasticsearchVersionSubstitution.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.quarkus.hibernate.search.standalone.elasticsearch.runtime;
-
-import org.hibernate.search.backend.elasticsearch.ElasticsearchVersion;
-
-import io.quarkus.runtime.ObjectSubstitution;
-
-public class ElasticsearchVersionSubstitution implements ObjectSubstitution {
- @Override
- public String serialize(ElasticsearchVersion obj) {
- return obj.toString();
- }
-
- @Override
- public ElasticsearchVersion deserialize(String obj) {
- return ElasticsearchVersion.of(obj);
- }
-}
diff --git a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneBuildTimeConfig.java b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneBuildTimeConfig.java
index 14c699821b8c4..616f87521052a 100644
--- a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneBuildTimeConfig.java
+++ b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneBuildTimeConfig.java
@@ -4,8 +4,7 @@
import java.util.Map;
import java.util.Optional;
-import org.hibernate.search.backend.elasticsearch.ElasticsearchVersion;
-
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchBackendElasticsearchBuildTimeConfig;
import io.quarkus.runtime.annotations.ConfigDocMapKey;
import io.quarkus.runtime.annotations.ConfigDocSection;
import io.quarkus.runtime.annotations.ConfigGroup;
@@ -14,7 +13,6 @@
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithName;
-import io.smallrye.config.WithParentName;
import io.smallrye.config.WithUnnamedKey;
@ConfigMapping(prefix = "quarkus.hibernate-search-standalone")
@@ -34,16 +32,16 @@ public interface HibernateSearchStandaloneBuildTimeConfig {
boolean enabled();
/**
- * Configuration for backends.
+ * Configuration for Elasticsearch/OpenSearch backends.
*/
@ConfigDocSection
@WithName("elasticsearch")
@WithUnnamedKey // The default backend has the null key
@ConfigDocMapKey("backend-name")
- Map backends();
+ Map backends();
/**
- * A xref:hibernate-search-stqndqlone-elasticsearch.adoc#bean-reference-note-anchor[bean reference] to a component
+ * A xref:hibernate-search-standalone-elasticsearch.adoc#bean-reference-note-anchor[bean reference] to a component
* that should be notified of any failure occurring in a background process
* (mainly index operations).
*
@@ -58,7 +56,7 @@ public interface HibernateSearchStandaloneBuildTimeConfig {
* Instead of setting this configuration property,
* you can simply annotate your custom `FailureHandler` implementation with `@SearchExtension`
* and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically.
- * See xref:hibernate-search-stqndqlone-elasticsearch.adoc#plugging-in-custom-components[this section]
+ * See xref:hibernate-search-standalone-elasticsearch.adoc#plugging-in-custom-components[this section]
* for more information.
*
* If this configuration property is set, it takes precedence over any `@SearchExtension` annotation.
@@ -79,117 +77,6 @@ public interface HibernateSearchStandaloneBuildTimeConfig {
*/
MappingConfig mapping();
- @ConfigGroup
- interface ElasticsearchBackendBuildTimeConfig {
- /**
- * The version of Elasticsearch used in the cluster.
- *
- * As the schema is generated without a connection to the server, this item is mandatory.
- *
- * It doesn't have to be the exact version (it can be `7` or `7.1` for instance) but it has to be sufficiently precise
- * to choose a model dialect (the one used to generate the schema) compatible with the protocol dialect (the one used
- * to communicate with Elasticsearch).
- *
- * There's no rule of thumb here as it depends on the schema incompatibilities introduced by Elasticsearch versions. In
- * any case, if there is a problem, you will have an error when Hibernate Search tries to connect to the cluster.
- *
- * @asciidoclet
- */
- Optional version();
-
- /**
- * The default configuration for the Elasticsearch indexes.
- */
- @WithParentName
- ElasticsearchIndexBuildTimeConfig indexDefaults();
-
- /**
- * Per-index configuration overrides.
- */
- @ConfigDocSection
- @ConfigDocMapKey("index-name")
- Map indexes();
- }
-
- @ConfigGroup
- interface ElasticsearchIndexBuildTimeConfig {
- /**
- * Configuration for automatic creation and validation of the Elasticsearch schema:
- * indexes, their mapping, their settings.
- */
- SchemaManagementConfig schemaManagement();
-
- /**
- * Configuration for full-text analysis.
- */
- AnalysisConfig analysis();
- }
-
- @ConfigGroup
- interface SchemaManagementConfig {
-
- // @formatter:off
- /**
- * Path to a file in the classpath holding custom index settings to be included in the index definition
- * when creating an Elasticsearch index.
- *
- * The provided settings will be merged with those generated by Hibernate Search, including analyzer definitions.
- * When analysis is configured both through an analysis configurer and these custom settings, the behavior is undefined;
- * it should not be relied upon.
- *
- * See link:{hibernate-search-docs-url}#backend-elasticsearch-configuration-index-settings[this section of the reference documentation]
- * for more information.
- *
- * @asciidoclet
- */
- // @formatter:on
- Optional settingsFile();
-
- // @formatter:off
- /**
- * Path to a file in the classpath holding a custom index mapping to be included in the index definition
- * when creating an Elasticsearch index.
- *
- * The file does not need to (and generally shouldn't) contain the full mapping:
- * Hibernate Search will automatically inject missing properties (index fields) in the given mapping.
- *
- * See link:{hibernate-search-docs-url}#backend-elasticsearch-mapping-custom[this section of the reference documentation]
- * for more information.
- *
- * @asciidoclet
- */
- // @formatter:on
- Optional mappingFile();
-
- }
-
- @ConfigGroup
- interface AnalysisConfig {
- /**
- * One or more xref:hibernate-search-standalone-elasticsearch.adoc#bean-reference-note-anchor[bean references]
- * to the component(s) used to configure full text analysis (e.g. analyzers, normalizers).
- *
- * The referenced beans must implement `ElasticsearchAnalysisConfigurer`.
- *
- * See xref:hibernate-search-standalone-elasticsearch.adoc#analysis-configurer[Setting up the analyzers] for more
- * information.
- *
- * [NOTE]
- * ====
- * Instead of setting this configuration property,
- * you can simply annotate your custom `ElasticsearchAnalysisConfigurer` implementations with `@SearchExtension`
- * and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically.
- * See xref:hibernate-search-standalone-elasticsearch.adoc#plugging-in-custom-components[this section]
- * for more information.
- *
- * If this configuration property is set, it takes precedence over any `@SearchExtension` annotation.
- * ====
- *
- * @asciidoclet
- */
- Optional> configurer();
- }
-
@ConfigGroup
interface MappingConfig {
/**
diff --git a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneElasticsearchMapperContext.java b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneElasticsearchMapperContext.java
new file mode 100644
index 0000000000000..950d4e0860279
--- /dev/null
+++ b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneElasticsearchMapperContext.java
@@ -0,0 +1,57 @@
+package io.quarkus.hibernate.search.standalone.elasticsearch.runtime;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import org.hibernate.search.engine.environment.bean.BeanReference;
+
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.MapperContext;
+import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.bean.HibernateSearchBeanUtil;
+import io.quarkus.runtime.annotations.RecordableConstructor;
+
+public final class HibernateSearchStandaloneElasticsearchMapperContext implements MapperContext {
+
+ private final Set backendNamesForIndexedEntities;
+ private final Map> backendAndIndexNamesForSearchExtensions;
+
+ @RecordableConstructor
+ public HibernateSearchStandaloneElasticsearchMapperContext(Set backendNamesForIndexedEntities,
+ Map> backendAndIndexNamesForSearchExtensions) {
+ this.backendNamesForIndexedEntities = backendNamesForIndexedEntities;
+ this.backendAndIndexNamesForSearchExtensions = backendAndIndexNamesForSearchExtensions;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{}";
+ }
+
+ @Override
+ public Set getBackendNamesForIndexedEntities() {
+ return backendNamesForIndexedEntities;
+ }
+
+ @Override
+ public Map> getBackendAndIndexNamesForSearchExtensions() {
+ return backendAndIndexNamesForSearchExtensions;
+ }
+
+ @Override
+ public String backendPropertyKey(String backendName, String indexName, String propertyKeyRadical) {
+ return HibernateSearchStandaloneRuntimeConfig.backendPropertyKey(backendName, indexName, propertyKeyRadical);
+ }
+
+ @Override
+ public Optional> singleExtensionBeanReferenceFor(Optional override, Class beanType,
+ String backendName, String indexName) {
+ return HibernateSearchBeanUtil.singleExtensionBeanReferenceFor(override, beanType, backendName, indexName);
+ }
+
+ @Override
+ public Optional>> multiExtensionBeanReferencesFor(Optional> override,
+ Class beanType, String backendName, String indexName) {
+ return HibernateSearchBeanUtil.multiExtensionBeanReferencesFor(override, beanType, backendName, indexName);
+ }
+}
diff --git a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneRecorder.java b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneRecorder.java
index 708be069ddb1f..9bccbd6789a21 100644
--- a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneRecorder.java
+++ b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneRecorder.java
@@ -1,8 +1,6 @@
package io.quarkus.hibernate.search.standalone.elasticsearch.runtime;
-import static io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchConfigUtil.addBackendConfig;
-import static io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchConfigUtil.addBackendIndexConfig;
-import static io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchConfigUtil.addConfig;
+import static io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchConfigUtil.addConfig;
import java.util.ArrayList;
import java.util.Collections;
@@ -10,17 +8,11 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;
-import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer;
-import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchBackendSettings;
-import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchIndexSettings;
-import org.hibernate.search.backend.elasticsearch.index.layout.IndexLayoutStrategy;
-import org.hibernate.search.engine.cfg.BackendSettings;
import org.hibernate.search.engine.cfg.EngineSettings;
import org.hibernate.search.engine.environment.bean.BeanReference;
import org.hibernate.search.engine.reporting.FailureHandler;
@@ -34,10 +26,7 @@
import io.quarkus.arc.Arc;
import io.quarkus.arc.SyntheticCreationalContext;
-import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneBuildTimeConfig.ElasticsearchBackendBuildTimeConfig;
-import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneBuildTimeConfig.ElasticsearchIndexBuildTimeConfig;
-import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneRuntimeConfig.ElasticsearchBackendRuntimeConfig;
-import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.HibernateSearchStandaloneRuntimeConfig.ElasticsearchIndexRuntimeConfig;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchBackendElasticsearchConfigHandler;
import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.bean.ArcBeanProvider;
import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.bean.HibernateSearchBeanUtil;
import io.quarkus.hibernate.search.standalone.elasticsearch.runtime.management.HibernateSearchStandaloneManagementHandler;
@@ -50,8 +39,8 @@
@Recorder
public class HibernateSearchStandaloneRecorder {
- public void preBoot(HibernateSearchStandaloneBuildTimeConfig buildTimeConfig,
- Map> backendAndIndexNamesForSearchExtensions,
+ public void preBoot(HibernateSearchStandaloneElasticsearchMapperContext mapperContext,
+ HibernateSearchStandaloneBuildTimeConfig buildTimeConfig,
Set rootAnnotationMappedClassNames) {
Set> rootAnnotationMappedClasses = new LinkedHashSet<>();
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
@@ -63,7 +52,7 @@ public void preBoot(HibernateSearchStandaloneBuildTimeConfig buildTimeConfig,
}
}
Map bootProperties = new LinkedHashMap<>();
- new StaticInitListener(buildTimeConfig, backendAndIndexNamesForSearchExtensions, rootAnnotationMappedClasses)
+ new StaticInitListener(mapperContext, buildTimeConfig, rootAnnotationMappedClasses)
.contributeBootProperties(bootProperties::put);
StandalonePojoIntegrationBooter booter = StandalonePojoIntegrationBooter.builder()
.properties(bootProperties)
@@ -98,8 +87,8 @@ public void clearPreBootState() {
}
public Function, SearchMapping> createSearchMappingFunction(
- HibernateSearchStandaloneRuntimeConfig runtimeConfig,
- Map> backendAndIndexNamesForSearchExtensions) {
+ HibernateSearchStandaloneElasticsearchMapperContext mapperContext,
+ HibernateSearchStandaloneRuntimeConfig runtimeConfig) {
return new Function, SearchMapping>() {
@Override
public SearchMapping apply(SyntheticCreationalContext context) {
@@ -108,7 +97,7 @@ public SearchMapping apply(SyntheticCreationalContext context) {
"Cannot retrieve the SearchMapping: Hibernate Search Standalone was deactivated through configuration properties");
}
Map bootProperties = new LinkedHashMap<>(HibernateSearchStandalonePreBootState.pop());
- new RuntimeInitListener(runtimeConfig, backendAndIndexNamesForSearchExtensions)
+ new RuntimeInitListener(mapperContext, runtimeConfig)
.contributeRuntimeProperties(bootProperties::put);
StandalonePojoIntegrationBooter booter = StandalonePojoIntegrationBooter.builder()
.properties(bootProperties)
@@ -133,15 +122,15 @@ public Handler managementHandler() {
}
private static final class StaticInitListener {
+ private final HibernateSearchStandaloneElasticsearchMapperContext mapperContext;
private final HibernateSearchStandaloneBuildTimeConfig buildTimeConfig;
- private final Map> backendAndIndexNamesForSearchExtensions;
private final Set> rootAnnotationMappedClasses;
- private StaticInitListener(HibernateSearchStandaloneBuildTimeConfig buildTimeConfig,
- Map> backendAndIndexNamesForSearchExtensions,
+ private StaticInitListener(HibernateSearchStandaloneElasticsearchMapperContext mapperContext,
+ HibernateSearchStandaloneBuildTimeConfig buildTimeConfig,
Set> rootAnnotationMappedClasses) {
+ this.mapperContext = mapperContext;
this.buildTimeConfig = buildTimeConfig;
- this.backendAndIndexNamesForSearchExtensions = backendAndIndexNamesForSearchExtensions;
this.rootAnnotationMappedClasses = rootAnnotationMappedClasses;
}
@@ -157,25 +146,9 @@ public void contributeBootProperties(BiConsumer propertyCollecto
StandalonePojoMapperSettings.MAPPING_CONFIGURER,
collectAllStandalonePojoMappingConfigurers());
- // We need this weird collecting of names from both @SearchExtension and the configuration properties
- // because a backend/index could potentially be configured exclusively through configuration properties,
- // or exclusively through @SearchExtension.
- // (Well maybe not for backends, but... let's keep it simple.)
- Map backendConfigs = buildTimeConfig == null
- ? Collections.emptyMap()
- : buildTimeConfig.backends();
- Map> backendAndIndexNames = new LinkedHashMap<>();
- mergeInto(backendAndIndexNames, backendAndIndexNamesForSearchExtensions);
- for (Entry entry : backendConfigs.entrySet()) {
- mergeInto(backendAndIndexNames, entry.getKey(), entry.getValue().indexes().keySet());
- }
-
- for (Entry> entry : backendAndIndexNames.entrySet()) {
- String backendName = entry.getKey();
- Set indexNames = entry.getValue();
- contributeBackendBuildTimeProperties(propertyCollector, backendName, indexNames,
- backendConfigs.get(backendName));
- }
+ HibernateSearchBackendElasticsearchConfigHandler.contributeBackendBuildTimeProperties(
+ propertyCollector, mapperContext,
+ buildTimeConfig == null ? Collections.emptyMap() : buildTimeConfig.backends());
}
private List> collectAllStandalonePojoMappingConfigurers() {
@@ -195,59 +168,16 @@ private List> collectAllStandalon
return configurers;
}
-
- private void contributeBackendBuildTimeProperties(BiConsumer propertyCollector, String backendName,
- Set indexNames,
- ElasticsearchBackendBuildTimeConfig elasticsearchBackendConfig) {
- addBackendConfig(propertyCollector, backendName, BackendSettings.TYPE,
- ElasticsearchBackendSettings.TYPE_NAME);
- if (elasticsearchBackendConfig != null) {
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.VERSION,
- elasticsearchBackendConfig.version());
- }
-
- // Index defaults at the backend level
- contributeBackendIndexBuildTimeProperties(propertyCollector, backendName, null,
- elasticsearchBackendConfig == null ? null : elasticsearchBackendConfig.indexDefaults());
-
- // Per-index properties
- for (String indexName : indexNames) {
- ElasticsearchIndexBuildTimeConfig indexConfig = elasticsearchBackendConfig == null ? null
- : elasticsearchBackendConfig.indexes().get(indexName);
- contributeBackendIndexBuildTimeProperties(propertyCollector, backendName, indexName, indexConfig);
- }
- }
-
- private void contributeBackendIndexBuildTimeProperties(BiConsumer propertyCollector,
- String backendName, String indexName, ElasticsearchIndexBuildTimeConfig indexConfig) {
- if (indexConfig != null) {
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_SETTINGS_FILE,
- indexConfig.schemaManagement().settingsFile());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MAPPING_FILE,
- indexConfig.schemaManagement().mappingFile());
- }
-
- // Settings that may default to a @SearchExtension-annotated-bean
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.ANALYSIS_CONFIGURER,
- HibernateSearchBeanUtil.multiExtensionBeanReferencesFor(
- indexConfig == null ? Optional.empty()
- : indexConfig.analysis().configurer(),
- ElasticsearchAnalysisConfigurer.class, backendName,
- indexName));
- }
}
private static final class RuntimeInitListener {
+ private final HibernateSearchStandaloneElasticsearchMapperContext mapperContext;
private final HibernateSearchStandaloneRuntimeConfig runtimeConfig;
- private final Map> backendAndIndexNamesForSearchExtensions;
- private RuntimeInitListener(HibernateSearchStandaloneRuntimeConfig runtimeConfig,
- Map> backendAndIndexNamesForSearchExtensions) {
+ private RuntimeInitListener(HibernateSearchStandaloneElasticsearchMapperContext mapperContext,
+ HibernateSearchStandaloneRuntimeConfig runtimeConfig) {
+ this.mapperContext = mapperContext;
this.runtimeConfig = runtimeConfig;
- this.backendAndIndexNamesForSearchExtensions = backendAndIndexNamesForSearchExtensions;
}
public void contributeRuntimeProperties(BiConsumer propertyCollector) {
@@ -264,119 +194,9 @@ public void contributeRuntimeProperties(BiConsumer propertyColle
: runtimeConfig.indexing().plan().synchronization().strategy(),
IndexingPlanSynchronizationStrategy.class, null, null));
- // We need this weird collecting of names from both @SearchExtension and the configuration properties
- // because a backend/index could potentially be configured exclusively through configuration properties,
- // or exclusively through @SearchExtension.
- // (Well maybe not for backends, but... let's keep it simple.)
- Map backendConfigs = runtimeConfig == null
- ? Collections.emptyMap()
- : runtimeConfig.backends();
- Map> backendAndIndexNames = new LinkedHashMap<>();
- mergeInto(backendAndIndexNames, backendAndIndexNamesForSearchExtensions);
- for (Entry entry : backendConfigs.entrySet()) {
- mergeInto(backendAndIndexNames, entry.getKey(), entry.getValue().indexes().keySet());
- }
-
- for (Entry> entry : backendAndIndexNames.entrySet()) {
- String backendName = entry.getKey();
- Set indexNames = entry.getValue();
- contributeBackendRuntimeProperties(propertyCollector, backendName, indexNames,
- backendConfigs.get(backendName));
- }
+ HibernateSearchBackendElasticsearchConfigHandler.contributeBackendRuntimeProperties(
+ propertyCollector, mapperContext,
+ runtimeConfig == null ? Collections.emptyMap() : runtimeConfig.backends());
}
-
- private void contributeBackendRuntimeProperties(BiConsumer propertyCollector, String backendName,
- Set indexNames, ElasticsearchBackendRuntimeConfig elasticsearchBackendConfig) {
- if (elasticsearchBackendConfig != null) {
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.HOSTS,
- elasticsearchBackendConfig.hosts());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.PROTOCOL,
- elasticsearchBackendConfig.protocol().getHibernateSearchString());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.USERNAME,
- elasticsearchBackendConfig.username());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.PASSWORD,
- elasticsearchBackendConfig.password());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.CONNECTION_TIMEOUT,
- elasticsearchBackendConfig.connectionTimeout().toMillis());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.READ_TIMEOUT,
- elasticsearchBackendConfig.readTimeout().toMillis());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.REQUEST_TIMEOUT,
- elasticsearchBackendConfig.requestTimeout(), Optional::isPresent, d -> d.get().toMillis());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.MAX_CONNECTIONS,
- elasticsearchBackendConfig.maxConnections());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.MAX_CONNECTIONS_PER_ROUTE,
- elasticsearchBackendConfig.maxConnectionsPerRoute());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.THREAD_POOL_SIZE,
- elasticsearchBackendConfig.threadPool().size());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.VERSION_CHECK_ENABLED,
- elasticsearchBackendConfig.versionCheck().enabled());
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.QUERY_SHARD_FAILURE_IGNORE,
- elasticsearchBackendConfig.query().shardFailure().ignore());
-
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.DISCOVERY_ENABLED,
- elasticsearchBackendConfig.discovery().enabled());
- if (elasticsearchBackendConfig.discovery().enabled()) {
- addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.DISCOVERY_REFRESH_INTERVAL,
- elasticsearchBackendConfig.discovery().refreshInterval().getSeconds());
- }
-
- // Settings that may default to a @SearchExtension-annotated-bean
- addBackendConfig(propertyCollector, backendName,
- ElasticsearchBackendSettings.LAYOUT_STRATEGY,
- HibernateSearchBeanUtil.singleExtensionBeanReferenceFor(
- elasticsearchBackendConfig.layout().strategy(),
- IndexLayoutStrategy.class, backendName, null));
- }
-
- // Settings that may default to a @SearchExtension-annotated-bean
- //
-
- // Index defaults at the backend level
- contributeBackendIndexRuntimeProperties(propertyCollector, backendName, null,
- elasticsearchBackendConfig == null ? null : elasticsearchBackendConfig.indexDefaults());
-
- // Per-index properties
- for (String indexName : indexNames) {
- ElasticsearchIndexRuntimeConfig indexConfig = elasticsearchBackendConfig == null ? null
- : elasticsearchBackendConfig.indexes().get(indexName);
- contributeBackendIndexRuntimeProperties(propertyCollector, backendName, indexName, indexConfig);
- }
- }
-
- private void contributeBackendIndexRuntimeProperties(BiConsumer propertyCollector,
- String backendName, String indexName, ElasticsearchIndexRuntimeConfig indexConfig) {
- if (indexConfig != null) {
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MINIMAL_REQUIRED_STATUS,
- indexConfig.schemaManagement().requiredStatus());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MINIMAL_REQUIRED_STATUS_WAIT_TIMEOUT,
- indexConfig.schemaManagement().requiredStatusWaitTimeout(), Optional::isPresent,
- d -> d.get().toMillis());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.INDEXING_QUEUE_COUNT,
- indexConfig.indexing().queueCount());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.INDEXING_QUEUE_SIZE,
- indexConfig.indexing().queueSize());
- addBackendIndexConfig(propertyCollector, backendName, indexName,
- ElasticsearchIndexSettings.INDEXING_MAX_BULK_SIZE,
- indexConfig.indexing().maxBulkSize());
- }
-
- // Settings that may default to a @SearchExtension-annotated-bean
- //
- }
- }
-
- private static void mergeInto(Map> target, Map> source) {
- for (Entry> entry : source.entrySet()) {
- mergeInto(target, entry.getKey(), entry.getValue());
- }
- }
-
- private static void mergeInto(Map> target, String key, Set values) {
- target.computeIfAbsent(key, ignored -> new LinkedHashSet<>())
- .addAll(values);
}
}
diff --git a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneRuntimeConfig.java b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneRuntimeConfig.java
index 5243927b51241..a8beac6716e7c 100644
--- a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneRuntimeConfig.java
+++ b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/HibernateSearchStandaloneRuntimeConfig.java
@@ -1,17 +1,12 @@
package io.quarkus.hibernate.search.standalone.elasticsearch.runtime;
-import java.time.Duration;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Optional;
-import java.util.OptionalInt;
-import org.hibernate.search.backend.elasticsearch.index.IndexStatus;
-import org.hibernate.search.engine.cfg.spi.ParseUtils;
import org.hibernate.search.mapper.pojo.standalone.schema.management.SchemaManagementStrategyName;
-import org.hibernate.search.util.common.SearchException;
+import io.quarkus.hibernate.search.backend.elasticsearch.common.runtime.HibernateSearchBackendElasticsearchRuntimeConfig;
import io.quarkus.runtime.annotations.ConfigDocDefault;
import io.quarkus.runtime.annotations.ConfigDocMapKey;
import io.quarkus.runtime.annotations.ConfigDocSection;
@@ -21,7 +16,6 @@
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithName;
-import io.smallrye.config.WithParentName;
import io.smallrye.config.WithUnnamedKey;
@ConfigMapping(prefix = "quarkus.hibernate-search-standalone")
@@ -44,13 +38,13 @@ public interface HibernateSearchStandaloneRuntimeConfig {
Optional active();
/**
- * Configuration for backends.
+ * Configuration for Elasticsearch/OpenSearch backends.
*/
@ConfigDocSection
@WithName("elasticsearch")
@WithUnnamedKey // The default backend has the null key
@ConfigDocMapKey("backend-name")
- Map backends();
+ Map backends();
/**
* Configuration for automatic creation and validation of the Elasticsearch schema:
@@ -63,181 +57,6 @@ public interface HibernateSearchStandaloneRuntimeConfig {
*/
IndexingConfig indexing();
- @ConfigGroup
- interface ElasticsearchBackendRuntimeConfig {
- /**
- * The list of hosts of the Elasticsearch servers.
- */
- @WithDefault("localhost:9200")
- List hosts();
-
- /**
- * The protocol to use when contacting Elasticsearch servers.
- * Set to "https" to enable SSL/TLS.
- */
- @WithDefault("http")
- ElasticsearchClientProtocol protocol();
-
- /**
- * The username used for authentication.
- */
- Optional username();
-
- /**
- * The password used for authentication.
- */
- Optional password();
-
- /**
- * The timeout when establishing a connection to an Elasticsearch server.
- */
- @WithDefault("1S")
- Duration connectionTimeout();
-
- /**
- * The timeout when reading responses from an Elasticsearch server.
- */
- @WithDefault("30S")
- Duration readTimeout();
-
- /**
- * The timeout when executing a request to an Elasticsearch server.
- *
- * This includes the time needed to wait for a connection to be available,
- * send the request and read the response.
- *
- * @asciidoclet
- */
- Optional requestTimeout();
-
- /**
- * The maximum number of connections to all the Elasticsearch servers.
- */
- @WithDefault("20")
- int maxConnections();
-
- /**
- * The maximum number of connections per Elasticsearch server.
- */
- @WithDefault("10")
- int maxConnectionsPerRoute();
-
- /**
- * Configuration for the automatic discovery of new Elasticsearch nodes.
- */
- DiscoveryConfig discovery();
-
- /**
- * Configuration for the thread pool assigned to the backend.
- */
- ThreadPoolConfig threadPool();
-
- /**
- * Configuration for search queries to this backend.
- */
- ElasticsearchQueryConfig query();
-
- /**
- * Configuration for version checks on this backend.
- */
- ElasticsearchVersionCheckConfig versionCheck();
-
- /**
- * The default configuration for the Elasticsearch indexes.
- */
- @WithParentName
- ElasticsearchIndexRuntimeConfig indexDefaults();
-
- /**
- * Per-index configuration overrides.
- */
- @ConfigDocSection
- @ConfigDocMapKey("index-name")
- Map indexes();
-
- /**
- * Configuration for the index layout.
- */
- LayoutConfig layout();
- }
-
- enum ElasticsearchClientProtocol {
- /**
- * Use clear-text HTTP, with SSL/TLS disabled.
- */
- HTTP("http"),
- /**
- * Use HTTPS, with SSL/TLS enabled.
- */
- HTTPS("https");
-
- public static ElasticsearchClientProtocol of(String value) {
- return ParseUtils.parseDiscreteValues(
- values(),
- ElasticsearchClientProtocol::getHibernateSearchString,
- (invalidValue, validValues) -> new SearchException(
- String.format(
- Locale.ROOT,
- "Invalid protocol: '%1$s'. Valid protocols are: %2$s.",
- invalidValue,
- validValues)),
- value);
- }
-
- private final String hibernateSearchString;
-
- ElasticsearchClientProtocol(String hibernateSearchString) {
- this.hibernateSearchString = hibernateSearchString;
- }
-
- public String getHibernateSearchString() {
- return hibernateSearchString;
- }
- }
-
- @ConfigGroup
- interface ElasticsearchVersionCheckConfig {
- /**
- * Whether Hibernate Search should check the version of the Elasticsearch cluster on startup.
- *
- * Set to `false` if the Elasticsearch cluster may not be available on startup.
- *
- * @asciidoclet
- */
- @WithDefault("true")
- boolean enabled();
- }
-
- @ConfigGroup
- interface ElasticsearchIndexRuntimeConfig {
- /**
- * Configuration for the schema management of the indexes.
- */
- ElasticsearchIndexSchemaManagementConfig schemaManagement();
-
- /**
- * Configuration for the indexing process that creates, updates and deletes documents.
- */
- ElasticsearchIndexIndexingConfig indexing();
- }
-
- @ConfigGroup
- interface DiscoveryConfig {
-
- /**
- * Defines if automatic discovery is enabled.
- */
- @WithDefault("false")
- Boolean enabled();
-
- /**
- * Refresh interval of the node list.
- */
- @WithDefault("10S")
- Duration refreshInterval();
-
- }
-
@ConfigGroup
interface IndexingConfig {
@@ -408,167 +227,6 @@ interface SchemaManagementConfig {
}
- @ConfigGroup
- interface ThreadPoolConfig {
- /**
- * The size of the thread pool assigned to the backend.
- *
- * Note that number is **per backend**, not per index.
- * Adding more indexes will not add more threads.
- *
- * As all operations happening in this thread-pool are non-blocking,
- * raising its size above the number of processor cores available to the JVM will not bring noticeable performance
- * benefit.
- * The only reason to alter this setting would be to reduce the number of threads;
- * for example, in an application with a single index with a single indexing queue,
- * running on a machine with 64 processor cores,
- * you might want to bring down the number of threads.
- *
- * Defaults to the number of processor cores available to the JVM on startup.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- OptionalInt size();
- }
-
- @ConfigGroup
- interface ElasticsearchQueryConfig {
- /**
- * Configuration for the behavior on shard failure.
- */
- ElasticsearchQueryShardFailureConfig shardFailure();
- }
-
- @ConfigGroup
- interface ElasticsearchQueryShardFailureConfig {
- /**
- * Whether partial shard failures are ignored (`true`)
- * or lead to Hibernate Search throwing an exception (`false`).
- */
- @WithDefault("false")
- boolean ignore();
- }
-
- // We can't set actual default values in this section,
- // otherwise "quarkus.hibernate-search-standalone.elasticsearch.index-defaults" will be ignored.
- @ConfigGroup
- interface ElasticsearchIndexSchemaManagementConfig {
- /**
- * The minimal https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster-health.html[Elasticsearch cluster
- * status] required on startup.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("yellow")
- Optional requiredStatus();
-
- /**
- * How long we should wait for the status before failing the bootstrap.
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("10S")
- Optional requiredStatusWaitTimeout();
- }
-
- // We can't set actual default values in this section,
- // otherwise "quarkus.hibernate-search-standalone.elasticsearch.index-defaults" will be ignored.
- @ConfigGroup
- interface ElasticsearchIndexIndexingConfig {
- /**
- * The number of indexing queues assigned to each index.
- *
- * Higher values will lead to more connections being used in parallel,
- * which may lead to higher indexing throughput,
- * but incurs a risk of overloading Elasticsearch,
- * i.e. of overflowing its HTTP request buffers and tripping
- * https://www.elastic.co/guide/en/elasticsearch/reference/7.9/circuit-breaker.html[circuit breakers],
- * leading to Elasticsearch giving up on some request and resulting in indexing failures.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("10")
- OptionalInt queueCount();
-
- /**
- * The size of indexing queues.
- *
- * Lower values may lead to lower memory usage, especially if there are many queues,
- * but values that are too low will reduce the likeliness of reaching the max bulk size
- * and increase the likeliness of application threads blocking because the queue is full,
- * which may lead to lower indexing throughput.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("1000")
- OptionalInt queueSize();
-
- /**
- * The maximum size of bulk requests created when processing indexing queues.
- *
- * Higher values will lead to more documents being sent in each HTTP request sent to Elasticsearch,
- * which may lead to higher indexing throughput,
- * but incurs a risk of overloading Elasticsearch,
- * i.e. of overflowing its HTTP request buffers and tripping
- * https://www.elastic.co/guide/en/elasticsearch/reference/7.9/circuit-breaker.html[circuit breakers],
- * leading to Elasticsearch giving up on some request and resulting in indexing failures.
- *
- * Note that raising this number above the queue size has no effect,
- * as bulks cannot include more requests than are contained in the queue.
- *
- * @asciidoclet
- */
- // We can't set an actual default value here: see comment on this class.
- @ConfigDocDefault("100")
- OptionalInt maxBulkSize();
- }
-
- @ConfigGroup
- interface LayoutConfig {
- /**
- * A xref:hibernate-search-standalone-elasticsearch.adoc#bean-reference-note-anchor[bean reference] to the component
- * used to configure the Elasticsearch layout: index names, index aliases, ...
- *
- * The referenced bean must implement `IndexLayoutStrategy`.
- *
- * Available built-in implementations:
- *
- * `simple`::
- * The default, future-proof strategy: if the index name in Hibernate Search is `myIndex`,
- * this strategy will create an index named `myindex-000001`, an alias for write operations named `myindex-write`,
- * and an alias for read operations named `myindex-read`.
- * `no-alias`::
- * A strategy without index aliases, mostly useful on legacy clusters:
- * if the index name in Hibernate Search is `myIndex`,
- * this strategy will create an index named `myindex`, and will not use any alias.
- *
- * See
- * link:{hibernate-search-docs-url}#backend-elasticsearch-indexlayout[this section of the reference documentation]
- * for more information.
- *
- * [NOTE]
- * ====
- * Instead of setting this configuration property,
- * you can simply annotate your custom `IndexLayoutStrategy` implementation with `@SearchExtension`
- * and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically.
- * See xref:hibernate-search-standalone-elasticsearch.adoc#plugging-in-custom-components[this section]
- * for more information.
- *
- * If this configuration property is set, it takes precedence over any `@SearchExtension` annotation.
- * ====
- *
- * @asciidoclet
- */
- Optional strategy();
- }
-
- static String elasticsearchVersionPropertyKey(String backendName) {
- return backendPropertyKey(backendName, null, "version");
- }
-
static String extensionPropertyKey(String radical) {
StringBuilder keyBuilder = new StringBuilder("quarkus.hibernate-search-standalone.");
keyBuilder.append(radical);
diff --git a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/resources/META-INF/quarkus-extension.yaml
index 538b2011cea0f..274ea3ff9ee74 100644
--- a/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/resources/META-INF/quarkus-extension.yaml
+++ b/extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -9,6 +9,7 @@ metadata:
- "full-text"
- "hibernate"
- "elasticsearch"
+ - "opensearch"
guide: "https://quarkus.io/guides/hibernate-search-standalone-elasticsearch"
categories:
- "data"
diff --git a/extensions/pom.xml b/extensions/pom.xml
index 4e511fcc40963..7f86c1174b30f 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -99,6 +99,7 @@
hibernate-reactive
hibernate-validator
panache
+ hibernate-search-backend-elasticsearch-common
hibernate-search-orm-elasticsearch
hibernate-search-orm-outbox-polling
hibernate-search-standalone-elasticsearch