diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandler.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandler.java index a4ca4b697..50a6ec29a 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandler.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandler.java @@ -386,7 +386,7 @@ public class ResourceProcessorHandlerMethodReturnValueHandler implements Handler * * @author Oliver Gierke */ - private static class ResourcesProcessorWrapper extends DefaultProcessorWrapper { + static class ResourcesProcessorWrapper extends DefaultProcessorWrapper { /** * Creates a new {@link ResourcesProcessorWrapper} for the given {@link ResourceProcessor}. @@ -419,9 +419,9 @@ public class ResourceProcessorHandlerMethodReturnValueHandler implements Handler * @param target that target {@link TypeInformation}. * @return */ - private static boolean isValueTypeMatch(Resources resources, TypeInformation target) { + static boolean isValueTypeMatch(Resources resources, TypeInformation target) { - if (resources == null || !Resources.class.equals(resources.getClass())) { + if (resources == null) { return false; } @@ -437,7 +437,9 @@ public class ResourceProcessorHandlerMethodReturnValueHandler implements Handler return false; } - TypeInformation resourceTypeInformation = target.getSuperTypeInformation(Resources.class).getComponentType(); + Class resourcesType = resources.getClass(); + + TypeInformation resourceTypeInformation = target.getSuperTypeInformation(resourcesType).getComponentType(); return ResourceProcessorWrapper.isValueTypeMatch((Resource) element, resourceTypeInformation); } } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandlerUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandlerUnitTests.java index 012a4122e..8a8a4a21e 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandlerUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandlerUnitTests.java @@ -36,8 +36,15 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.core.MethodParameter; +import org.springframework.data.rest.core.projection.ProxyProjectionFactory; +import org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler.ResourcesProcessorWrapper; +import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.TypeInformation; import org.springframework.hateoas.Link; +import org.springframework.hateoas.PagedResources; +import org.springframework.hateoas.PagedResources.PageMetadata; import org.springframework.hateoas.Resource; import org.springframework.hateoas.ResourceProcessor; import org.springframework.hateoas.Resources; @@ -61,6 +68,8 @@ public class ResourceProcessorHandlerMethodReturnValueHandlerUnitTests { static final Resource FOO = new Resource("foo"); static final Resources> FOOS = new Resources>(Collections.singletonList(FOO)); + static final PagedResources> FOO_PAGE = new PagedResources>( + Collections.singleton(FOO), new PageMetadata(1, 0, 10)); static final StringResource FOO_RES = new StringResource("foo"); static final HttpEntity> FOO_ENTITY = new HttpEntity>(FOO); static final ResponseEntity> FOO_RESP_ENTITY = new ResponseEntity>(FOO, @@ -205,6 +214,33 @@ public class ResourceProcessorHandlerMethodReturnValueHandlerUnitTests { Mockito.any(ModelAndViewContainer.class), Mockito.any(NativeWebRequest.class)); } + /** + * @see DATAREST-331 + */ + @Test + public void resourcesProcessorMatchesValueSubTypes() { + + TypeInformation type = ClassTypeInformation.from(PagedStringResources.class); + assertThat(ResourcesProcessorWrapper.isValueTypeMatch(FOO_PAGE, type), is(true)); + } + + /** + * @see DATAREST-331 + */ + @Test + public void invokesProcessorsForProjection() throws Exception { + + ProjectionProcessor projectionProcessor = new ProjectionProcessor(); + resourceProcessors.add(projectionProcessor); + + ProxyProjectionFactory factory = new ProxyProjectionFactory(new DefaultListableBeanFactory()); + SampleProjection projection = factory.createProjection(new Sample(), SampleProjection.class); + Resource resource = new Resource(projection); + + invokeReturnValueHandler("object", is(resource), resource); + assertThat(projectionProcessor.invoked, is(true)); + } + // Helpers ---------------------------------------------------------// private void invokeReturnValueHandler(String method, final Matcher matcher, Object returnValue) throws Exception { final MethodParameter methodParam = METHOD_PARAMS.get(method); @@ -317,4 +353,25 @@ public class ResourceProcessorHandlerMethodReturnValueHandlerUnitTests { } } + static class PagedStringResources extends PagedResources> {}; + + static class Sample { + + } + + static interface SampleProjection { + + } + + static class ProjectionProcessor implements ResourceProcessor> { + + boolean invoked = false; + + @Override + public Resource process(Resource resource) { + + this.invoked = true; + return resource; + } + } }