diff --git a/pom.xml b/pom.xml
index b82816e812..6207852557 100755
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,7 @@
2.3.232
3.2.0
5.2
+ 2.3.0
9.2.0
42.7.5
23.8.0.25.04
@@ -183,6 +184,12 @@
pom
import
+
+ org.junit-pioneer
+ junit-pioneer
+ ${junit-pioneer}
+ test
+
diff --git a/spring-data-jpa/pom.xml b/spring-data-jpa/pom.xml
index cdb738558f..c53600dde8 100644
--- a/spring-data-jpa/pom.xml
+++ b/spring-data-jpa/pom.xml
@@ -100,6 +100,12 @@
test
+
+ org.junit-pioneer
+ junit-pioneer
+ test
+
+
org.springframework
spring-core-test
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java
index 95495accb4..5e971e370d 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java
@@ -39,6 +39,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.aot.AotDetector;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
@@ -87,6 +88,7 @@
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
+ * @author Hyunsang Han
*/
public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport {
@@ -338,8 +340,10 @@ public static class JpaRepositoryRegistrationAotProcessor extends RepositoryRegi
Environment environment = repositoryContext.getEnvironment();
+ String enabledByDefault = AotDetector.useGeneratedArtifacts() ? "true" : "false";
+
boolean enabled = Boolean
- .parseBoolean(environment.getProperty(AotContext.GENERATED_REPOSITORIES_ENABLED, "false"));
+ .parseBoolean(environment.getProperty(AotContext.GENERATED_REPOSITORIES_ENABLED, enabledByDefault));
if (!enabled) {
return null;
}
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryRegistrationAotProcessorUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryRegistrationAotProcessorUnitTests.java
index 82c06f9687..e3825d671e 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryRegistrationAotProcessorUnitTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryRegistrationAotProcessorUnitTests.java
@@ -30,6 +30,9 @@
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.ClearSystemProperty;
+import org.junitpioneer.jupiter.SetSystemProperty;
+import org.springframework.aot.AotDetector;
import org.springframework.aot.generate.ClassNameGenerator;
import org.springframework.aot.generate.DefaultGenerationContext;
import org.springframework.aot.generate.GenerationContext;
@@ -56,14 +59,14 @@
/**
* @author Christoph Strobl
+ * @author Hyunsang Han
*/
class JpaRepositoryRegistrationAotProcessorUnitTests {
@Test // GH-2628
void aotProcessorMustNotRegisterDomainTypes() {
- GenerationContext ctx = new DefaultGenerationContext(new ClassNameGenerator(ClassName.OBJECT),
- new InMemoryGeneratedFiles());
+ GenerationContext ctx = createGenerationContext();
new JpaRepositoryConfigExtension.JpaRepositoryRegistrationAotProcessor()
.contribute(new DummyAotRepositoryContext(null) {
@@ -79,8 +82,7 @@ public Set> getResolvedTypes() {
@Test // GH-2628
void aotProcessorMustNotRegisterAnnotations() {
- GenerationContext ctx = new DefaultGenerationContext(new ClassNameGenerator(ClassName.OBJECT),
- new InMemoryGeneratedFiles());
+ GenerationContext ctx = createGenerationContext();
new JpaRepositoryConfigExtension.JpaRepositoryRegistrationAotProcessor()
.contribute(new DummyAotRepositoryContext(null) {
@@ -99,8 +101,7 @@ public Set> getResolvedAnnotations() {
@Test // GH-3838
void repositoryProcessorShouldConsiderPersistenceManagedTypes() {
- GenerationContext ctx = new DefaultGenerationContext(new ClassNameGenerator(ClassName.OBJECT),
- new InMemoryGeneratedFiles());
+ GenerationContext ctx = createGenerationContext();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean(PersistenceManagedTypes.class, () -> {
@@ -126,12 +127,83 @@ public List getManagedPackages() {
context.getEnvironment().getPropertySources()
.addFirst(new MockPropertySource().withProperty(AotContext.GENERATED_REPOSITORIES_ENABLED, "true"));
- JpaRepositoryContributor contributor = new JpaRepositoryConfigExtension.JpaRepositoryRegistrationAotProcessor()
- .contribute(new DummyAotRepositoryContext(context), ctx);
+ JpaRepositoryContributor contributor = createContributor(new DummyAotRepositoryContext(context), ctx);
assertThat(contributor.getMetamodel().managedType(Person.class)).isNotNull();
}
+ @Test // GH-3899
+ @SetSystemProperty(key = AotDetector.AOT_ENABLED, value = "true")
+ void repositoryProcessorShouldEnableAotRepositoriesByDefaultWhenAotIsEnabled() {
+
+ GenerationContext ctx = createGenerationContext();
+ GenericApplicationContext context = createApplicationContext();
+
+ JpaRepositoryContributor contributor = createContributorWithPersonTypes(context, ctx);
+
+ assertThat(contributor).isNotNull();
+ }
+
+ @Test // GH-3899
+ @ClearSystemProperty(key = AotDetector.AOT_ENABLED)
+ void repositoryProcessorShouldNotEnableAotRepositoriesByDefaultWhenAotIsDisabled() {
+
+ GenerationContext ctx = createGenerationContext();
+ GenericApplicationContext context = createApplicationContext();
+
+ JpaRepositoryContributor contributor = createContributorWithPersonTypes(context, ctx);
+
+ assertThat(contributor).isNull();
+ }
+
+ @Test // GH-3899
+ @SetSystemProperty(key = AotDetector.AOT_ENABLED, value = "true")
+ @SetSystemProperty(key = AotContext.GENERATED_REPOSITORIES_ENABLED, value = "false")
+ void repositoryProcessorShouldRespectExplicitRepositoryEnabledProperty() {
+
+ GenerationContext ctx = createGenerationContext();
+ GenericApplicationContext context = createApplicationContext();
+
+ JpaRepositoryContributor contributor = createContributorWithPersonTypes(context, ctx);
+
+ assertThat(contributor).isNull();
+ }
+
+ @Test // GH-3899
+ @SetSystemProperty(key = AotContext.GENERATED_REPOSITORIES_ENABLED, value = "true")
+ void repositoryProcessorShouldEnableWhenExplicitlySetToTrue() {
+
+ GenerationContext ctx = createGenerationContext();
+ GenericApplicationContext context = createApplicationContext();
+
+ JpaRepositoryContributor contributor = createContributorWithPersonTypes(context, ctx);
+
+ assertThat(contributor).isNotNull();
+ }
+
+ private GenerationContext createGenerationContext() {
+ return new DefaultGenerationContext(new ClassNameGenerator(ClassName.OBJECT),
+ new InMemoryGeneratedFiles());
+ }
+
+ private GenericApplicationContext createApplicationContext() {
+ return new GenericApplicationContext();
+ }
+
+ private JpaRepositoryContributor createContributor(AotRepositoryContext repositoryContext, GenerationContext ctx) {
+ return new JpaRepositoryConfigExtension.JpaRepositoryRegistrationAotProcessor()
+ .contribute(repositoryContext, ctx);
+ }
+
+ private JpaRepositoryContributor createContributorWithPersonTypes(GenericApplicationContext context, GenerationContext ctx) {
+ return createContributor(new DummyAotRepositoryContext(context) {
+ @Override
+ public Set> getResolvedTypes() {
+ return Collections.singleton(Person.class);
+ }
+ }, ctx);
+ }
+
@Entity
static class Person {
@Id Long id;
diff --git a/src/main/antora/modules/ROOT/pages/jpa/aot.adoc b/src/main/antora/modules/ROOT/pages/jpa/aot.adoc
index e8d2d4a1a8..67fce33498 100644
--- a/src/main/antora/modules/ROOT/pages/jpa/aot.adoc
+++ b/src/main/antora/modules/ROOT/pages/jpa/aot.adoc
@@ -44,7 +44,12 @@ Do not use them directly in your code as generation and implementation details m
=== Running with AOT Repositories
AOT is a mandatory step to transform a Spring application to a native executable, so it is automatically enabled when running in this mode.
-It is also possible to use those optimizations on the JVM by setting the `spring.aot.enabled` and `spring.aot.repositories.enabled` properties to `true`.
+When AOT is enabled (either for native compilation or by setting `spring.aot.enabled=true`), AOT repositories are automatically enabled by default.
+
+You can explicitly control AOT repository generation by setting the `spring.aot.repositories.enabled` property:
+
+* `spring.aot.repositories.enabled=true` - Explicitly enable AOT repositories
+* `spring.aot.repositories.enabled=false` - Disable AOT repositories even when AOT is enabled
AOT repositories contribute configuration changes to the actual repository bean registration to register the generated repository fragment.