Improve error message if store module doesn't support a well-known fragment interface.
We now throw a RepositoryCreationException (or subclass) when a repository cannot be created due to a missing fragment, a fragment without implementation or if a well-known fragment is not supported by the repository factory. Throw QueryCreationException if QueryExecutorMethodInterceptor cannot resolve a RepositoryQuery. Closes #2341 Original pull request: #2342.
This commit is contained in:
@@ -136,16 +136,17 @@ class RepositoryCompositionUnitTests {
|
||||
assertThat(barFoo.invoke(barFoo.findMethod(getString).get())).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test // DATACMNS-102
|
||||
@Test // DATACMNS-102, GH-2341
|
||||
void shouldValidateStructuralFragments() {
|
||||
|
||||
RepositoryComposition mixed = RepositoryComposition.of(RepositoryFragment.structural(QueryByExampleExecutor.class),
|
||||
RepositoryFragment.implemented(backingRepo));
|
||||
|
||||
assertThatIllegalStateException() //
|
||||
assertThatExceptionOfType(FragmentNotImplementedException.class) //
|
||||
.isThrownBy(mixed::validateImplementation) //
|
||||
.withMessageContaining(
|
||||
"Fragment org.springframework.data.repository.query.QueryByExampleExecutor has no implementation.");
|
||||
"Fragment org.springframework.data.repository.query.QueryByExampleExecutor")
|
||||
.withMessageContaining("has no implementation");
|
||||
}
|
||||
|
||||
@Test // DATACMNS-102
|
||||
|
||||
@@ -51,6 +51,7 @@ import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.RepositoryDefinition;
|
||||
@@ -61,7 +62,13 @@ import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
|
||||
import org.springframework.data.repository.core.support.RepositoryMethodInvocationListener.RepositoryMethodInvocation;
|
||||
import org.springframework.data.repository.core.support.RepositoryMethodInvocationListener.RepositoryMethodInvocationResult.State;
|
||||
import org.springframework.data.repository.query.QueryByExampleExecutor;
|
||||
import org.springframework.data.repository.query.QueryCreationException;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.data.repository.sample.User;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@@ -422,6 +429,49 @@ class RepositoryFactorySupportUnitTests {
|
||||
orderedInvocation.verify(startup).start("spring.data.repository.proxy");
|
||||
}
|
||||
|
||||
@Test // GH-2341
|
||||
void dummyRepositoryShouldsupportQuerydsl() {
|
||||
factory.getRepository(WithQuerydsl.class, backingRepo);
|
||||
}
|
||||
|
||||
@Test // GH-2341
|
||||
void dummyRepositoryNotSupportingReactiveQuerydslShouldRaiseException() {
|
||||
assertThatThrownBy(() -> factory.getRepository(WithReactiveQuerydsl.class, backingRepo))
|
||||
.isInstanceOf(UnsupportedFragmentException.class).hasMessage(
|
||||
"Repository org.springframework.data.repository.core.support.RepositoryFactorySupportUnitTests$WithReactiveQuerydsl implements org.springframework.data.repository.query.ReactiveQueryByExampleExecutor but DummyRepositoryFactory does not support Reactive Query by Example!");
|
||||
}
|
||||
|
||||
@Test // GH-2341
|
||||
void dummyRepositoryNotSupportingQbeShouldRaiseException() {
|
||||
assertThatThrownBy(() -> factory.getRepository(WithQbe.class, backingRepo))
|
||||
.hasMessageContaining("does not support Query by Example");
|
||||
}
|
||||
|
||||
@Test // GH-2341
|
||||
void dummyRepositoryNotSupportingReactiveQbeShouldRaiseException() {
|
||||
assertThatThrownBy(() -> factory.getRepository(WithReactiveQbe.class, backingRepo))
|
||||
.hasMessageContaining("does not support Reactive Query by Example");
|
||||
}
|
||||
|
||||
@Test // GH-2341
|
||||
void derivedQueryMethodCannotBeImplemented() {
|
||||
|
||||
DummyRepositoryFactory factory = new DummyRepositoryFactory(backingRepo) {
|
||||
@Override
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
return Optional.of((method, metadata, factory, namedQueries) -> {
|
||||
new PartTree(method.getName(), method.getReturnType());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
assertThatThrownBy(() -> factory.getRepository(WithQueryMethodUsingInvalidProperty.class))
|
||||
.isInstanceOf(QueryCreationException.class).hasMessageContaining("findAllByName")
|
||||
.hasMessageContaining("No property name found for type Object");
|
||||
}
|
||||
|
||||
private ConvertingRepository prepareConvertingRepository(final Object expectedValue) {
|
||||
|
||||
when(factory.queryOne.execute(any(Object[].class))).then(invocation -> {
|
||||
@@ -543,4 +593,27 @@ class RepositoryFactorySupportUnitTests {
|
||||
|
||||
CustomRepositoryBaseClass(EntityInformation<?, ?> information) {}
|
||||
}
|
||||
|
||||
interface WithQuerydsl extends Repository<Object, Long>, QuerydslPredicateExecutor<Object> {
|
||||
|
||||
}
|
||||
|
||||
interface WithReactiveQuerydsl extends Repository<Object, Long>, ReactiveQueryByExampleExecutor<Object> {
|
||||
|
||||
}
|
||||
|
||||
interface WithQbe extends Repository<Object, Long>, QueryByExampleExecutor<Object> {
|
||||
|
||||
}
|
||||
|
||||
interface WithReactiveQbe extends Repository<Object, Long>, ReactiveQueryByExampleExecutor<Object> {
|
||||
|
||||
}
|
||||
|
||||
interface WithQueryMethodUsingInvalidProperty extends Repository<Object, Long> {
|
||||
|
||||
Object findAllByName();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user