Skip to content

Commit 027b8c2

Browse files
committed
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
1 parent 2f9427a commit 027b8c2

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

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

+6
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,12 @@ public boolean equals(@Nullable Object o) {
331331
return false;
332332
}
333333

334+
// in case types cannot be resolved resort to toString checking to avoid infinite recursion caused by raw types and
335+
// self-referencing generics
336+
if (that.resolvableType.hasUnresolvableGenerics() || this.resolvableType.hasUnresolvableGenerics()) {
337+
return ObjectUtils.nullSafeEquals(that.resolvableType.toString(), this.resolvableType.toString());
338+
}
339+
334340
return ObjectUtils.nullSafeEquals(resolvedGenerics.get(), that.resolvedGenerics.get());
335341
}
336342

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

+30
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.assertj.core.api.Assertions.*;
1919

20+
import java.lang.reflect.Method;
2021
import java.util.Collection;
2122
import java.util.Collections;
2223
import java.util.EnumMap;
@@ -33,6 +34,7 @@
3334
import org.springframework.beans.factory.annotation.Autowire;
3435
import org.springframework.core.ResolvableType;
3536
import org.springframework.data.geo.GeoResults;
37+
import org.springframework.data.repository.Repository;
3638
import org.springframework.util.ReflectionUtils;
3739

3840
/**
@@ -358,6 +360,24 @@ void considersNestedGenericsInEquality() throws ReflectiveOperationException {
358360
assertThat(TypeInformation.of(containerList)).isNotEqualTo(TypeInformation.of(containerMap));
359361
}
360362

363+
@Test // GH-3084
364+
void considersNestedGenericsInEqualityForRecursiveUnresolvableTypes() throws Exception {
365+
366+
TypeInformation<RepoWithRawGenerics> repro = TypeInformation.of(RepoWithRawGenerics.class);
367+
368+
Method findAllExternalIdsFor = RepoWithRawGenerics.class.getDeclaredMethod("findAllExternalIdsFor");
369+
TypeInformation<?> returnType = repro.getReturnType(findAllExternalIdsFor);
370+
371+
List<TypeInformation<?>> arguments = TypeInformation.of(RepoWithRawGenerics.class)//
372+
.getRequiredSuperTypeInformation(Repository.class)//
373+
.getTypeArguments();
374+
375+
TypeInformation<?> domainType = arguments.get(1);
376+
TypeInformation<?> actualType = returnType.getRequiredComponentType();
377+
378+
assertThat(domainType.isAssignableFrom(actualType)).isTrue();
379+
}
380+
361381
class Person {
362382

363383
Addresses addresses;
@@ -462,4 +482,14 @@ static class MyContainer<T> {
462482
T data;
463483
}
464484

485+
static abstract class SomeType<Self extends SomeType<Self>> {
486+
487+
}
488+
489+
@SuppressWarnings("rawtypes")
490+
interface RepoWithRawGenerics extends Repository<SomeType, SomeType> {
491+
492+
<T extends SomeType<T>> List<SomeType<T>> findAllExternalIdsFor();
493+
}
494+
465495
}

0 commit comments

Comments
 (0)