Browse Source

Fix `StackOverflowError` in TypeDiscoverer comparison.

We now resort to String-based comparison if a generic cannot be resolved. Previously, unresolved generics caused an infinite recursion.

Closes #3084
3.2.x
Mark Paluch 2 years ago
parent
commit
289e4d1f52
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 6
      src/main/java/org/springframework/data/util/TypeDiscoverer.java
  2. 30
      src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java

6
src/main/java/org/springframework/data/util/TypeDiscoverer.java

@ -331,6 +331,12 @@ class TypeDiscoverer<S> implements TypeInformation<S> { @@ -331,6 +331,12 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
return false;
}
// in case types cannot be resolved resort to toString checking to avoid infinite recursion caused by raw types and
// self-referencing generics
if (that.resolvableType.hasUnresolvableGenerics() || this.resolvableType.hasUnresolvableGenerics()) {
return ObjectUtils.nullSafeEquals(that.resolvableType.toString(), this.resolvableType.toString());
}
return ObjectUtils.nullSafeEquals(resolvedGenerics.get(), that.resolvedGenerics.get());
}

30
src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java

@ -17,6 +17,7 @@ package org.springframework.data.util; @@ -17,6 +17,7 @@ package org.springframework.data.util;
import static org.assertj.core.api.Assertions.*;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
@ -33,6 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @@ -33,6 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.core.ResolvableType;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.repository.Repository;
import org.springframework.util.ReflectionUtils;
/**
@ -358,6 +360,24 @@ public class TypeDiscovererUnitTests { @@ -358,6 +360,24 @@ public class TypeDiscovererUnitTests {
assertThat(TypeInformation.of(containerList)).isNotEqualTo(TypeInformation.of(containerMap));
}
@Test // GH-3084
void considersNestedGenericsInEqualityForRecursiveUnresolvableTypes() throws Exception {
TypeInformation<RepoWithRawGenerics> repro = TypeInformation.of(RepoWithRawGenerics.class);
Method findAllExternalIdsFor = RepoWithRawGenerics.class.getDeclaredMethod("findAllExternalIdsFor");
TypeInformation<?> returnType = repro.getReturnType(findAllExternalIdsFor);
List<TypeInformation<?>> arguments = TypeInformation.of(RepoWithRawGenerics.class)//
.getRequiredSuperTypeInformation(Repository.class)//
.getTypeArguments();
TypeInformation<?> domainType = arguments.get(1);
TypeInformation<?> actualType = returnType.getRequiredComponentType();
assertThat(domainType.isAssignableFrom(actualType)).isTrue();
}
class Person {
Addresses addresses;
@ -462,4 +482,14 @@ public class TypeDiscovererUnitTests { @@ -462,4 +482,14 @@ public class TypeDiscovererUnitTests {
T data;
}
static abstract class SomeType<Self extends SomeType<Self>> {
}
@SuppressWarnings("rawtypes")
interface RepoWithRawGenerics extends Repository<SomeType, SomeType> {
<T extends SomeType<T>> List<SomeType<T>> findAllExternalIdsFor();
}
}

Loading…
Cancel
Save