Browse Source

Polishing.

Introduce constants and test. Update documentation.

Original pull request: #5017
See #4983
pull/5026/head
Mark Paluch 5 months ago
parent
commit
61cbfb5a11
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 15
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotMongoRepositoryPostProcessor.java
  2. 202
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/AotMongoRepositoryPostProcessorUnitTests.java
  3. 7
      src/main/antora/modules/ROOT/pages/mongodb/aot.adoc

15
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotMongoRepositoryPostProcessor.java

@ -16,26 +16,31 @@
package org.springframework.data.mongodb.repository.aot; package org.springframework.data.mongodb.repository.aot;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.aot.generate.GenerationContext; import org.springframework.aot.generate.GenerationContext;
import org.springframework.data.aot.AotContext;
import org.springframework.data.mongodb.aot.LazyLoadingProxyAotProcessor; import org.springframework.data.mongodb.aot.LazyLoadingProxyAotProcessor;
import org.springframework.data.mongodb.aot.MongoAotPredicates; import org.springframework.data.mongodb.aot.MongoAotPredicates;
import org.springframework.data.repository.aot.generate.RepositoryContributor;
import org.springframework.data.repository.config.AotRepositoryContext; import org.springframework.data.repository.config.AotRepositoryContext;
import org.springframework.data.repository.config.RepositoryRegistrationAotProcessor; import org.springframework.data.repository.config.RepositoryRegistrationAotProcessor;
import org.springframework.data.util.TypeContributor; import org.springframework.data.util.TypeContributor;
import org.springframework.data.util.TypeUtils; import org.springframework.data.util.TypeUtils;
/** /**
* Mongodb-specific {@link RepositoryRegistrationAotProcessor} that contributes generated code for repositories.
*
* @author Christoph Strobl * @author Christoph Strobl
* @since 4.0
*/ */
public class AotMongoRepositoryPostProcessor extends RepositoryRegistrationAotProcessor { public class AotMongoRepositoryPostProcessor extends RepositoryRegistrationAotProcessor {
private static final String MODULE_NAME = "mongodb";
private final LazyLoadingProxyAotProcessor lazyLoadingProxyAotProcessor = new LazyLoadingProxyAotProcessor(); private final LazyLoadingProxyAotProcessor lazyLoadingProxyAotProcessor = new LazyLoadingProxyAotProcessor();
@Override @Override
protected @Nullable RepositoryContributor contribute(AotRepositoryContext repositoryContext, protected @Nullable MongoRepositoryContributor contribute(AotRepositoryContext repositoryContext,
GenerationContext generationContext) { GenerationContext generationContext) {
// do some custom type registration here // do some custom type registration here
super.contribute(repositoryContext, generationContext); super.contribute(repositoryContext, generationContext);
@ -44,7 +49,7 @@ public class AotMongoRepositoryPostProcessor extends RepositoryRegistrationAotPr
lazyLoadingProxyAotProcessor.registerLazyLoadingProxyIfNeeded(type, generationContext); lazyLoadingProxyAotProcessor.registerLazyLoadingProxyIfNeeded(type, generationContext);
}); });
if (!repositoryContext.isGeneratedRepositoriesEnabled("mongodb")) { if (!repositoryContext.isGeneratedRepositoriesEnabled(MODULE_NAME)) {
return null; return null;
} }
@ -57,6 +62,8 @@ public class AotMongoRepositoryPostProcessor extends RepositoryRegistrationAotPr
if (TypeUtils.type(type).isPartOf("org.springframework.data.mongodb", "com.mongodb")) { if (TypeUtils.type(type).isPartOf("org.springframework.data.mongodb", "com.mongodb")) {
return; return;
} }
super.contributeType(type, generationContext); super.contributeType(type, generationContext);
} }
} }

202
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/AotMongoRepositoryPostProcessorUnitTests.java

