Protect against NPE when resolving generic array

Update ResolvableType to check that the resolved component type from
a generic array is not null before attempting to use it to generate the
resolved array class.

Issue: SPR-11044
master
Phillip Webb 11 years ago
parent a7af9505de
commit e5aef5ee9d
  1. 3
      spring-core/src/main/java/org/springframework/core/ResolvableType.java
  2. 28
      spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
  3. 26
      spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java

@ -575,7 +575,8 @@ public final class ResolvableType implements Serializable {
return (Class<?>) this.type; return (Class<?>) this.type;
} }
if (this.type instanceof GenericArrayType) { if (this.type instanceof GenericArrayType) {
return Array.newInstance(getComponentType().resolve(), 0).getClass(); Class<?> resolvedComponent = getComponentType().resolve();
return (resolvedComponent == null ? null : Array.newInstance(resolvedComponent, 0).getClass());
} }
return resolveType().resolve(); return resolveType().resolve();
} }

@ -144,6 +144,24 @@ public class GenericTypeResolverTests {
assertThat(resolved, equalTo(new Class[] { Object.class })); assertThat(resolved, equalTo(new Class[] { Object.class }));
} }
@Test
public void getGenericsOnArrayFromParamCannotBeResolved() throws Exception {
// SPR-11044
MethodParameter methodParameter = MethodParameter.forMethodOrConstructor(
WithArrayBase.class.getDeclaredMethod("array", Object[].class), 0);
Class<?> resolved = GenericTypeResolver.resolveParameterType(methodParameter, WithArray.class);
assertThat(resolved, equalTo((Class) Object[].class));
}
@Test
public void getGenericsOnArrayFromReturnCannotBeResolved() throws Exception {
// SPR-11044
Class<?> resolved = GenericTypeResolver.resolveReturnType(
WithArrayBase.class.getDeclaredMethod("array", Object[].class),
WithArray.class);
assertThat(resolved, equalTo((Class) Object[].class));
}
public interface MyInterfaceType<T> { public interface MyInterfaceType<T> {
} }
@ -279,4 +297,14 @@ public class GenericTypeResolverTests {
} }
} }
static abstract class WithArrayBase<T> {
public abstract T[] array(T... args);
}
static abstract class WithArray<T> extends WithArrayBase<T> {
}
} }

@ -519,6 +519,30 @@ public class ResolvableTypeTests {
assertThat(generic.resolve(), equalTo((Class) String[].class)); assertThat(generic.resolve(), equalTo((Class) String[].class));
} }
@Test
public void resolveVariableGenericArray() throws Exception {
ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"), TypedFields.class);
assertThat(type.getType().toString(), equalTo("T[]"));
assertThat(type.isArray(), equalTo(true));
assertThat(type.resolve(), equalTo((Class) String[].class));
}
@Test
public void resolveVariableGenericArrayUnknown() throws Exception {
ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"));
assertThat(type.getType().toString(), equalTo("T[]"));
assertThat(type.isArray(), equalTo(true));
assertThat(type.resolve(), nullValue());
}
@Test
public void resolveVariableGenericArrayUnknownWithFallback() throws Exception {
ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"));
assertThat(type.getType().toString(), equalTo("T[]"));
assertThat(type.isArray(), equalTo(true));
assertThat(type.resolve(Object.class), equalTo((Class) Object.class));
}
@Test @Test
public void resolveWildcardTypeUpperBounds() throws Exception { public void resolveWildcardTypeUpperBounds() throws Exception {
ResolvableType type = ResolvableType.forField(Fields.class.getField("wildcardType")); ResolvableType type = ResolvableType.forField(Fields.class.getField("wildcardType"));
@ -1253,6 +1277,8 @@ public class ResolvableTypeTests {
public Map<Map<String, Integer>, Map<Byte, Long>> nested; public Map<Map<String, Integer>, Map<Byte, Long>> nested;
public T[] variableTypeGenericArray;
} }

Loading…
Cancel
Save