From 9e8abf07feb40a2b5418ffa8db28378121ea38e7 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Wed, 28 Oct 2020 22:41:36 +0100 Subject: [PATCH] #1387 - Proper type resolution for CollectionModel post-processing. CollectionModelProcessorWrapper erroneously returned a raw type in case a CollectionModel type assignment check failed which rendered the element type verification to always match as it's effectively compared against Object. We're now returning null to rather proceed with the next candidate type. Original ticket: #1379. --- .../RepresentationModelProcessorInvoker.java | 3 +- ...ntationModelProcessorInvokerUnitTests.java | 53 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/hateoas/server/mvc/RepresentationModelProcessorInvoker.java b/src/main/java/org/springframework/hateoas/server/mvc/RepresentationModelProcessorInvoker.java index f85316b1..4b967e72 100644 --- a/src/main/java/org/springframework/hateoas/server/mvc/RepresentationModelProcessorInvoker.java +++ b/src/main/java/org/springframework/hateoas/server/mvc/RepresentationModelProcessorInvoker.java @@ -430,6 +430,7 @@ public class RepresentationModelProcessorInvoker { * @param superType must not be {@literal null}. * @return */ + @Nullable private static ResolvableType getSuperType(ResolvableType source, Class superType) { Class rawType = source.getRawClass(); @@ -450,7 +451,7 @@ public class RepresentationModelProcessorInvoker { } } - return ResolvableType.forClass(superType); + return null; } } diff --git a/src/test/java/org/springframework/hateoas/server/mvc/RepresentationModelProcessorInvokerUnitTests.java b/src/test/java/org/springframework/hateoas/server/mvc/RepresentationModelProcessorInvokerUnitTests.java index ba0a84ac..8d0af63c 100644 --- a/src/test/java/org/springframework/hateoas/server/mvc/RepresentationModelProcessorInvokerUnitTests.java +++ b/src/test/java/org/springframework/hateoas/server/mvc/RepresentationModelProcessorInvokerUnitTests.java @@ -15,12 +15,14 @@ */ package org.springframework.hateoas.server.mvc; +import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; import java.util.Collections; import org.junit.jupiter.api.Test; import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.RepresentationModel; import org.springframework.hateoas.server.RepresentationModelProcessor; @@ -28,6 +30,7 @@ import org.springframework.hateoas.server.RepresentationModelProcessor; * Unit tests for {@link RepresentationModelProcessorInvoker}. * * @author Oliver Drotbohm + * @author Karina Pleskach */ public class RepresentationModelProcessorInvokerUnitTests { @@ -41,6 +44,33 @@ public class RepresentationModelProcessorInvokerUnitTests { .doesNotThrowAnyException(); } + @Test // #1379 + void doesNotInvokeProcessorForNonAssignableNestedEntity() { + + FirstEntityProcessor processor = new FirstEntityProcessor(); + RepresentationModelProcessorInvoker invoker = new RepresentationModelProcessorInvoker( + singletonList(processor)); + + EntityModel entityModel = EntityModel.of(new SecondEntity()); + invoker.invokeProcessorsFor(CollectionModel.of(singleton(entityModel))); + + assertThat(processor.invoked).isFalse(); + } + + @Test // #1379 + void doesNotInvokeProcessorForNonAssignableNestedEntityOnSpecializedCollectionModel() { + + FirstEntityProcessor firstProcessor = new FirstEntityProcessor(); + + RepresentationModelProcessorInvoker invoker = new RepresentationModelProcessorInvoker( + singletonList(firstProcessor)); + + EntityModel entityModel = EntityModel.of(new SecondEntity()); + invoker.invokeProcessorsFor(new MyCollectionModelInheritor<>(singletonList(entityModel))); + + assertThat(firstProcessor.invoked).isFalse(); + } + // #1280 static class GenericPostProcessor> implements RepresentationModelProcessor { @@ -52,4 +82,27 @@ public class RepresentationModelProcessorInvokerUnitTests { } static class GenericModel> extends RepresentationModel {} + + static class FirstEntity {} + + static class SecondEntity {}; + + static class FirstEntityProcessor implements RepresentationModelProcessor>> { + + boolean invoked = false; + + @Override + public CollectionModel> process(CollectionModel> model) { + + invoked = true; + + return model; + } + } + + static class MyCollectionModelInheritor extends CollectionModel { + public MyCollectionModelInheritor(Iterable content) { + super(content); + } + } }