@ -0,0 +1,202 @@
/*
* 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.mongodb.repository.aot;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.jmolecules.ddd.annotation.Entity;
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;
import org.springframework.aot.generate.InMemoryGeneratedFiles;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.data.annotation.Id;
import org.springframework.data.aot.AotContext;
import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.config.AotRepositoryContext;
import org.springframework.data.repository.config.AotRepositoryInformation;
import org.springframework.data.repository.config.RepositoryConfigurationSource;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.support.AbstractRepositoryMetadata;
import org.springframework.javapoet.ClassName;
/**
* Unit tests for {@link AotMongoRepositoryPostProcessor}.
*
* @author Mark Paluch
*/
class AotMongoRepositoryPostProcessorUnitTests {
@Test // GH-4893
@SetSystemProperty(key = AotDetector.AOT_ENABLED, value = "true")
void repositoryProcessorShouldEnableAotRepositoriesByDefaultWhenAotIsEnabled() {
GenerationContext ctx = createGenerationContext();
GenericApplicationContext context = new GenericApplicationContext();
MongoRepositoryContributor contributor = createContributorWithPersonTypes(context, ctx);
assertThat(contributor).isNotNull();
}
@Test // GH-4893
@ClearSystemProperty(key = AotContext.GENERATED_REPOSITORIES_ENABLED)
void shouldEnableAotRepositoriesByDefault() {
GenerationContext ctx = createGenerationContext();
GenericApplicationContext context = new GenericApplicationContext();
MongoRepositoryContributor contributor = createContributorWithPersonTypes(context, ctx);
assertThat(contributor).isNotNull();
}
@Test // GH-4893
@SetSystemProperty(key = AotContext.GENERATED_REPOSITORIES_ENABLED, value = "false")
void shouldDisableAotRepositoriesWhenGeneratedRepositoriesIsFalse() {
GenerationContext ctx = createGenerationContext();
GenericApplicationContext context = new GenericApplicationContext();
MongoRepositoryContributor contributor = createContributorWithPersonTypes(context, ctx);
assertThat(contributor).isNull();
}
@Test // GH-3899
@SetSystemProperty(key = "spring.aot.mongodb.repositories.enabled", value = "false")
void shouldDisableAotRepositoriesWhenJpaGeneratedRepositoriesIsFalse() {
GenerationContext ctx = createGenerationContext();
GenericApplicationContext context = new GenericApplicationContext();
MongoRepositoryContributor contributor = createContributorWithPersonTypes(context, ctx);
assertThat(contributor).isNull();
}
private GenerationContext createGenerationContext() {
return new DefaultGenerationContext(new ClassNameGenerator(ClassName.OBJECT), new InMemoryGeneratedFiles());
}
private MongoRepositoryContributor createContributorWithPersonTypes(GenericApplicationContext context,
GenerationContext ctx) {
return new AotMongoRepositoryPostProcessor().contribute(new DummyAotRepositoryContext(context) {
@Override
public Set<Class<?>> getResolvedTypes() {
return Collections.singleton(Person.class);
}
}, ctx);
}
@Entity
static class Person {
@Id Long id;
}
interface PersonRepository extends Repository<Person, Long> {}
static class DummyAotRepositoryContext implements AotRepositoryContext {
private final @Nullable AbstractApplicationContext applicationContext;
DummyAotRepositoryContext(@Nullable AbstractApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public String getBeanName() {
return "jpaRepository";
}
@Override
public String getModuleName() {
return "JPA";
}
@Override
public RepositoryConfigurationSource getConfigurationSource() {
return mock(RepositoryConfigurationSource.class);
}
@Override
public Set<String> getBasePackages() {
return Collections.singleton(this.getClass().getPackageName());
}
@Override
public Set<Class<? extends Annotation>> getIdentifyingAnnotations() {
return Collections.singleton(Entity.class);
}
@Override
public RepositoryInformation getRepositoryInformation() {
return new AotRepositoryInformation(AbstractRepositoryMetadata.getMetadata(PersonRepository.class),
SimpleMongoRepository.class, List.of());
}
@Override
public Set<MergedAnnotation<Annotation>> getResolvedAnnotations() {
return Set.of();
}
@Override
public Set<Class<?>> getResolvedTypes() {
return Set.of();
}
@Override
public ConfigurableListableBeanFactory getBeanFactory() {
return applicationContext != null ? applicationContext.getBeanFactory() : null;
}
@Override
public Environment getEnvironment() {
return applicationContext == null ? new StandardEnvironment() : applicationContext.getEnvironment();
}
@Override
public TypeIntrospector introspectType(String typeName) {
return null;
}
@Override
public IntrospectedBeanDefinition introspectBeanDefinition(String beanName) {
return null;
}
}
}

7
src/main/antora/modules/ROOT/pages/mongodb/aot.adoc

@ -43,7 +43,12 @@ Do not use them directly in your code as generation and implementation details m
=== Running with AOT Repositories === 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. 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` System 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 disable AOT repository generation entirely or only disable MongoDB AOT repositories:
* Set the `spring.aot.repositories.enabled=false` property to disable generated repositories for all Spring Data modules.
* Set the `spring.aot.mongodb.repositories.enabled=false` property to disable only MongoDB AOT repositories.
AOT repositories contribute configuration changes to the actual repository bean registration to register the generated repository fragment. AOT repositories contribute configuration changes to the actual repository bean registration to register the generated repository fragment.

Loading…
Cancel
Save