Introduce infrastructure for AOT processing of repository declarations
This commit introduces initial support for framework 6 bases ahead of time processing of data components and adds extension points for module implementations. See: #2593 Original Pull Request: #2624
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright 2022 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 static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.aot.RepositoryBeanContributionAssert.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.aop.SpringProxy;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.DecoratingProxy;
|
||||
import org.springframework.core.annotation.SynthesizedAnnotation;
|
||||
import org.springframework.data.annotation.QueryAnnotation;
|
||||
import org.springframework.data.aot.sample.ConfigWithCustomImplementation;
|
||||
import org.springframework.data.aot.sample.ConfigWithCustomRepositoryBaseClass;
|
||||
import org.springframework.data.aot.sample.ConfigWithFragments;
|
||||
import org.springframework.data.aot.sample.ConfigWithQueryMethods;
|
||||
import org.springframework.data.aot.sample.ConfigWithQueryMethods.ProjectionInterface;
|
||||
import org.springframework.data.aot.sample.ConfigWithSimpleCrudRepository;
|
||||
import org.springframework.data.aot.sample.ConfigWithTransactionManagerPresent;
|
||||
import org.springframework.data.aot.sample.ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty;
|
||||
import org.springframework.data.aot.sample.ReactiveConfig;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.repository.reactive.ReactiveSortingRepository;
|
||||
import org.springframework.transaction.interceptor.TransactionalProxy;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AotContributingRepositoryBeanPostProcessorTests {
|
||||
|
||||
@Test // GH-2593
|
||||
void simpleRepositoryNoTxManagerNoKotlinNoReactiveNoComponent() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(ConfigWithSimpleCrudRepository.class)
|
||||
.forRepository(ConfigWithSimpleCrudRepository.MyRepo.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.targetRepositoryTypeIs(ConfigWithSimpleCrudRepository.MyRepo.class) //
|
||||
.hasNoFragments() //
|
||||
.codeContributionSatisfies(contribution -> { //
|
||||
contribution.contributesReflectionFor(ConfigWithSimpleCrudRepository.MyRepo.class) // repository interface
|
||||
.contributesReflectionFor(PagingAndSortingRepository.class) // base repository
|
||||
.contributesReflectionFor(ConfigWithSimpleCrudRepository.Person.class) // repository domain type
|
||||
.contributesJdkProxy(ConfigWithSimpleCrudRepository.MyRepo.class, SpringProxy.class, Advised.class,
|
||||
DecoratingProxy.class) //
|
||||
.doesNotContributeJdkProxy(ConfigWithSimpleCrudRepository.MyRepo.class, Repository.class,
|
||||
TransactionalProxy.class, Advised.class, DecoratingProxy.class)
|
||||
.doesNotContributeJdkProxy(ConfigWithSimpleCrudRepository.MyRepo.class, Repository.class,
|
||||
TransactionalProxy.class, Advised.class, DecoratingProxy.class, Serializable.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void simpleRepositoryWithTxManagerNoKotlinNoReactiveNoComponent() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(
|
||||
ConfigWithTransactionManagerPresent.class).forRepository(ConfigWithTransactionManagerPresent.MyTxRepo.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.targetRepositoryTypeIs(ConfigWithTransactionManagerPresent.MyTxRepo.class) //
|
||||
.hasNoFragments() //
|
||||
.codeContributionSatisfies(contribution -> { //
|
||||
contribution.contributesReflectionFor(ConfigWithTransactionManagerPresent.MyTxRepo.class) // repository
|
||||
// interface
|
||||
.contributesReflectionFor(PagingAndSortingRepository.class) // base repository
|
||||
.contributesReflectionFor(ConfigWithTransactionManagerPresent.Person.class) // repository domain type
|
||||
|
||||
// proxies
|
||||
.contributesJdkProxy(ConfigWithTransactionManagerPresent.MyTxRepo.class, SpringProxy.class, Advised.class,
|
||||
DecoratingProxy.class)
|
||||
.contributesJdkProxy(ConfigWithTransactionManagerPresent.MyTxRepo.class, Repository.class,
|
||||
TransactionalProxy.class, Advised.class, DecoratingProxy.class)
|
||||
.doesNotContributeJdkProxy(ConfigWithTransactionManagerPresent.MyTxRepo.class, Repository.class,
|
||||
TransactionalProxy.class, Advised.class, DecoratingProxy.class, Serializable.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void simpleRepositoryWithTxManagerNoKotlinNoReactiveButComponent() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(
|
||||
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.class)
|
||||
.forRepository(ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.MyComponentTxRepo.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.targetRepositoryTypeIs(
|
||||
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.MyComponentTxRepo.class) //
|
||||
.hasNoFragments() //
|
||||
.codeContributionSatisfies(contribution -> { //
|
||||
contribution
|
||||
.contributesReflectionFor(
|
||||
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.MyComponentTxRepo.class) // repository
|
||||
// interface
|
||||
.contributesReflectionFor(PagingAndSortingRepository.class) // base repository
|
||||
.contributesReflectionFor(
|
||||
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.Person.class) // repository domain
|
||||
// type
|
||||
|
||||
// proxies
|
||||
.contributesJdkProxy(
|
||||
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.MyComponentTxRepo.class,
|
||||
SpringProxy.class, Advised.class, DecoratingProxy.class)
|
||||
.contributesJdkProxy(
|
||||
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.MyComponentTxRepo.class,
|
||||
Repository.class, TransactionalProxy.class, Advised.class, DecoratingProxy.class)
|
||||
.contributesJdkProxy(
|
||||
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.MyComponentTxRepo.class,
|
||||
Repository.class, TransactionalProxy.class, Advised.class, DecoratingProxy.class, Serializable.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void contributesFragmentsCorrectly() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(ConfigWithFragments.class)
|
||||
.forRepository(ConfigWithFragments.RepositoryWithFragments.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.targetRepositoryTypeIs(ConfigWithFragments.RepositoryWithFragments.class) //
|
||||
.hasFragments() //
|
||||
.codeContributionSatisfies(contribution -> { //
|
||||
contribution.contributesReflectionFor(ConfigWithFragments.RepositoryWithFragments.class) // repository
|
||||
// interface
|
||||
.contributesReflectionFor(PagingAndSortingRepository.class) // base repository
|
||||
.contributesReflectionFor(ConfigWithFragments.Person.class) // repository domain type
|
||||
|
||||
// fragments
|
||||
.contributesReflectionFor(ConfigWithFragments.CustomImplInterface1.class,
|
||||
ConfigWithFragments.CustomImplInterface1Impl.class)
|
||||
.contributesReflectionFor(ConfigWithFragments.CustomImplInterface2.class,
|
||||
ConfigWithFragments.CustomImplInterface2Impl.class)
|
||||
|
||||
// proxies
|
||||
.contributesJdkProxy(ConfigWithFragments.RepositoryWithFragments.class, SpringProxy.class, Advised.class,
|
||||
DecoratingProxy.class)
|
||||
.doesNotContributeJdkProxy(
|
||||
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.MyComponentTxRepo.class,
|
||||
Repository.class, TransactionalProxy.class, Advised.class, DecoratingProxy.class)
|
||||
.doesNotContributeJdkProxy(
|
||||
ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.MyComponentTxRepo.class,
|
||||
Repository.class, TransactionalProxy.class, Advised.class, DecoratingProxy.class, Serializable.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void contributesCustomImplementationCorrectly() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(ConfigWithCustomImplementation.class)
|
||||
.forRepository(ConfigWithCustomImplementation.RepositoryWithCustomImplementation.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.targetRepositoryTypeIs(ConfigWithCustomImplementation.RepositoryWithCustomImplementation.class) //
|
||||
.hasFragments() //
|
||||
.codeContributionSatisfies(contribution -> { //
|
||||
contribution.contributesReflectionFor(ConfigWithCustomImplementation.RepositoryWithCustomImplementation.class) // repository
|
||||
// interface
|
||||
.contributesReflectionFor(PagingAndSortingRepository.class) // base repository
|
||||
.contributesReflectionFor(ConfigWithCustomImplementation.Person.class) // repository domain type
|
||||
|
||||
// fragments
|
||||
.contributesReflectionFor(ConfigWithCustomImplementation.CustomImplInterface.class,
|
||||
ConfigWithCustomImplementation.RepositoryWithCustomImplementationImpl.class);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void contributesDomainTypeAndReachablesCorrectly() {
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(ConfigWithSimpleCrudRepository.class)
|
||||
.forRepository(ConfigWithSimpleCrudRepository.MyRepo.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.codeContributionSatisfies(contribution -> {
|
||||
contribution.contributesReflectionFor(ConfigWithSimpleCrudRepository.Person.class,
|
||||
ConfigWithSimpleCrudRepository.Address.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void contributesReactiveRepositoryCorrectly() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(ReactiveConfig.class)
|
||||
.forRepository(ReactiveConfig.CustomerRepositoryReactive.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.targetRepositoryTypeIs(ReactiveConfig.CustomerRepositoryReactive.class) //
|
||||
.hasNoFragments() //
|
||||
.codeContributionSatisfies(contribution -> { //
|
||||
// interface
|
||||
contribution.contributesReflectionFor(ReactiveConfig.CustomerRepositoryReactive.class) // repository
|
||||
.contributesReflectionFor(ReactiveSortingRepository.class) // base repo class
|
||||
.contributesReflectionFor(ReactiveConfig.Person.class); // repository domain type
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void contributesRepositoryBaseClassCorrectly() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(
|
||||
ConfigWithCustomRepositoryBaseClass.class)
|
||||
.forRepository(ConfigWithCustomRepositoryBaseClass.CustomerRepositoryWithCustomBaseRepo.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.targetRepositoryTypeIs(ConfigWithCustomRepositoryBaseClass.CustomerRepositoryWithCustomBaseRepo.class) //
|
||||
.hasNoFragments() //
|
||||
.codeContributionSatisfies(contribution -> { //
|
||||
// interface
|
||||
contribution
|
||||
.contributesReflectionFor(ConfigWithCustomRepositoryBaseClass.CustomerRepositoryWithCustomBaseRepo.class) // repository
|
||||
.contributesReflectionFor(ConfigWithCustomRepositoryBaseClass.RepoBaseClass.class) // base repo class
|
||||
.contributesReflectionFor(ConfigWithCustomRepositoryBaseClass.Person.class); // repository domain type
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void contributesTypesFromQueryMethods() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(ConfigWithQueryMethods.class)
|
||||
.forRepository(ConfigWithQueryMethods.CustomerRepositoryWithQueryMethods.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.codeContributionSatisfies(contribution -> {
|
||||
contribution.contributesReflectionFor(ProjectionInterface.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void contributesProxiesForPotentialProjections() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(ConfigWithQueryMethods.class)
|
||||
.forRepository(ConfigWithQueryMethods.CustomerRepositoryWithQueryMethods.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.codeContributionSatisfies(contribution -> {
|
||||
|
||||
contribution.contributesJdkProxyFor(ProjectionInterface.class);
|
||||
contribution.doesNotContributeJdkProxyFor(Page.class);
|
||||
contribution.doesNotContributeJdkProxyFor(ConfigWithQueryMethods.Person.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void contributesProxiesForDataAnnotations() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(ConfigWithQueryMethods.class)
|
||||
.forRepository(ConfigWithQueryMethods.CustomerRepositoryWithQueryMethods.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.codeContributionSatisfies(contribution -> {
|
||||
|
||||
contribution.contributesJdkProxy(Param.class, SynthesizedAnnotation.class);
|
||||
contribution.contributesJdkProxy(ConfigWithQueryMethods.CustomQuery.class, SynthesizedAnnotation.class);
|
||||
contribution.contributesJdkProxy(QueryAnnotation.class, SynthesizedAnnotation.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void doesNotCareAboutNonDataAnnotations() {
|
||||
|
||||
RepositoryBeanContribution repositoryBeanContribution = computeConfiguration(ConfigWithSimpleCrudRepository.class)
|
||||
.forRepository(ConfigWithSimpleCrudRepository.MyRepo.class);
|
||||
|
||||
assertThatContribution(repositoryBeanContribution) //
|
||||
.codeContributionSatisfies(contribution -> {
|
||||
contribution.doesNotContributeReflectionFor(javax.annotation.Nullable.class);
|
||||
contribution.doesNotContributeJdkProxyFor(javax.annotation.Nullable.class);
|
||||
});
|
||||
}
|
||||
|
||||
BeanContributionBuilder computeConfiguration(Class<?> configuration, AnnotationConfigApplicationContext ctx) {
|
||||
|
||||
ctx.register(configuration);
|
||||
ctx.refreshForAotProcessing();
|
||||
|
||||
return it -> {
|
||||
|
||||
String[] repoBeanNames = ctx.getBeanNamesForType(it);
|
||||
assertThat(repoBeanNames).describedAs("Unable to find repository %s in configuration %s.", it, configuration)
|
||||
.hasSize(1);
|
||||
|
||||
String beanName = repoBeanNames[0];
|
||||
BeanDefinition beanDefinition = ctx.getBeanDefinition(beanName);
|
||||
|
||||
AotContributingRepositoryBeanPostProcessor postProcessor = ctx
|
||||
.getBean(AotContributingRepositoryBeanPostProcessor.class);
|
||||
|
||||
postProcessor.setBeanFactory(ctx.getDefaultListableBeanFactory());
|
||||
|
||||
return postProcessor.contribute((RootBeanDefinition) beanDefinition, it, beanName);
|
||||
};
|
||||
}
|
||||
|
||||
BeanContributionBuilder computeConfiguration(Class<?> configuration) {
|
||||
return computeConfiguration(configuration, new AnnotationConfigApplicationContext());
|
||||
}
|
||||
|
||||
interface BeanContributionBuilder {
|
||||
RepositoryBeanContribution forRepository(Class<?> repositoryInterface);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2022 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 static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.data.ManagedTypes;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
class AotDataComponentsBeanFactoryPostProcessorUnitTests {
|
||||
|
||||
@Test // Gh-2593
|
||||
void replacesManagedTypesBeanDefinitionUsingSupplierForCtorValue() {
|
||||
|
||||
Supplier<Iterable<Class<?>>> typesSupplier = mock(Supplier.class);
|
||||
|
||||
Mockito.when(typesSupplier.get()).thenReturn(Collections.singleton(DomainType.class));
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerBeanDefinition("data.managed-types", BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ManagedTypes.class).addConstructorArgValue(typesSupplier).getBeanDefinition());
|
||||
|
||||
new AotDataComponentsBeanFactoryPostProcessor().contribute(beanFactory);
|
||||
|
||||
assertThat(beanFactory.getBeanNamesForType(ManagedTypes.class)).hasSize(1);
|
||||
verify(typesSupplier).get();
|
||||
|
||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("data.managed-types");
|
||||
assertThat(beanDefinition.getFactoryMethodName()).isEqualTo("of");
|
||||
assertThat(beanDefinition.hasConstructorArgumentValues()).isTrue();
|
||||
assertThat(beanDefinition.getConstructorArgumentValues().getArgumentValue(0, null).getValue())
|
||||
.isEqualTo(Collections.singleton(DomainType.class));
|
||||
}
|
||||
|
||||
@Test // Gh-2593
|
||||
void leavesManagedTypesBeanDefinitionNotUsingSupplierForCtorValue() {
|
||||
|
||||
Iterable<Class<?>> types = spy(new LinkedHashSet<>(Collections.singleton(DomainType.class)));
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
AbstractBeanDefinition sourceBD = BeanDefinitionBuilder.rootBeanDefinition(ManagedTypes.class)
|
||||
.addConstructorArgValue(types).getBeanDefinition();
|
||||
beanFactory.registerBeanDefinition("data.managed-types", sourceBD);
|
||||
|
||||
new AotDataComponentsBeanFactoryPostProcessor().contribute(beanFactory);
|
||||
|
||||
assertThat(beanFactory.getBeanNamesForType(ManagedTypes.class)).hasSize(1);
|
||||
verifyNoInteractions(types);
|
||||
|
||||
assertThat(beanFactory.getBeanDefinition("data.managed-types")).isSameAs(sourceBD);
|
||||
}
|
||||
|
||||
private static class DomainType {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2022 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 static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.aot.generator.DefaultCodeContribution;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.generator.BeanInstantiationContribution;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.data.ManagedTypes;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
class AotManagedTypesPostProcessorUnitTests {
|
||||
|
||||
final RootBeanDefinition managedTypesDefinition = (RootBeanDefinition) BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ManagedTypes.class).setFactoryMethod("of")
|
||||
.addConstructorArgValue(Collections.singleton(A.class)).getBeanDefinition();
|
||||
|
||||
final RootBeanDefinition myManagedTypesDefinition = (RootBeanDefinition) BeanDefinitionBuilder
|
||||
.rootBeanDefinition(MyManagedTypes.class).getBeanDefinition();
|
||||
|
||||
@Test // GH-2593
|
||||
void processesBeanWithMatchingModulePrefix() {
|
||||
|
||||
BeanInstantiationContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
}).contribute(managedTypesDefinition, ManagedTypes.class, "commons.managed-types");
|
||||
|
||||
assertThat(contribution).isNotNull();
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void contributesReflectionForManagedTypes() {
|
||||
|
||||
BeanInstantiationContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
}).contribute(managedTypesDefinition, ManagedTypes.class, "commons.managed-types");
|
||||
|
||||
DefaultCodeContribution codeContribution = new DefaultCodeContribution(new RuntimeHints());
|
||||
contribution.applyTo(codeContribution);
|
||||
|
||||
new CodeContributionAssert(codeContribution) //
|
||||
.contributesReflectionFor(A.class) //
|
||||
.doesNotContributeReflectionFor(B.class);
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void processesMatchingSubtypeBean() {
|
||||
|
||||
BeanInstantiationContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", myManagedTypesDefinition);
|
||||
}).contribute(myManagedTypesDefinition, MyManagedTypes.class, "commons.managed-types");
|
||||
|
||||
assertThat(contribution).isNotNull();
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void ignoresBeanNotMatchingRequiredType() {
|
||||
|
||||
BeanInstantiationContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
}).contribute(managedTypesDefinition, Object.class, "commons.managed-types");
|
||||
|
||||
assertThat(contribution).isNull();
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void ignoresBeanNotMatchingPrefix() {
|
||||
|
||||
BeanInstantiationContribution contribution = createPostProcessor("commons", bf -> {
|
||||
bf.registerBeanDefinition("commons.managed-types", managedTypesDefinition);
|
||||
}).contribute(managedTypesDefinition, ManagedTypes.class, "jpa.managed-types");
|
||||
|
||||
assertThat(contribution).isNull();
|
||||
}
|
||||
|
||||
private AotManagedTypesPostProcessor createPostProcessor(String prefix, Consumer<DefaultListableBeanFactory> action) {
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
action.accept(beanFactory);
|
||||
|
||||
AotManagedTypesPostProcessor postProcessor = createPostProcessor(beanFactory);
|
||||
postProcessor.setModulePrefix(prefix);
|
||||
|
||||
return postProcessor;
|
||||
}
|
||||
|
||||
private AotManagedTypesPostProcessor createPostProcessor(BeanFactory beanFactory) {
|
||||
|
||||
AotManagedTypesPostProcessor aotManagedTypesPostProcessor = new AotManagedTypesPostProcessor();
|
||||
aotManagedTypesPostProcessor.setBeanFactory(beanFactory);
|
||||
return aotManagedTypesPostProcessor;
|
||||
}
|
||||
|
||||
static class A {}
|
||||
|
||||
static class B {}
|
||||
|
||||
static class MyManagedTypes implements ManagedTypes {
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<Class<?>> action) {
|
||||
// just do nothing ¯\_(ツ)_/¯
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2022 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 static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.springframework.aot.hint.ClassProxyHint;
|
||||
import org.springframework.aot.hint.TypeReference;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2022/04
|
||||
*/
|
||||
public class ClassProxyAssert extends AbstractAssert<ClassProxyAssert, ClassProxyHint> {
|
||||
|
||||
protected ClassProxyAssert(ClassProxyHint classProxyHint) {
|
||||
super(classProxyHint, ClassProxyAssert.class);
|
||||
}
|
||||
|
||||
public void matches(Class<?>... proxyInterfaces) {
|
||||
assertThat(actual.getProxiedInterfaces().stream().map(TypeReference::getCanonicalName))
|
||||
.containsExactly(Arrays.stream(proxyInterfaces).map(Class::getCanonicalName).toArray(String[]::new));
|
||||
}
|
||||
|
||||
public List<TypeReference> getProxiedInterfaces() {
|
||||
return actual.getProxiedInterfaces();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2022 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 static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.springframework.aot.generator.CodeContribution;
|
||||
import org.springframework.aot.generator.ProtectedAccess;
|
||||
import org.springframework.aot.hint.ClassProxyHint;
|
||||
import org.springframework.aot.hint.JdkProxyHint;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.javapoet.support.MultiStatement;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2022/04
|
||||
*/
|
||||
public class CodeContributionAssert extends AbstractAssert<CodeContributionAssert, CodeContribution>
|
||||
implements CodeContribution {
|
||||
|
||||
public CodeContributionAssert(CodeContribution contribution) {
|
||||
super(contribution, CodeContributionAssert.class);
|
||||
}
|
||||
|
||||
public CodeContributionAssert doesNotContributeReflectionFor(Class<?>... types) {
|
||||
|
||||
for (Class<?> type : types) {
|
||||
assertThat(this.actual.runtimeHints().reflection().getTypeHint(type))
|
||||
.describedAs("Reflection entry found for %s", type).isNull();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CodeContributionAssert contributesReflectionFor(Class<?>... types) {
|
||||
|
||||
for (Class<?> type : types) {
|
||||
assertThat(this.actual.runtimeHints().reflection().getTypeHint(type))
|
||||
.describedAs("No reflection entry found for %s", type).isNotNull();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CodeContributionAssert contributesJdkProxyFor(Class<?> entryPoint) {
|
||||
assertThat(jdkProxiesFor(entryPoint).findFirst()).describedAs("No jdk proxy found for %s", entryPoint).isPresent();
|
||||
return this;
|
||||
}
|
||||
|
||||
public CodeContributionAssert doesNotContributeJdkProxyFor(Class<?> entryPoint) {
|
||||
assertThat(jdkProxiesFor(entryPoint).findFirst()).describedAs("Found jdk proxy matching %s though it should not be present.", entryPoint).isNotPresent();
|
||||
return this;
|
||||
}
|
||||
|
||||
public CodeContributionAssert doesNotContributeJdkProxy(Class<?>... proxyInterfaces) {
|
||||
|
||||
assertThat(jdkProxiesFor(proxyInterfaces[0])).describedAs("Found jdk proxy matching %s though it should not be present.", Arrays.asList(proxyInterfaces)).noneSatisfy(it -> {
|
||||
new JdkProxyAssert(it).matches(proxyInterfaces);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public CodeContributionAssert contributesJdkProxy(Class<?>... proxyInterfaces) {
|
||||
|
||||
assertThat(jdkProxiesFor(proxyInterfaces[0])).describedAs("Unable to find jdk proxy matching %s", Arrays.asList(proxyInterfaces)).anySatisfy(it -> {
|
||||
new JdkProxyAssert(it).matches(proxyInterfaces);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private Stream<JdkProxyHint> jdkProxiesFor(Class<?> entryPoint) {
|
||||
return this.actual.runtimeHints().proxies().jdkProxies().filter(jdkProxyHint -> {
|
||||
return jdkProxyHint.getProxiedInterfaces().get(0).getCanonicalName().equals(entryPoint.getCanonicalName());
|
||||
});
|
||||
}
|
||||
|
||||
public CodeContributionAssert contributesClassProxy(Class<?>... proxyInterfaces) {
|
||||
|
||||
assertThat(classProxiesFor(proxyInterfaces[0])).describedAs("Unable to find jdk proxy matching %s", Arrays.asList(proxyInterfaces)).anySatisfy(it -> {
|
||||
new ClassProxyAssert(it).matches(proxyInterfaces);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private Stream<ClassProxyHint> classProxiesFor(Class<?> entryPoint) {
|
||||
return this.actual.runtimeHints().proxies().classProxies().filter(jdkProxyHint -> {
|
||||
return jdkProxyHint.getProxiedInterfaces().get(0).getCanonicalName().equals(entryPoint.getCanonicalName());
|
||||
});
|
||||
}
|
||||
|
||||
public MultiStatement statements() {
|
||||
return actual.statements();
|
||||
}
|
||||
|
||||
public RuntimeHints runtimeHints() {
|
||||
return actual.runtimeHints();
|
||||
}
|
||||
|
||||
public ProtectedAccess protectedAccess() {
|
||||
return actual.protectedAccess();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2022 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 static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.springframework.aot.hint.JdkProxyHint;
|
||||
import org.springframework.aot.hint.TypeReference;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2022/04
|
||||
*/
|
||||
public class JdkProxyAssert extends AbstractAssert<JdkProxyAssert, JdkProxyHint> {
|
||||
|
||||
public JdkProxyAssert(JdkProxyHint jdkProxyHint) {
|
||||
super(jdkProxyHint, JdkProxyAssert.class);
|
||||
}
|
||||
|
||||
public void matches(Class<?>... proxyInterfaces) {
|
||||
assertThat(actual.getProxiedInterfaces().stream().map(TypeReference::getCanonicalName))
|
||||
.containsExactly(Arrays.stream(proxyInterfaces).map(Class::getCanonicalName).toArray(String[]::new));
|
||||
}
|
||||
|
||||
public List<TypeReference> getProxiedInterfaces() {
|
||||
return actual.getProxiedInterfaces();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2022 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 static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.springframework.aot.generator.CodeContribution;
|
||||
import org.springframework.aot.generator.DefaultCodeContribution;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.support.RepositoryFragment;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2022/04
|
||||
*/
|
||||
public class RepositoryBeanContributionAssert
|
||||
extends AbstractAssert<RepositoryBeanContributionAssert, RepositoryBeanContribution> {
|
||||
|
||||
public RepositoryBeanContributionAssert(RepositoryBeanContribution actual) {
|
||||
super(actual, RepositoryBeanContributionAssert.class);
|
||||
}
|
||||
|
||||
public static RepositoryBeanContributionAssert assertThatContribution(RepositoryBeanContribution actual) {
|
||||
return new RepositoryBeanContributionAssert(actual);
|
||||
}
|
||||
|
||||
public RepositoryBeanContributionAssert targetRepositoryTypeIs(Class<?> expected) {
|
||||
|
||||
assertThat(getRepositoryInformation().getRepositoryInterface()).isEqualTo(expected);
|
||||
return myself;
|
||||
}
|
||||
|
||||
public RepositoryBeanContributionAssert hasNoFragments() {
|
||||
assertThat(getRepositoryInformation().getFragments()).isEmpty();
|
||||
return this;
|
||||
}
|
||||
|
||||
public RepositoryBeanContributionAssert hasFragments() {
|
||||
|
||||
assertThat(getRepositoryInformation().getFragments()).isNotEmpty();
|
||||
return this;
|
||||
}
|
||||
|
||||
public RepositoryBeanContributionAssert verifyFragments(Consumer<Set<RepositoryFragment<?>>> consumer) {
|
||||
|
||||
assertThat(getRepositoryInformation().getFragments()).satisfies(it -> consumer.accept(new LinkedHashSet<>(it)));
|
||||
return this;
|
||||
}
|
||||
|
||||
public RepositoryBeanContributionAssert codeContributionSatisfies(Consumer<CodeContributionAssert> consumer) {
|
||||
|
||||
DefaultCodeContribution codeContribution = new DefaultCodeContribution(new RuntimeHints());
|
||||
this.actual.applyTo(codeContribution);
|
||||
consumer.accept(new CodeContributionAssert(codeContribution));
|
||||
return this;
|
||||
}
|
||||
|
||||
private RepositoryInformation getRepositoryInformation() {
|
||||
assertThat(this.actual).describedAs("No repository interface found on null bean contribution.").isNotNull();
|
||||
assertThat(this.actual.getRepositoryInformation())
|
||||
.describedAs("No repository interface found on null repository information.").isNotNull();
|
||||
return this.actual.getRepositoryInformation();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2022 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 static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.aot.types.*;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class TypeCollectorUnitTests {
|
||||
|
||||
@Test // GH-2593
|
||||
void detectsSignatureTypes() {
|
||||
assertThat(TypeCollector.inspect(FieldsAndMethods.class).list()).containsExactlyInAnyOrder(FieldsAndMethods.class,
|
||||
AbstractType.class, InterfaceType.class);
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void detectsMethodArgs() {
|
||||
assertThat(TypeCollector.inspect(TypesInMethodSignatures.class).list())
|
||||
.containsExactlyInAnyOrder(TypesInMethodSignatures.class, EmptyType1.class, EmptyType2.class);
|
||||
}
|
||||
|
||||
@Test // GH-2593
|
||||
void doesNotOverflowOnCyclicPropertyReferences() {
|
||||
assertThat(TypeCollector.inspect(CyclicPropertiesA.class).list()).containsExactlyInAnyOrder(CyclicPropertiesA.class,
|
||||
CyclicPropertiesB.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotOverflowOnCyclicSelfReferences() {
|
||||
assertThat(TypeCollector.inspect(CyclicPropertiesSelf.class).list())
|
||||
.containsExactlyInAnyOrder(CyclicPropertiesSelf.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotOverflowOnCyclicGenericsReferences() {
|
||||
assertThat(TypeCollector.inspect(CyclicGenerics.class).list()).containsExactlyInAnyOrder(CyclicGenerics.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void includesDeclaredClassesInInspection() {
|
||||
assertThat(TypeCollector.inspect(WithDeclaredClass.class).list()).containsExactlyInAnyOrder(WithDeclaredClass.class,
|
||||
WithDeclaredClass.SomeEnum.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2021 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.sample;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.aot.sample.ConfigWithCustomFactoryBeanBaseClass.MyFixedRepoFactory;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.config.EnableRepositories;
|
||||
import org.springframework.data.repository.core.support.DummyRepositoryFactoryBean;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRepositories(repositoryFactoryBeanClass = MyFixedRepoFactory.class, considerNestedRepositories = true,
|
||||
includeFilters = { @Filter(type = FilterType.REGEX, pattern = ".*FixedFactoryRepository") })
|
||||
public class ConfigWithCustomFactoryBeanBaseClass {
|
||||
|
||||
public interface FixedFactoryRepository extends CrudRepository<Person, String> {
|
||||
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
Address address;
|
||||
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
String street;
|
||||
}
|
||||
|
||||
public static class MyFixedRepoFactory extends DummyRepositoryFactoryBean<FixedFactoryRepository, Person, String> {
|
||||
|
||||
public MyFixedRepoFactory(Class<? extends FixedFactoryRepository> repositoryInterface) {
|
||||
super(FixedFactoryRepository.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.sample;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.config.EnableRepositories;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRepositories(considerNestedRepositories = true,
|
||||
includeFilters = { @Filter(type = FilterType.REGEX, pattern = ".*RepositoryWithCustomImplementation") })
|
||||
public class ConfigWithCustomImplementation {
|
||||
|
||||
public interface RepositoryWithCustomImplementation extends Repository<Person, String>, CustomImplInterface {
|
||||
|
||||
}
|
||||
|
||||
public interface CustomImplInterface {
|
||||
|
||||
List<Person> findMyCustomer();
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class RepositoryWithCustomImplementationImpl implements CustomImplInterface {
|
||||
|
||||
@Override
|
||||
public List<Person> findMyCustomer() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
Address address;
|
||||
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
String street;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2021 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.sample;
|
||||
|
||||
import lombok.experimental.Delegate;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.aot.sample.ConfigWithCustomRepositoryBaseClass.RepoBaseClass;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.config.EnableRepositories;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRepositories(repositoryBaseClass = RepoBaseClass.class, considerNestedRepositories = true,
|
||||
includeFilters = { @Filter(type = FilterType.REGEX, pattern = ".*CustomerRepositoryWithCustomBaseRepo$") })
|
||||
public class ConfigWithCustomRepositoryBaseClass {
|
||||
|
||||
public interface CustomerRepositoryWithCustomBaseRepo extends CrudRepository<Person, String> {
|
||||
|
||||
}
|
||||
|
||||
public static class RepoBaseClass<T, ID> implements CrudRepository<T, ID> {
|
||||
|
||||
private @Delegate CrudRepository<T, ID> delegate;
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
Address address;
|
||||
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
String street;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.sample;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.config.EnableRepositories;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRepositories(considerNestedRepositories = true,
|
||||
includeFilters = { @Filter(type = FilterType.REGEX, pattern = ".*RepositoryWithFragments") })
|
||||
public class ConfigWithFragments {
|
||||
|
||||
public interface RepositoryWithFragments
|
||||
extends Repository<Person, String>, CustomImplInterface1, CustomImplInterface2 {
|
||||
|
||||
}
|
||||
|
||||
public interface CustomImplInterface1 {
|
||||
|
||||
List<Customer> findMyCustomer();
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class CustomImplInterface1Impl implements CustomImplInterface1 {
|
||||
|
||||
@Override
|
||||
public List<Customer> findMyCustomer() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public interface CustomImplInterface2 {
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class CustomImplInterface2Impl implements CustomImplInterface2 {
|
||||
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
Address address;
|
||||
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
String street;
|
||||
}
|
||||
|
||||
public static class Customer {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.sample;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.annotation.QueryAnnotation;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.config.EnableRepositories;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRepositories(considerNestedRepositories = true, includeFilters = {@Filter(type = FilterType.REGEX, pattern = ".*CustomerRepositoryWithQueryMethods")})
|
||||
public class ConfigWithQueryMethods {
|
||||
|
||||
public interface CustomerRepositoryWithQueryMethods extends Repository<Person, String> {
|
||||
|
||||
Page<Person> findAllBy(@Param("longValue") Long val);
|
||||
|
||||
@CustomQuery
|
||||
String customQuery();
|
||||
|
||||
ProjectionInterface findProjectionBy();
|
||||
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
Address address;
|
||||
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
String street;
|
||||
}
|
||||
|
||||
public interface ProjectionInterface {}
|
||||
|
||||
@Nullable
|
||||
@QueryAnnotation
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CustomQuery {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2022 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.sample;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.aot.sample.ConfigWithSimpleCrudRepository.MyRepo;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.config.EnableRepositories;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@EnableRepositories(includeFilters = { @Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyRepo.class) },
|
||||
basePackageClasses = ConfigWithSimpleCrudRepository.class, considerNestedRepositories = true)
|
||||
public class ConfigWithSimpleCrudRepository {
|
||||
|
||||
public interface MyRepo extends CrudRepository<Person, String> {
|
||||
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
@javax.annotation.Nullable
|
||||
Address address;
|
||||
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
String street;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2022 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.sample;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.aot.sample.ConfigWithTransactionManagerPresent.MyTxRepo;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.config.EnableRepositories;
|
||||
import org.springframework.transaction.TransactionManager;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@EnableRepositories(includeFilters = { @Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyTxRepo.class) },
|
||||
basePackageClasses = ConfigWithTransactionManagerPresent.class, considerNestedRepositories = true)
|
||||
public class ConfigWithTransactionManagerPresent {
|
||||
|
||||
public interface MyTxRepo extends CrudRepository<Person, String> {
|
||||
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
Address address;
|
||||
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
String street;
|
||||
}
|
||||
|
||||
@Bean
|
||||
TransactionManager txManager() {
|
||||
return Mockito.mock(TransactionManager.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2022 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.sample;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.aot.sample.ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.MyComponentTxRepo;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.config.EnableRepositories;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.TransactionManager;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@EnableRepositories(includeFilters = { @Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyComponentTxRepo.class) },
|
||||
basePackageClasses = ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty.class,
|
||||
considerNestedRepositories = true)
|
||||
public class ConfigWithTransactionManagerPresentAndAtComponentAnnotatedRepoisoty {
|
||||
|
||||
@Component
|
||||
public interface MyComponentTxRepo extends CrudRepository<Person, String> {
|
||||
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
Address address;
|
||||
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
String street;
|
||||
}
|
||||
|
||||
@Bean
|
||||
TransactionManager txManager() {
|
||||
return Mockito.mock(TransactionManager.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.sample;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.repository.config.EnableReactiveRepositories;
|
||||
import org.springframework.data.repository.config.EnableRepositories;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Configuration
|
||||
@EnableReactiveRepositories(considerNestedRepositories = true, includeFilters = {@Filter(type = FilterType.REGEX, pattern = ".*CustomerRepositoryReactive$")})
|
||||
public class ReactiveConfig {
|
||||
|
||||
public interface CustomerRepositoryReactive extends ReactiveCrudRepository<Person, String> {
|
||||
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
Address address;
|
||||
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
String street;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public abstract class AbstractType {
|
||||
|
||||
private Object fieldInAbstractType;
|
||||
|
||||
abstract Object abstractMethod();
|
||||
|
||||
Object methodDefinedInAbstractType() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2021 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.types;
|
||||
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.annotation.PersistenceCreator;
|
||||
import org.springframework.data.geo.Point;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class Address implements LocationHolder {
|
||||
|
||||
String street;
|
||||
Point location;
|
||||
|
||||
Address() {
|
||||
}
|
||||
|
||||
@PersistenceCreator
|
||||
Address(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point getLocation() {
|
||||
return location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class BaseEntity {
|
||||
|
||||
Address address;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.types;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@TypeAlias("cu")
|
||||
public class Customer extends BaseEntity {
|
||||
|
||||
@Id
|
||||
String id;
|
||||
|
||||
@Transient
|
||||
String transientProperty;
|
||||
|
||||
@LastModifiedDate
|
||||
Instant modifiedAt;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class CyclicGenerics<T extends CyclicGenerics<? extends CyclicGenerics<T>>> {
|
||||
|
||||
T property;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class CyclicPropertiesA {
|
||||
|
||||
CyclicPropertiesB b;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class CyclicPropertiesB {
|
||||
|
||||
CyclicPropertiesA refToA;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class CyclicPropertiesSelf {
|
||||
|
||||
CyclicPropertiesSelf refSelf;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2021 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.types;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class DomainObjectWithSimpleTypesOnly {
|
||||
|
||||
@Id
|
||||
String id;
|
||||
Long longValue;
|
||||
int primValue;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2022 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class EmptyType1 {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2022 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class EmptyType2 {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class FieldsAndMethods extends AbstractType implements InterfaceType {
|
||||
|
||||
public static final Object CONSTANT_FIELD = null;
|
||||
|
||||
private Object privateField;
|
||||
Object packagePrivateField;
|
||||
protected Object protectedField;
|
||||
public Object publicField;
|
||||
|
||||
@Override
|
||||
Long abstractMethod() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer someDefaultMethod() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object privateMethod() {
|
||||
return null;
|
||||
}
|
||||
|
||||
Object packagePrivateMethod() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Object protectedMethod() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object publicMethod() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public interface InterfaceType {
|
||||
|
||||
default Object someDefaultMethod() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.types;
|
||||
|
||||
import org.springframework.data.geo.Point;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public interface LocationHolder {
|
||||
|
||||
Point getLocation();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public interface ProjectionInterface {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class TypesInMethodSignatures {
|
||||
|
||||
TypesInMethodSignatures(String ctorArg) {
|
||||
|
||||
}
|
||||
|
||||
Long returnValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void voidReturn() {
|
||||
|
||||
}
|
||||
|
||||
EmptyType1 aDomainType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void setSomething(EmptyType2 something) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Object methodArg(Integer methodArg) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2021 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.types;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class WithDeclaredClass {
|
||||
|
||||
public enum SomeEnum {};
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2022 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.repository.config;
|
||||
|
||||
import org.springframework.data.repository.core.support.DummyRepositoryFactoryBean;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2022/04
|
||||
*/
|
||||
class DummyConfigurationExtension extends RepositoryConfigurationExtensionSupport {
|
||||
|
||||
public String getRepositoryFactoryBeanClassName() {
|
||||
return DummyRepositoryFactoryBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModulePrefix() {
|
||||
return "commons";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2022 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.repository.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2022/04
|
||||
*/
|
||||
class DummyRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
|
||||
|
||||
DummyRegistrar() {
|
||||
setResourceLoader(new DefaultResourceLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableRepositories.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getExtension() {
|
||||
return new DummyConfigurationExtension();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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.repository.config;
|
||||
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.repository.core.support.ReactiveDummyRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.reactive.ReactiveSortingRepository;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Import(ReactiveDummyRegistrar.class)
|
||||
@Inherited
|
||||
public @interface EnableReactiveRepositories {
|
||||
|
||||
String[] value() default {};
|
||||
|
||||
String[] basePackages() default {};
|
||||
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
Filter[] includeFilters() default {};
|
||||
|
||||
Filter[] excludeFilters() default {};
|
||||
|
||||
Class<?> repositoryFactoryBeanClass() default ReactiveDummyRepositoryFactoryBean.class;
|
||||
|
||||
Class<?> repositoryBaseClass() default ReactiveSortingRepository.class;
|
||||
|
||||
String namedQueriesLocation() default "";
|
||||
|
||||
String repositoryImplementationPostfix() default "Impl";
|
||||
|
||||
boolean considerNestedRepositories() default false;
|
||||
|
||||
boolean limitImplementationBasePackages() default true;
|
||||
|
||||
BootstrapMode bootstrapMode() default BootstrapMode.DEFAULT;
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupportUnitTests.DummyRegistrar;
|
||||
import org.springframework.data.repository.core.support.DummyRepositoryFactoryBean;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2022 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.repository.config;
|
||||
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.ReactiveDummyRepositoryFactoryBean;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2022/04
|
||||
*/
|
||||
class ReactiveDummyConfigurationExtension extends RepositoryConfigurationExtensionSupport {
|
||||
|
||||
public String getRepositoryFactoryBeanClassName() {
|
||||
return ReactiveDummyRepositoryFactoryBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModulePrefix() {
|
||||
return "commons";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useRepositoryConfiguration(RepositoryMetadata metadata) {
|
||||
if(metadata.isReactiveRepository()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2022 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.repository.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2022/04
|
||||
*/
|
||||
class ReactiveDummyRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
|
||||
|
||||
ReactiveDummyRegistrar() {
|
||||
setResourceLoader(new DefaultResourceLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableReactiveRepositories.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getExtension() {
|
||||
return new ReactiveDummyConfigurationExtension();
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupportUnitTests.DummyConfigurationExtension;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.springframework.data.repository.config;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -33,7 +31,6 @@ import org.springframework.context.annotation.AnnotationBeanNameGenerator;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
import org.springframework.data.mapping.Person;
|
||||
|
||||
@@ -110,7 +110,7 @@ class RepositoryConfigurationExtensionSupportUnitTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Annotation>> getIdentifyingAnnotations() {
|
||||
public Collection<Class<? extends Annotation>> getIdentifyingAnnotations() {
|
||||
return Collections.singleton(Primary.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.repository.core.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.repository.core.CrudMethods;
|
||||
@@ -103,4 +104,9 @@ public final class DummyRepositoryInformation implements RepositoryInformation {
|
||||
public boolean isReactiveRepository() {
|
||||
return metadata.isReactiveRepository();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RepositoryFragment<?>> getFragments() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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.repository.core.support;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.metrics.ApplicationStartup;
|
||||
import org.springframework.core.metrics.StartupStep;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
|
||||
/**
|
||||
* Dummy implementation for {@link RepositoryFactorySupport} that is equipped with mocks to simulate behavior for test
|
||||
* cases.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class ReactiveDummyRepositoryFactory extends ReactiveRepositoryFactorySupport {
|
||||
|
||||
public final MyRepositoryQuery queryOne = mock(MyRepositoryQuery.class);
|
||||
public final RepositoryQuery queryTwo = mock(RepositoryQuery.class);
|
||||
public final QueryLookupStrategy strategy = mock(QueryLookupStrategy.class);
|
||||
|
||||
private final ApplicationStartup applicationStartup;
|
||||
|
||||
@SuppressWarnings("unchecked") private final QuerydslPredicateExecutor<Object> querydsl = mock(
|
||||
QuerydslPredicateExecutor.class);
|
||||
private final Object repository;
|
||||
|
||||
public ReactiveDummyRepositoryFactory(Object repository) {
|
||||
|
||||
this.repository = repository;
|
||||
|
||||
when(strategy.resolveQuery(Mockito.any(Method.class), Mockito.any(RepositoryMetadata.class),
|
||||
Mockito.any(ProjectionFactory.class), Mockito.any(NamedQueries.class))).thenReturn(queryOne);
|
||||
|
||||
this.applicationStartup = mock(ApplicationStartup.class);
|
||||
var startupStep = mock(StartupStep.class);
|
||||
when(applicationStartup.start(anyString())).thenReturn(startupStep);
|
||||
when(startupStep.tag(anyString(), anyString())).thenReturn(startupStep);
|
||||
when(startupStep.tag(anyString(), ArgumentMatchers.<Supplier<String>> any())).thenReturn(startupStep);
|
||||
|
||||
var beanFactory = Mockito.mock(BeanFactory.class);
|
||||
when(beanFactory.getBean(ApplicationStartup.class)).thenReturn(applicationStartup);
|
||||
setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID> EntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return mock(EntityInformation.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getTargetRepository(RepositoryInformation information) {
|
||||
return repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
return repository.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(Key key,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
return Optional.of(strategy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
|
||||
|
||||
var fragments = super.getRepositoryFragments(metadata);
|
||||
|
||||
return QuerydslPredicateExecutor.class.isAssignableFrom(metadata.getRepositoryInterface()) //
|
||||
? fragments.append(RepositoryFragments.just(querydsl)) //
|
||||
: fragments;
|
||||
}
|
||||
|
||||
ApplicationStartup getApplicationStartup() {
|
||||
return this.applicationStartup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface MyRepositoryQuery extends RepositoryQuery {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2012-2022 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.repository.core.support;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.data.mapping.context.SampleMappingContext;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ReactiveDummyRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
|
||||
extends RepositoryFactoryBeanSupport<T, S, ID> {
|
||||
|
||||
private final T repository;
|
||||
|
||||
public ReactiveDummyRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
|
||||
|
||||
super(repositoryInterface);
|
||||
|
||||
this.repository = mock(repositoryInterface);
|
||||
setMappingContext(new SampleMappingContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryFactorySupport createRepositoryFactory() {
|
||||
return new ReactiveDummyRepositoryFactory(repository);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user