DATACMNS-1764 - Polishing.

Move Publisher decoration into its own type to avoid a static reference to Publisher. Fix imperative repository MethodLookups.

Original Pull Request: #455.
This commit is contained in:
Mark Paluch
2020-08-11 14:53:28 +02:00
parent b667dfa779
commit 01e394b913
2 changed files with 47 additions and 43 deletions

View File

@@ -139,7 +139,7 @@ public class RepositoryComposition {
REACTIVE_ARGS_CONVERTER);
}
return new RepositoryComposition(metadata, RepositoryFragments.empty(), MethodLookups.direct(),
return new RepositoryComposition(metadata, RepositoryFragments.empty(), MethodLookups.forRepositoryTypes(metadata),
PASSTHRU_ARG_CONVERTER);
}
@@ -480,11 +480,8 @@ public class RepositoryComposition {
/**
* Invoke {@link Method} by resolving the fragment that implements a suitable method.
*
* @param repositoryInformation
* @param listener
* @param invokedMethod invoked method as per invocation on the interface.
* @param methodToCall backend method that is backing the call.
* @param args
* @return
* @throws Throwable
*/
@@ -496,8 +493,7 @@ public class RepositoryComposition {
/**
* Invoke {@link Method} by resolving the fragment that implements a suitable method.
*
* @param listener
* @param repositoryInformation
* @param repositoryInterface
* @param listener
* @param invokedMethod invoked method as per invocation on the interface.
* @param methodToCall backend method that is backing the call.

View File

@@ -135,7 +135,7 @@ abstract class RepositoryMethodInvoker {
Object result = invokable.invoke(args);
if (result != null && ReactiveWrappers.supports(result.getClass())) {
return inferReactiveInvocationCallbacks(repositoryInterface, multicaster, args, result);
return new ReactiveInvocationListenerDecorator().decorate(repositoryInterface, multicaster, args, result);
}
if (result instanceof Stream) {
@@ -169,7 +169,7 @@ abstract class RepositoryMethodInvoker {
.captureInvocationOn(repositoryInterface);
try {
Publisher<?> result = inferReactiveInvocationCallbacks(repositoryInterface, multicaster, args,
Publisher<?> result = new ReactiveInvocationListenerDecorator().decorate(repositoryInterface, multicaster, args,
invokable.invoke(args));
if (returnsReactiveType) {
@@ -188,42 +188,7 @@ abstract class RepositoryMethodInvoker {
captured.getDuration());
}
private Publisher<Object> inferReactiveInvocationCallbacks(Class<?> repositoryInterface,
RepositoryInvocationMulticaster multicaster, Object[] args, Object result) {
if (result instanceof Mono) {
return Mono.usingWhen(
Mono.fromSupplier(() -> RepositoryMethodInvocationCaptor.captureInvocationOn(repositoryInterface)), it -> {
it.trackStart();
return ReactiveWrapperConverters.toWrapper(result, Mono.class);
}, it -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.success()));
return Mono.empty();
}, (it, e) -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.error(e)));
return Mono.empty();
}, it -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.canceled()));
return Mono.empty();
});
}
return Flux.usingWhen(
Mono.fromSupplier(() -> RepositoryMethodInvocationCaptor.captureInvocationOn(repositoryInterface)), it -> {
it.trackStart();
return result instanceof Publisher ? (Publisher<?>) result
: ReactiveWrapperConverters.toWrapper(result, Publisher.class);
}, it -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.success()));
return Mono.empty();
}, (it, e) -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.error(e)));
return Mono.empty();
}, it -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.canceled()));
return Mono.empty();
});
}
interface Invokable {
@@ -240,6 +205,49 @@ abstract class RepositoryMethodInvoker {
}
}
/**
* Delegate to decorate {@link Publisher} invocations with {@link RepositoryInvocationMulticaster} callbacks.
*/
class ReactiveInvocationListenerDecorator {
Publisher<Object> decorate(Class<?> repositoryInterface, RepositoryInvocationMulticaster multicaster, Object[] args,
Object result) {
if (result instanceof Mono) {
return Mono.usingWhen(
Mono.fromSupplier(() -> RepositoryMethodInvocationCaptor.captureInvocationOn(repositoryInterface)), it -> {
it.trackStart();
return ReactiveWrapperConverters.toWrapper(result, Mono.class);
}, it -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.success()));
return Mono.empty();
}, (it, e) -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.error(e)));
return Mono.empty();
}, it -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.canceled()));
return Mono.empty();
});
}
return Flux.usingWhen(
Mono.fromSupplier(() -> RepositoryMethodInvocationCaptor.captureInvocationOn(repositoryInterface)), it -> {
it.trackStart();
return result instanceof Publisher ? (Publisher<?>) result
: ReactiveWrapperConverters.toWrapper(result, Publisher.class);
}, it -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.success()));
return Mono.empty();
}, (it, e) -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.error(e)));
return Mono.empty();
}, it -> {
multicaster.notifyListeners(method, args, computeInvocationResult(it.canceled()));
return Mono.empty();
});
}
}
/**
* Implementation to invoke fragment methods.
*/