#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.
This commit is contained in:
Oliver Drotbohm
2020-10-28 22:41:36 +01:00
parent 02a387244b
commit 9e8abf07fe
2 changed files with 55 additions and 1 deletions

View File

@@ -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;
}
}

View File

@@ -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<SecondEntity> 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<SecondEntity> entityModel = EntityModel.of(new SecondEntity());
invoker.invokeProcessorsFor(new MyCollectionModelInheritor<>(singletonList(entityModel)));
assertThat(firstProcessor.invoked).isFalse();
}
// #1280
static class GenericPostProcessor<T extends GenericModel<T>> implements RepresentationModelProcessor<T> {
@@ -52,4 +82,27 @@ public class RepresentationModelProcessorInvokerUnitTests {
}
static class GenericModel<T extends RepresentationModel<T>> extends RepresentationModel<T> {}
static class FirstEntity {}
static class SecondEntity {};
static class FirstEntityProcessor implements RepresentationModelProcessor<CollectionModel<EntityModel<FirstEntity>>> {
boolean invoked = false;
@Override
public CollectionModel<EntityModel<FirstEntity>> process(CollectionModel<EntityModel<FirstEntity>> model) {
invoked = true;
return model;
}
}
static class MyCollectionModelInheritor<T> extends CollectionModel<T> {
public MyCollectionModelInheritor(Iterable<T> content) {
super(content);
}
}
}