DATACMNS-1289 - Allow fragment creation only from implementations that implement their declared class.

We now check that fragment implementations created via RepositoryFragment.implemented(Class<T>, T) are a subtype of the given class. This assertion raises an exception that prevents errors during runtime.

This change addresses an issue with customized intermediate base repositories in combination with ambiguous naming of implementations. Method invocations fail if a repository derives from a customized base repository interface that implements e.g. CrudRepository and there's an implementation matching the base repository name followed by the implementation suffix. We assume in that case, the implementation contains implementations of the methods declared in the customized base interface.

Original pull request: #280.
This commit is contained in:
Mark Paluch
2018-04-05 15:27:50 +02:00
committed by Oliver Gierke
parent d8a1c2cfde
commit 142c9ddb5c
2 changed files with 66 additions and 3 deletions

View File

@@ -155,12 +155,27 @@ public interface RepositoryFragment<T> {
}
}
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = false)
static class ImplementedRepositoryFragment<T> implements RepositoryFragment<T> {
private final @NonNull Optional<Class<T>> interfaceClass;
private final @NonNull T implementation;
private final Optional<Class<T>> interfaceClass;
private final T implementation;
public ImplementedRepositoryFragment(Optional<Class<T>> interfaceClass, T implementation) {
Assert.notNull(interfaceClass, "Interface class must not be null!");
Assert.notNull(implementation, "Implementation object must not be null!");
interfaceClass.ifPresent(it -> {
Assert.isTrue(ClassUtils.isAssignableValue(it, implementation),
() -> String.format("Fragment implementation %s does not implement %s!", ClassUtils.getQualifiedName(it),
ClassUtils.getQualifiedName(implementation.getClass())));
});
this.interfaceClass = interfaceClass;
this.implementation = implementation;
}
/*
* (non-Javadoc)