diff --git a/extensions/hibernate-search-orm-coordination-outbox-polling/deployment/src/main/java/io/quarkus/hibernate/search/orm/coordination/outboxpolling/deployment/HibernateSearchOutboxPollingProcessor.java b/extensions/hibernate-search-orm-coordination-outbox-polling/deployment/src/main/java/io/quarkus/hibernate/search/orm/coordination/outboxpolling/deployment/HibernateSearchOutboxPollingProcessor.java index a7bd284e1f49a..decf580687c5a 100644 --- a/extensions/hibernate-search-orm-coordination-outbox-polling/deployment/src/main/java/io/quarkus/hibernate/search/orm/coordination/outboxpolling/deployment/HibernateSearchOutboxPollingProcessor.java +++ b/extensions/hibernate-search-orm-coordination-outbox-polling/deployment/src/main/java/io/quarkus/hibernate/search/orm/coordination/outboxpolling/deployment/HibernateSearchOutboxPollingProcessor.java @@ -16,6 +16,7 @@ import io.quarkus.hibernate.search.orm.coordination.outboxpolling.runtime.HibernateSearchOutboxPollingRecorder; import io.quarkus.hibernate.search.orm.coordination.outboxpolling.runtime.HibernateSearchOutboxPollingRuntimeConfig; import io.quarkus.hibernate.search.orm.elasticsearch.deployment.HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem; +import io.quarkus.hibernate.search.orm.elasticsearch.deployment.HibernateSearchEnabled; import io.quarkus.hibernate.search.orm.elasticsearch.deployment.HibernateSearchIntegrationRuntimeConfiguredBuildItem; import io.quarkus.hibernate.search.orm.elasticsearch.deployment.HibernateSearchIntegrationStaticConfiguredBuildItem; import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchBuildTimeConfigPersistenceUnit; @@ -24,11 +25,7 @@ class HibernateSearchOutboxPollingProcessor { private static final String HIBERNATE_SEARCH_ORM_COORDINATION_OUTBOX_POLLING = "Hibernate Search ORM - Coordination - Outbox polling"; - @BuildStep - void registerIndexedClasses() { - } - - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) void registerInternalModel(BuildProducer additionalIndexedClasses, BuildProducer reflectiveClasses, BuildProducer additionalJpaModel) { @@ -41,7 +38,7 @@ void registerInternalModel(BuildProducer addi } } - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) @Record(ExecutionTime.STATIC_INIT) void setStaticConfig(HibernateSearchOutboxPollingRecorder recorder, List configuredPersistenceUnits, @@ -59,7 +56,7 @@ void setStaticConfig(HibernateSearchOutboxPollingRecorder recorder, } } - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) @Record(ExecutionTime.RUNTIME_INIT) void setRuntimeConfig(HibernateSearchOutboxPollingRecorder recorder, HibernateSearchOutboxPollingRuntimeConfig runtimeConfig, diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchCdiProcessor.java b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchCdiProcessor.java index 5e952a91301f6..ae798228c096e 100644 --- a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchCdiProcessor.java +++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchElasticsearchCdiProcessor.java @@ -25,7 +25,7 @@ public class HibernateSearchElasticsearchCdiProcessor { @Record(ExecutionTime.RUNTIME_INIT) - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) void generateSearchBeans(HibernateSearchElasticsearchRecorder recorder, HibernateSearchElasticsearchRuntimeConfig runtimeConfig, List configuredPersistenceUnits, @@ -67,7 +67,7 @@ private static SyntheticBeanBuildItem createSyntheticBean(String persistence return configurator.done(); } - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) void registerAnnotations(BuildProducer additionalBeans, BuildProducer beanDefiningAnnotations) { // add the @SearchExtension class 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 d6a830014ca79..427c3c663bc2c 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 @@ -74,11 +74,13 @@ class HibernateSearchElasticsearchProcessor { HibernateSearchElasticsearchBuildTimeConfig buildTimeConfig; + // Note this is necessary even if Hibernate Search is disabled @BuildStep(onlyIf = NativeOrNativeSourcesBuild.class) NativeImageFeatureBuildItem nativeImageFeature() { return new NativeImageFeatureBuildItem(DisableLoggingFeature.class); } + // Note this is necessary even if Hibernate Search is disabled @BuildStep void setupLogFilters(BuildProducer filters) { // if the category changes, please also update DisableLoggingFeature in the runtime module @@ -86,7 +88,33 @@ void setupLogFilters(BuildProducer filters) { "org.hibernate.search.mapper.orm.bootstrap.impl.HibernateSearchPreIntegrationService", "HSEARCH000034")); } - @BuildStep + @BuildStep(onlyIfNot = HibernateSearchEnabled.class) + @Record(ExecutionTime.STATIC_INIT) + public void disableHibernateSearchStaticInit(HibernateSearchElasticsearchRecorder recorder, + List persistenceUnitDescriptorBuildItems, + BuildProducer staticIntegrations) { + for (PersistenceUnitDescriptorBuildItem puDescriptor : persistenceUnitDescriptorBuildItems) { + String puName = puDescriptor.getPersistenceUnitName(); + staticIntegrations.produce(new HibernateOrmIntegrationStaticConfiguredBuildItem(HIBERNATE_SEARCH_ELASTICSEARCH, + puName).setInitListener(recorder.createStaticInitInactiveListener())); + } + } + + @BuildStep(onlyIfNot = HibernateSearchEnabled.class) + @Record(ExecutionTime.RUNTIME_INIT) + public void disableHibernateSearchRuntimeInit(HibernateSearchElasticsearchRecorder recorder, + HibernateSearchElasticsearchRuntimeConfig runtimeConfig, + List persistenceUnitDescriptorBuildItems, + BuildProducer runtimeIntegrations) { + recorder.checkNoExplicitActiveTrue(runtimeConfig); + for (PersistenceUnitDescriptorBuildItem puDescriptor : persistenceUnitDescriptorBuildItems) { + String puName = puDescriptor.getPersistenceUnitName(); + runtimeIntegrations.produce(new HibernateOrmIntegrationRuntimeConfiguredBuildItem(HIBERNATE_SEARCH_ELASTICSEARCH, + puName).setInitListener(recorder.createRuntimeInitInactiveListener())); + } + } + + @BuildStep(onlyIf = HibernateSearchEnabled.class) @Record(ExecutionTime.STATIC_INIT) public void build(HibernateSearchElasticsearchRecorder recorder, CombinedIndexBuildItem combinedIndexBuildItem, @@ -156,11 +184,12 @@ private void buildForPersistenceUnit(HibernateSearchElasticsearchRecorder record if (indexedAnnotationsForPU.isEmpty()) { // we don't have any indexed entity, we can disable Hibernate Search staticIntegrations.produce(new HibernateOrmIntegrationStaticConfiguredBuildItem(HIBERNATE_SEARCH_ELASTICSEARCH, - persistenceUnitName).setInitListener(recorder.createDisabledStaticInitListener())); + persistenceUnitName).setInitListener(recorder.createStaticInitInactiveListener())); // we need a runtime listener even when Hibernate Search is disabled, // just to let Hibernate Search boot up until the point where it checks whether it's enabled or not runtimeIntegrations.produce(new HibernateOrmIntegrationRuntimeConfiguredBuildItem(HIBERNATE_SEARCH_ELASTICSEARCH, - persistenceUnitName).setInitListener(recorder.createDisabledRuntimeInitListener())); + persistenceUnitName) + .setInitListener(recorder.createRuntimeInitInactiveListener())); return; } @@ -176,7 +205,7 @@ private void buildForPersistenceUnit(HibernateSearchElasticsearchRecorder record backendNamesForIndexedEntities, backendAndIndexNamesForSearchExtensions)); } - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) void registerBeans(List searchEnabledPUs, BuildProducer unremovableBean) { if (searchEnabledPUs.isEmpty()) { @@ -189,7 +218,7 @@ void registerBeans(List integrationStaticConfigBuildItems, @@ -224,7 +253,7 @@ void setStaticConfig(RecorderContext recorderContext, HibernateSearchElasticsear } } - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) @Record(ExecutionTime.RUNTIME_INIT) void setRuntimeConfig(HibernateSearchElasticsearchRecorder recorder, HibernateSearchElasticsearchRuntimeConfig runtimeConfig, @@ -251,7 +280,7 @@ void setRuntimeConfig(HibernateSearchElasticsearchRecorder recorder, } } - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) public void processPersistenceUnitBuildTimeConfig( List configuredPersistenceUnits, ApplicationArchivesBuildItem applicationArchivesBuildItem, @@ -358,7 +387,7 @@ private void registerReflectionForGson(BuildProducer r reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, reflectiveClasses)); } - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) DevservicesElasticsearchBuildItem devServices(HibernateSearchElasticsearchBuildTimeConfig buildTimeConfig) { if (buildTimeConfig.defaultPersistenceUnit != null && buildTimeConfig.defaultPersistenceUnit.defaultBackend != null // If the version is not set, the default backend is not in use. @@ -376,7 +405,7 @@ DevservicesElasticsearchBuildItem devServices(HibernateSearchElasticsearchBuildT } } - @BuildStep(onlyIfNot = IsNormal.class) + @BuildStep(onlyIf = HibernateSearchEnabled.class, onlyIfNot = IsNormal.class) void devServicesDropAndCreateAndDropByDefault( List configuredPersistenceUnits, BuildProducer devServicesAdditionalConfigProducer) { diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchEnabled.java b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchEnabled.java new file mode 100644 index 0000000000000..a979855b48bc4 --- /dev/null +++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/HibernateSearchEnabled.java @@ -0,0 +1,24 @@ +package io.quarkus.hibernate.search.orm.elasticsearch.deployment; + +import java.util.function.BooleanSupplier; + +import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchBuildTimeConfig; + +/** + * Supplier that can be used to only run build steps + * if the Hibernate Search extension is enabled. + */ +public class HibernateSearchEnabled implements BooleanSupplier { + + private final HibernateSearchElasticsearchBuildTimeConfig config; + + HibernateSearchEnabled(HibernateSearchElasticsearchBuildTimeConfig config) { + this.config = config; + } + + @Override + public boolean getAsBoolean() { + return config.enabled; + } + +} diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/devconsole/HibernateSearchElasticsearchDevConsoleProcessor.java b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/devconsole/HibernateSearchElasticsearchDevConsoleProcessor.java index 5540c3fb62e6d..fd6292d15b67f 100644 --- a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/devconsole/HibernateSearchElasticsearchDevConsoleProcessor.java +++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/deployment/devconsole/HibernateSearchElasticsearchDevConsoleProcessor.java @@ -14,12 +14,13 @@ import io.quarkus.devconsole.spi.DevConsoleRouteBuildItem; import io.quarkus.devconsole.spi.DevConsoleRuntimeTemplateInfoBuildItem; import io.quarkus.hibernate.search.orm.elasticsearch.deployment.HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem; +import io.quarkus.hibernate.search.orm.elasticsearch.deployment.HibernateSearchEnabled; import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfig; import io.quarkus.hibernate.search.orm.elasticsearch.runtime.devconsole.HibernateSearchDevConsoleRecorder; public class HibernateSearchElasticsearchDevConsoleProcessor { - @BuildStep(onlyIf = IsDevelopment.class) + @BuildStep(onlyIf = { HibernateSearchEnabled.class, IsDevelopment.class }) @Record(RUNTIME_INIT) public DevConsoleRuntimeTemplateInfoBuildItem collectBeanInfo(HibernateSearchDevConsoleRecorder recorder, HibernateSearchElasticsearchRuntimeConfig runtimeConfig, @@ -32,7 +33,7 @@ public DevConsoleRuntimeTemplateInfoBuildItem collectBeanInfo(HibernateSearchDev recorder.infoSupplier(runtimeConfig, persistenceUnitNames), this.getClass(), curateOutcomeBuildItem); } - @BuildStep + @BuildStep(onlyIf = HibernateSearchEnabled.class) @Record(value = STATIC_INIT, optional = true) DevConsoleRouteBuildItem invokeEndpoint(HibernateSearchDevConsoleRecorder recorder) { return new DevConsoleRouteBuildItem("entity-types", "POST", recorder.indexEntity()); diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigDisabledAndIndexedEntityTest.java b/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigActiveFalseAndIndexedEntityTest.java similarity index 87% rename from extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigDisabledAndIndexedEntityTest.java rename to extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigActiveFalseAndIndexedEntityTest.java index 40afd526411e1..d0dcf47c2ca0a 100644 --- a/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigDisabledAndIndexedEntityTest.java +++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigActiveFalseAndIndexedEntityTest.java @@ -18,23 +18,23 @@ import io.quarkus.arc.Arc; import io.quarkus.test.QuarkusUnitTest; -public class ConfigDisabledAndIndexedEntityTest { +public class ConfigActiveFalseAndIndexedEntityTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( () -> ShrinkWrap.create(JavaArchive.class).addClass(IndexedEntity.class)) .withConfigurationResource("application.properties") - .overrideConfigKey("quarkus.hibernate-search-orm.enabled", "false"); + .overrideConfigKey("quarkus.hibernate-search-orm.active", "false"); @Inject SessionFactory sessionFactory; @Test - public void testDisabled() { + public void test() { assertThatThrownBy(() -> Arc.container().instance(SearchMapping.class).get()) .isInstanceOf(IllegalStateException.class) .hasMessageContaining( - "Cannot retrieve the SearchMapping: Hibernate Search was disabled through configuration properties"); + "Cannot retrieve the SearchMapping: Hibernate Search was deactivated through configuration properties"); assertThatThrownBy(() -> Search.mapping(sessionFactory)) .isInstanceOf(SearchException.class) @@ -43,7 +43,7 @@ public void testDisabled() { assertThatThrownBy(() -> Arc.container().instance(SearchSession.class).get()) .isInstanceOf(IllegalStateException.class) .hasMessageContaining( - "Cannot retrieve the SearchSession: Hibernate Search was disabled through configuration properties"); + "Cannot retrieve the SearchSession: Hibernate Search was deactivated through configuration properties"); try (Session session = sessionFactory.openSession()) { assertThatThrownBy(() -> Search.session(session).search(IndexedEntity.class)) diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigEnabledFalseAndActiveTrueTest.java b/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigEnabledFalseAndActiveTrueTest.java new file mode 100644 index 0000000000000..f17059b54ddf2 --- /dev/null +++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigEnabledFalseAndActiveTrueTest.java @@ -0,0 +1,63 @@ +package io.quarkus.hibernate.search.orm.elasticsearch.test.configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import javax.inject.Inject; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.search.mapper.orm.Search; +import org.hibernate.search.mapper.orm.mapping.SearchMapping; +import org.hibernate.search.mapper.orm.session.SearchSession; +import org.hibernate.search.util.common.SearchException; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; + +public class ConfigEnabledFalseAndActiveTrueTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class).addClass(IndexedEntity.class)) + .withConfigurationResource("application.properties") + .overrideConfigKey("quarkus.hibernate-search-orm.enabled", "false") + .overrideConfigKey("quarkus.hibernate-search-orm.active", "true") + .assertException(throwable -> assertThat(throwable) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining( + "Hibernate Search activated explicitly, but Hibernate Search was disabled at build time", + "If you want Hibernate Search to be active at runtime, you must set 'quarkus.hibernate-search-orm.enabled' to 'true' at build time", + "If you don't want Hibernate Search to be active at runtime, you must leave 'quarkus.hibernate-search-orm.active' unset or set it to 'false'")); + + @Inject + SessionFactory sessionFactory; + + @Test + public void test() { + assertThatThrownBy(() -> Arc.container().instance(SearchMapping.class).get()) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining( + "Cannot retrieve the SearchMapping: Hibernate Search was disabled through configuration properties"); + + assertThatThrownBy(() -> Search.mapping(sessionFactory)) + .isInstanceOf(SearchException.class) + .hasMessageContaining("Hibernate Search was not initialized."); + + assertThatThrownBy(() -> Arc.container().instance(SearchSession.class).get()) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining( + "Cannot retrieve the SearchSession: Hibernate Search was disabled through configuration properties"); + + try (Session session = sessionFactory.openSession()) { + assertThatThrownBy(() -> Search.session(session).search(IndexedEntity.class)) + .isInstanceOf(SearchException.class) + .hasMessageContaining("Hibernate Search was not initialized."); + } + } +} diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigEnabledFalseAndIndexedEntityTest.java b/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigEnabledFalseAndIndexedEntityTest.java new file mode 100644 index 0000000000000..805558a09f4a8 --- /dev/null +++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/test/java/io/quarkus/hibernate/search/orm/elasticsearch/test/configuration/ConfigEnabledFalseAndIndexedEntityTest.java @@ -0,0 +1,51 @@ +package io.quarkus.hibernate.search.orm.elasticsearch.test.configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import javax.inject.Inject; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.search.mapper.orm.Search; +import org.hibernate.search.mapper.orm.mapping.SearchMapping; +import org.hibernate.search.mapper.orm.session.SearchSession; +import org.hibernate.search.util.common.SearchException; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.test.QuarkusUnitTest; + +public class ConfigEnabledFalseAndIndexedEntityTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class).addClass(IndexedEntity.class)) + .withConfigurationResource("application.properties") + .overrideConfigKey("quarkus.hibernate-search-orm.enabled", "false"); + + @Inject + SessionFactory sessionFactory; + + @Test + public void test() { + assertThat(Arc.container().instance(SearchMapping.class).get()) + .isNull(); + + assertThatThrownBy(() -> Search.mapping(sessionFactory)) + .isInstanceOf(SearchException.class) + .hasMessageContaining("Hibernate Search was not initialized."); + + assertThat(Arc.container().instance(SearchSession.class).get()) + .isNull(); + + try (Session session = sessionFactory.openSession()) { + assertThatThrownBy(() -> Search.session(session).search(IndexedEntity.class)) + .isInstanceOf(SearchException.class) + .hasMessageContaining("Hibernate Search was not initialized."); + } + } +} diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchBuildTimeConfig.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchBuildTimeConfig.java index 621d075ff2b4a..23b6aa84255bb 100644 --- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchBuildTimeConfig.java +++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchBuildTimeConfig.java @@ -13,6 +13,18 @@ @ConfigRoot(name = "hibernate-search-orm", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) public class HibernateSearchElasticsearchBuildTimeConfig { + /** + * Whether Hibernate Search is enabled during the build. + * + * If Hibernate Search is disabled during the build, all processing related to Hibernate Search will be skipped, + * but it will not be possible to activate Hibernate Search at runtime: + * `quarkus.hibernate-search-orm.active` will default to `false` and setting it to `true` will lead to an error. + * + * @asciidoclet + */ + @ConfigItem(defaultValue = "true") + public boolean enabled; + /** * Configuration for the default persistence unit. */ 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 bf7af08b6e495..33b31e0812a42 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 @@ -48,6 +48,7 @@ import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfigPersistenceUnit.ElasticsearchIndexRuntimeConfig; import io.quarkus.hibernate.search.orm.elasticsearch.runtime.bean.HibernateSearchBeanUtil; import io.quarkus.runtime.annotations.Recorder; +import io.quarkus.runtime.configuration.ConfigurationException; @Recorder public class HibernateSearchElasticsearchRecorder { @@ -60,8 +61,8 @@ public HibernateOrmIntegrationStaticInitListener createStaticInitListener( backendAndIndexNamesForSearchExtensions, integrationStaticInitListeners); } - public HibernateOrmIntegrationStaticInitListener createDisabledStaticInitListener() { - return new HibernateSearchIntegrationDisabledListener(); + public HibernateOrmIntegrationStaticInitListener createStaticInitInactiveListener() { + return new HibernateSearchIntegrationStaticInitInactiveListener(); } public HibernateOrmIntegrationRuntimeInitListener createRuntimeInitListener( @@ -74,8 +75,27 @@ public HibernateOrmIntegrationRuntimeInitListener createRuntimeInitListener( backendAndIndexNamesForSearchExtensions, integrationRuntimeInitListeners); } - public HibernateOrmIntegrationRuntimeInitListener createDisabledRuntimeInitListener() { - return new HibernateSearchIntegrationRuntimeInitDisabledListener(); + public void checkNoExplicitActiveTrue(HibernateSearchElasticsearchRuntimeConfig runtimeConfig) { + for (var entry : runtimeConfig.getAllPersistenceUnitConfigsAsMap().entrySet()) { + var config = entry.getValue(); + if (config.active.orElse(false)) { + var puName = entry.getKey(); + String enabledPropertyKey = HibernateSearchElasticsearchRuntimeConfig.extensionPropertyKey("enabled"); + String activePropertyKey = HibernateSearchElasticsearchRuntimeConfig.mapperPropertyKey(puName, "active"); + throw new ConfigurationException( + "Hibernate Search activated explicitly, but Hibernate Search was disabled at build time." + + " If you want Hibernate Search to be active at runtime, you must set '" + enabledPropertyKey + + "' to 'true' at build time." + + " If you don't want Hibernate Search to be active at runtime, you must leave '" + + activePropertyKey + + "' unset or set it to 'false'.", + Set.of(enabledPropertyKey, activePropertyKey)); + } + } + } + + public HibernateOrmIntegrationRuntimeInitListener createRuntimeInitInactiveListener() { + return new HibernateSearchIntegrationRuntimeInitInactiveListener(); } public Supplier searchMappingSupplier(HibernateSearchElasticsearchRuntimeConfig runtimeConfig, @@ -83,11 +103,11 @@ public Supplier searchMappingSupplier(HibernateSearchElasticsearc return new Supplier() { @Override public SearchMapping get() { - HibernateSearchElasticsearchRuntimeConfigPersistenceUnit config = runtimeConfig + HibernateSearchElasticsearchRuntimeConfigPersistenceUnit puRuntimeConfig = runtimeConfig .getAllPersistenceUnitConfigsAsMap().get(persistenceUnitName); - if (config != null && !config.enabled) { + if (puRuntimeConfig != null && !puRuntimeConfig.active.orElse(true)) { throw new IllegalStateException( - "Cannot retrieve the SearchMapping: Hibernate Search was disabled through configuration properties"); + "Cannot retrieve the SearchMapping: Hibernate Search was deactivated through configuration properties"); } SessionFactory sessionFactory; if (isDefaultPersistenceUnit) { @@ -106,11 +126,11 @@ public Supplier searchSessionSupplier(HibernateSearchElasticsearc return new Supplier() { @Override public SearchSession get() { - HibernateSearchElasticsearchRuntimeConfigPersistenceUnit config = runtimeConfig + HibernateSearchElasticsearchRuntimeConfigPersistenceUnit puRuntimeConfig = runtimeConfig .getAllPersistenceUnitConfigsAsMap().get(persistenceUnitName); - if (config != null && !config.enabled) { + if (puRuntimeConfig != null && !puRuntimeConfig.active.orElse(true)) { throw new IllegalStateException( - "Cannot retrieve the SearchSession: Hibernate Search was disabled through configuration properties"); + "Cannot retrieve the SearchSession: Hibernate Search was deactivated through configuration properties"); } Session session; if (isDefaultPersistenceUnit) { @@ -124,9 +144,9 @@ public SearchSession get() { }; } - private static final class HibernateSearchIntegrationDisabledListener + private static final class HibernateSearchIntegrationStaticInitInactiveListener implements HibernateOrmIntegrationStaticInitListener { - private HibernateSearchIntegrationDisabledListener() { + private HibernateSearchIntegrationStaticInitInactiveListener() { } @Override @@ -260,10 +280,10 @@ private void contributeBackendIndexBuildTimeProperties(BiConsumer propertyColle @Override public List> contributeServiceInitiators() { return List.of( - // The service must be initiated even if Hibernate Search is disabled, - // because it's also responsible for determining that Hibernate Search is disabled. + // The service must be initiated even if Hibernate Search is not supposed to start, + // because it's also responsible for determining that Hibernate Search should not start. new HibernateSearchPreIntegrationService.Initiator()); } } @@ -303,7 +323,7 @@ private HibernateSearchIntegrationRuntimeInitListener(String persistenceUnitName @Override public void contributeRuntimeProperties(BiConsumer propertyCollector) { if (runtimeConfig != null) { - if (!runtimeConfig.enabled) { + if (!runtimeConfig.active.orElse(true)) { addConfig(propertyCollector, HibernateOrmMapperSettings.ENABLED, false); // Do not process other properties: Hibernate Search is disabled anyway. return; @@ -436,8 +456,8 @@ public List> contributeServiceInitiators() { return List.of( // One of the purposes of this service is to provide configuration to Hibernate Search, // so it absolutely must be updated with the runtime configuration. - // The service must be initiated even if Hibernate Search is disabled, - // because it's also responsible for determining that Hibernate Search is disabled. + // The service must be initiated even if Hibernate Search is not supposed to start, + // because it's also responsible for determining that Hibernate Search should not start. new HibernateSearchPreIntegrationService.Initiator()); } } diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRuntimeConfig.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRuntimeConfig.java index 83f3a9f5c8988..361c6eb7092f5 100644 --- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRuntimeConfig.java +++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/HibernateSearchElasticsearchRuntimeConfig.java @@ -41,6 +41,12 @@ public static String elasticsearchVersionPropertyKey(String persistenceUnitName, return backendPropertyKey(persistenceUnitName, backendName, null, "version"); } + public static String extensionPropertyKey(String radical) { + StringBuilder keyBuilder = new StringBuilder("quarkus.hibernate-search-orm."); + keyBuilder.append(radical); + return keyBuilder.toString(); + } + public static String mapperPropertyKey(String persistenceUnitName, String radical) { StringBuilder keyBuilder = new StringBuilder("quarkus.hibernate-search-orm."); if (!PersistenceUnitUtil.isDefaultPersistenceUnit(persistenceUnitName)) { 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 b6533ed8457a1..2c0679be92d17 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 @@ -23,10 +23,18 @@ public class HibernateSearchElasticsearchRuntimeConfigPersistenceUnit { /** - * Whether Hibernate Search is enabled. + * Whether Hibernate Search should be active at runtime. + * + * If Hibernate Search is not active, it won't index Hibernate ORM entities, + * and accessing the SearchMapping/SearchSession for search or other operation will not be possible. + * + * Note that if Hibernate Search is disabled (i.e. `quarkus.hibernate-search-orm.enabled` is set to `false`), + * it won't be active, and setting this property to `true` will fail. + * + * @asciidoclet */ - @ConfigItem(defaultValue = "true") - public boolean enabled; + @ConfigItem(defaultValueDocumentation = "`true` if Hibernate Search is enabled; `false` otherwise") + public Optional active; /** * Default backend diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchSupplier.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchSupplier.java index 5aa7c72028e7b..28b6ab144126b 100644 --- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchSupplier.java +++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchSupplier.java @@ -34,7 +34,7 @@ public class HibernateSearchSupplier implements Supplier mappings = searchMapping(persistenceUnitNames); @@ -52,8 +52,8 @@ public IndexedPersistenceUnits get() { })); } - private boolean isEnabled() { - return runtimeConfig.defaultPersistenceUnit.enabled; + private boolean isActive() { + return runtimeConfig.defaultPersistenceUnit.active.orElse(true); } public static Map searchMapping(Set persistenceUnitNames) { diff --git a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateSearchDisabledTest.java b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateSearchActiveFalseTest.java similarity index 86% rename from integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateSearchDisabledTest.java rename to integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateSearchActiveFalseTest.java index 9ba09f23e284b..7c96f92a20c0f 100644 --- a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateSearchDisabledTest.java +++ b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateSearchActiveFalseTest.java @@ -12,15 +12,15 @@ * Note that this test cannot be placed under the relevant {@code -deployment} module because then the DEV UI processor would * not be able to locate the template resources correctly. */ -public class DevConsoleHibernateSearchDisabledTest { +public class DevConsoleHibernateSearchActiveFalseTest { @RegisterExtension static final QuarkusDevModeTest test = new QuarkusDevModeTest() .withApplicationRoot((jar) -> jar.addAsResource( new StringAsset("quarkus.datasource.db-kind=h2\n" + "quarkus.datasource.jdbc.url=jdbc:h2:mem:test\n" - // Hibernate Search is disabled: the dev console should be empty. - + "quarkus.hibernate-search-orm.enabled=false\n" + // Hibernate Search is inactive: the dev console should be empty. + + "quarkus.hibernate-search-orm.active=false\n" + "quarkus.hibernate-search-orm.elasticsearch.version=7.10\n"), "application.properties") .addClasses(MyIndexedEntity.class));