From 74cc5551a5acf730cac017e49d054dceec5f1f96 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 24 Jan 2017 16:46:33 +0100 Subject: [PATCH] DATAREST-983 - AnnotatedEventHandlerInvoker now resolves generic handler method argument. We now resolve the handler method argument type of an annotated repository event handler against the concrete handler type to make sure generics are resolved properly. --- .../event/AnnotatedEventHandlerInvoker.java | 8 ++-- ...AnnotatedEventHandlerInvokerUnitTests.java | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvoker.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvoker.java index dd612b47c..0c2cedf97 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvoker.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvoker.java @@ -31,6 +31,7 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; +import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.rest.core.annotation.HandleAfterCreate; @@ -165,13 +166,12 @@ public class AnnotatedEventHandlerInvoker implements ApplicationListener[] parameterTypes = method.getParameterTypes(); - - if (parameterTypes.length == 0) { + if (method.getParameterCount() == 0) { throw new IllegalStateException(String.format(PARAMETER_MISSING, method)); } - EventHandlerMethod handlerMethod = EventHandlerMethod.of(parameterTypes[0], handler, method); + ResolvableType parameter = ResolvableType.forMethodParameter(method, 0, handler.getClass()); + EventHandlerMethod handlerMethod = EventHandlerMethod.of(parameter.resolve(), handler, method); if (LOG.isDebugEnabled()) { LOG.debug("Annotated handler method found: {}", handlerMethod); diff --git a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvokerUnitTests.java b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvokerUnitTests.java index dc6cb6647..bb671347d 100644 --- a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvokerUnitTests.java +++ b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvokerUnitTests.java @@ -85,6 +85,23 @@ public class AnnotatedEventHandlerInvokerUnitTests { assertThat(orderHandler1.timestamp, is(greaterThan(orderHandler2.timestamp))); } + @Test // DATAREST-983 + public void invokesEventHandlerOnParentClass() { + + FirstEventHandler firstHandler = new FirstEventHandler(); + SecondEventHandler secondHandler = new SecondEventHandler(); + + AnnotatedEventHandlerInvoker invoker = new AnnotatedEventHandlerInvoker(); + invoker.postProcessAfterInitialization(firstHandler, "firstHandler"); + invoker.postProcessAfterInitialization(secondHandler, "secondHandler"); + + invoker.onApplicationEvent(new BeforeCreateEvent(new FirstEntity())); + invoker.onApplicationEvent(new BeforeCreateEvent(new SecondEntity())); + + assertThat(firstHandler.callCount, is(1)); + assertThat(secondHandler.callCount, is(1)); + } + @RepositoryEventHandler static class Sample { @@ -130,4 +147,27 @@ public class AnnotatedEventHandlerInvokerUnitTests { timestamp = System.nanoTime(); } } + + // DATAREST-983 + + static class AbstractBaseEntityEventHandler { + int callCount = 0; + + @HandleBeforeCreate + private void method(T entity) { + callCount += 1; + } + } + + @RepositoryEventHandler + static class FirstEventHandler extends AbstractBaseEntityEventHandler {} + + @RepositoryEventHandler + static class SecondEventHandler extends AbstractBaseEntityEventHandler {} + + static abstract class BaseEntity {} + + static class FirstEntity extends BaseEntity {} + + static class SecondEntity extends BaseEntity {} }