Skip to content

Default spring.aot.repositories.enabled to true when AOT is active #3904

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<h2>2.3.232</h2>
<jakarta-persistence-api>3.2.0</jakarta-persistence-api>
<jsqlparser>5.2</jsqlparser>
<junit-pioneer>2.3.0</junit-pioneer>
<mysql-connector-java>9.2.0</mysql-connector-java>
<postgresql>42.7.5</postgresql>
<oracle>23.8.0.25.04</oracle>
Expand Down Expand Up @@ -183,6 +184,12 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.junit-pioneer</groupId>
<artifactId>junit-pioneer</artifactId>
<version>${junit-pioneer}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
6 changes: 6 additions & 0 deletions spring-data-jpa/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.junit-pioneer</groupId>
<artifactId>junit-pioneer</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core-test</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -87,6 +88,7 @@
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
* @author Hyunsang Han
*/
public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport {

Expand Down Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -79,8 +82,7 @@ public Set<Class<?>> 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) {
Expand All @@ -99,8 +101,7 @@ public Set<MergedAnnotation<Annotation>> 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, () -> {
Expand All @@ -126,12 +127,83 @@ public List<String> 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() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use @ClearSystemProperty here


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<Class<?>> getResolvedTypes() {
return Collections.singleton(Person.class);
}
}, ctx);
}

@Entity
static class Person {
@Id Long id;
Expand Down
7 changes: 6 additions & 1 deletion src/main/antora/modules/ROOT/pages/jpa/aot.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down