DATACMNS-1763 - Allow registration of QueryMethod invocation listeners.
We now allow for registering RepositoryMethodInvocationListeners to notify listeners upon repository method invocations (query methods and repository fragments). Listeners are notified upon method completion reporting the repository interface, the invoked methods, duration, outcome and arguments. Original Pull Request: #455
This commit is contained in:
committed by
Christoph Strobl
parent
d840057b0c
commit
e77947f0a5
@@ -50,14 +50,14 @@ class QueryExecutorMethodInterceptorUnitTests {
|
||||
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> new QueryExecutorMethodInterceptor(information, new SpelAwareProxyProjectionFactory(),
|
||||
Optional.empty(), PropertiesBasedNamedQueries.EMPTY, Collections.emptyList()));
|
||||
Optional.empty(), PropertiesBasedNamedQueries.EMPTY, Collections.emptyList(), Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1508
|
||||
void skipsQueryLookupsIfQueryLookupStrategyIsNotPresent() {
|
||||
|
||||
new QueryExecutorMethodInterceptor(information, new SpelAwareProxyProjectionFactory(), Optional.empty(),
|
||||
PropertiesBasedNamedQueries.EMPTY, Collections.emptyList());
|
||||
PropertiesBasedNamedQueries.EMPTY, Collections.emptyList(), Collections.emptyList());
|
||||
|
||||
verify(strategy, times(0)).resolveQuery(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@@ -29,10 +29,12 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
@@ -86,6 +88,7 @@ class RepositoryFactorySupportUnitTests {
|
||||
@Mock PlainQueryCreationListener otherListener;
|
||||
|
||||
@Mock RepositoryProxyPostProcessor repositoryPostProcessor;
|
||||
@Mock RepositoryMethodInvocationListener invocationListener;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
@@ -118,13 +121,16 @@ class RepositoryFactorySupportUnitTests {
|
||||
verify(repositoryPostProcessor, times(1)).postProcess(any(ProxyFactory.class), any(RepositoryInformation.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test // DATACMNS-1764
|
||||
void routesCallToRedeclaredMethodIntoTarget() {
|
||||
|
||||
factory.addInvocationListener(invocationListener);
|
||||
|
||||
ObjectRepository repository = factory.getRepository(ObjectRepository.class);
|
||||
repository.save(repository);
|
||||
|
||||
verify(backingRepo, times(1)).save(any(Object.class));
|
||||
verify(invocationListener).afterInvocation(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -177,7 +183,7 @@ class RepositoryFactorySupportUnitTests {
|
||||
assertThat(ReflectionTestUtils.getField(factory, "classLoader")).isEqualTo(ClassUtils.getDefaultClassLoader());
|
||||
}
|
||||
|
||||
@Test // DATACMNS-489
|
||||
@Test // DATACMNS-489, DATACMNS-1764
|
||||
void wrapsExecutionResultIntoFutureIfConfigured() throws Exception {
|
||||
|
||||
final Object reference = new Object();
|
||||
@@ -187,6 +193,8 @@ class RepositoryFactorySupportUnitTests {
|
||||
return reference;
|
||||
});
|
||||
|
||||
factory.addInvocationListener(invocationListener);
|
||||
|
||||
ConvertingRepository repository = factory.getRepository(ConvertingRepository.class);
|
||||
|
||||
AsyncAnnotationBeanPostProcessor processor = new AsyncAnnotationBeanPostProcessor();
|
||||
@@ -204,13 +212,44 @@ class RepositoryFactorySupportUnitTests {
|
||||
assertThat(future.get()).isEqualTo(reference);
|
||||
|
||||
verify(factory.queryOne, times(1)).execute(any(Object[].class));
|
||||
|
||||
ArgumentCaptor<RepositoryMethodInvocationListener.Invocation> captor = ArgumentCaptor
|
||||
.forClass(RepositoryMethodInvocationListener.Invocation.class);
|
||||
verify(invocationListener).afterInvocation(captor.capture());
|
||||
|
||||
RepositoryMethodInvocationListener.Invocation value = captor.getValue();
|
||||
assertThat(value.getResult()).isEqualTo(reference);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-509
|
||||
@Test // DATACMNS-1764, DATACMNS-1764
|
||||
void capturesFailureFromInvocation() {
|
||||
|
||||
when(factory.queryOne.execute(any(Object[].class))).thenThrow(new IllegalStateException());
|
||||
|
||||
factory.addInvocationListener(invocationListener);
|
||||
|
||||
ConvertingRepository repository = factory.getRepository(ConvertingRepository.class);
|
||||
|
||||
try {
|
||||
repository.findByLastname("Foo");
|
||||
fail("Missing exception");
|
||||
} catch (IllegalStateException e) {}
|
||||
|
||||
ArgumentCaptor<RepositoryMethodInvocationListener.Invocation> captor = ArgumentCaptor
|
||||
.forClass(RepositoryMethodInvocationListener.Invocation.class);
|
||||
verify(invocationListener).afterInvocation(captor.capture());
|
||||
|
||||
RepositoryMethodInvocationListener.Invocation invocation = captor.getValue();
|
||||
assertThat(invocation.getDuration(TimeUnit.NANOSECONDS)).isGreaterThan(0);
|
||||
assertThat(invocation.getException()).isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-509, DATACMNS-1764
|
||||
void convertsWithSameElementType() {
|
||||
|
||||
List<String> names = singletonList("Dave");
|
||||
|
||||
factory.addInvocationListener(invocationListener);
|
||||
when(factory.queryOne.execute(any(Object[].class))).thenReturn(names);
|
||||
|
||||
ConvertingRepository repository = factory.getRepository(ConvertingRepository.class);
|
||||
@@ -218,6 +257,13 @@ class RepositoryFactorySupportUnitTests {
|
||||
|
||||
assertThat(result).hasSize(1);
|
||||
assertThat(result.iterator().next()).isEqualTo("Dave");
|
||||
|
||||
ArgumentCaptor<RepositoryMethodInvocationListener.Invocation> captor = ArgumentCaptor
|
||||
.forClass(RepositoryMethodInvocationListener.Invocation.class);
|
||||
verify(invocationListener).afterInvocation(captor.capture());
|
||||
|
||||
RepositoryMethodInvocationListener.Invocation value = captor.getValue();
|
||||
assertThat(value.getResult()).isEqualTo(names);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-509
|
||||
@@ -461,6 +507,8 @@ class RepositoryFactorySupportUnitTests {
|
||||
|
||||
Set<Object> convertListToObjectSet();
|
||||
|
||||
Future<Object> findByLastname(String lastname);
|
||||
|
||||
@Async
|
||||
Future<Object> findByFirstname(String firstname);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user