diff --git a/pom.xml b/pom.xml
index a6dc167a03..b6cf6dcb33 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
+ * {@link #GENERATED_REPOSITORIES_ENABLED} acts as a kill switch, if disabled, store specific flags have no effect. + *
+ * Missing properties are interpreted as {@literal true}. + * + * @param moduleName The name of the module. Can be {@literal null} or {@literal empty}, in which case it will only + * check the general {@link #GENERATED_REPOSITORIES_ENABLED} flag. + * @return indicator if repository code generation is enabled. + * @since 5.0 + */ + default boolean isGeneratedRepositoriesEnabled(@Nullable String moduleName) { + + Environment environment = getEnvironment(); + Boolean codeGenerationEnabled = environment.getProperty(GENERATED_REPOSITORIES_ENABLED, Boolean.class, true); + if (!codeGenerationEnabled) { + return false; + } + + if (!StringUtils.hasText(moduleName)) { + return true; + } + + String modulePropertyName = GENERATED_REPOSITORIES_ENABLED.replace("enabled", + "%s.enabled".formatted(moduleName.toLowerCase(Locale.US))); + return environment.getProperty(modulePropertyName, Boolean.class, true); + } + /** * Returns a reference to the {@link ConfigurableListableBeanFactory} backing this {@link AotContext}. * diff --git a/src/test/java/org/springframework/data/aot/AotContextUnitTests.java b/src/test/java/org/springframework/data/aot/AotContextUnitTests.java new file mode 100644 index 0000000000..ce22035bd3 --- /dev/null +++ b/src/test/java/org/springframework/data/aot/AotContextUnitTests.java @@ -0,0 +1,91 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.aot; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.Mockito; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.core.env.Environment; +import org.springframework.mock.env.MockEnvironment; +import org.springframework.util.StringUtils; + +/** + * Tests for {@link AotContext}. + * + * @author Christoph Strobl + */ +class AotContextUnitTests { + + @ParameterizedTest // GH-3322 + @CsvSource({ // + "'spring.aot.repositories.enabled', '', '', '', true", // + "'spring.aot.repositories.enabled', 'true', '', '', true", // + "'spring.aot.repositories.enabled', 'false', '', '', false", // + "'spring.aot.repositories.enabled', '', 'commons', 'true', true", // + "'spring.aot.repositories.enabled', 'true', 'commons', 'true', true", // + "'spring.aot.repositories.enabled', '', 'commons', 'false', false", // + "'spring.aot.repositories.enabled', 'false', 'commons', 'true', false" // + }) + void considersEnvironmentSettingsForGeneratedRepositories(String generalFlag, String generalValue, String storeName, + String storeValue, boolean enabled) { + + MockAotContext ctx = new MockAotContext(); + if (StringUtils.hasText(generalFlag) && StringUtils.hasText(generalValue)) { + ctx.withProperty(generalFlag, generalValue); + } + if (StringUtils.hasText(storeName) && StringUtils.hasText(storeValue)) { + ctx.withProperty("spring.aot.repositories.%s.enabled".formatted(storeName), storeValue); + } + + Assertions.assertThat(ctx.isGeneratedRepositoriesEnabled(storeName)).isEqualTo(enabled); + } + + class MockAotContext implements AotContext { + + private final MockEnvironment environment; + + public MockAotContext() { + this.environment = new MockEnvironment(); + } + + MockAotContext withProperty(String key, String value) { + environment.setProperty(key, value); + return this; + } + + @Override + public ConfigurableListableBeanFactory getBeanFactory() { + return Mockito.mock(ConfigurableListableBeanFactory.class); + } + + @Override + public TypeIntrospector introspectType(String typeName) { + return Mockito.mock(TypeIntrospector.class); + } + + @Override + public IntrospectedBeanDefinition introspectBeanDefinition(String beanName) { + return Mockito.mock(IntrospectedBeanDefinition.class); + } + + @Override + public Environment getEnvironment() { + return environment; + } + } +}