From 26b1a182274c242b7f41f38e78bfc9b6d1b21597 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 c060e6858..ece74e393 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 @@ -91,6 +91,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 { @@ -136,4 +153,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 {} }