From 1a3ba79071a4e0898ec8d8807ea584ef00bdc3d7 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 25 Oct 2013 17:23:36 -0700 Subject: [PATCH] Restore prior resolveTypeArguments behavior Restore prior behavior of GenericTypeResolver.resolveTypeArguments to never include null elements in the returned array. Issue: SPR-11030 --- .../core/GenericTypeResolver.java | 2 +- .../org/springframework/core/ResolvableType.java | 16 +++++++++++++++- .../support/GenericConversionService.java | 10 +++++++--- .../core/GenericTypeResolverTests.java | 7 +++++++ 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java b/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java index a6589b17160..bec2f7542a5 100644 --- a/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java +++ b/spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java @@ -245,7 +245,7 @@ public abstract class GenericTypeResolver { if (!type.hasGenerics()) { return null; } - return type.resolveGenerics(); + return type.resolveGenerics(Object.class); } /** diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java index 0ae3f9bd585..2821a4f4229 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -480,10 +480,24 @@ public final class ResolvableType implements Serializable { * @see #resolve() */ public Class[] resolveGenerics() { + return resolveGenerics(null); + } + + /** + * Convenience method that will {@link #getGenerics() get} and {@link #resolve() + * resolve} generic parameters, using the specified {@code fallback} if any type + * cannot be resolved. + * @param fallback the fallback class to use if resolution fails (may be {@code null}) + * @return an array of resolved generic parameters (the resulting array will never be + * {@code null}, but it may contain {@code null} elements}) + * @see #getGenerics() + * @see #resolve() + */ + public Class[] resolveGenerics(Class fallback) { ResolvableType[] generics = getGenerics(); Class[] resolvedGenerics = new Class[generics.length]; for (int i = 0; i < generics.length; i++) { - resolvedGenerics[i] = generics[i].resolve(); + resolvedGenerics[i] = generics[i].resolve(fallback); } return resolvedGenerics; } diff --git a/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java b/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java index 9ac5b04d06d..b2358b25eaa 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java +++ b/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.springframework.core.GenericTypeResolver; +import org.springframework.core.ResolvableType; import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionService; @@ -267,8 +268,11 @@ public class GenericConversionService implements ConfigurableConversionService { // internal helpers private GenericConverter.ConvertiblePair getRequiredTypeInfo(Object converter, Class genericIfc) { - Class[] args = GenericTypeResolver.resolveTypeArguments(converter.getClass(), genericIfc); - return (args != null ? new GenericConverter.ConvertiblePair(args[0], args[1]) : null); + ResolvableType resolvableType = ResolvableType.forClass(converter.getClass()).as(genericIfc); + if(resolvableType.hasUnresolvableGenerics()) { + return null; + } + return new GenericConverter.ConvertiblePair(resolvableType.resolveGeneric(0), resolvableType.resolveGeneric(1)); } private void invalidateCache() { diff --git a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java index b7cb02c883b..f0d728eb823 100644 --- a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java +++ b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java @@ -21,6 +21,7 @@ import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.junit.Test; @@ -136,6 +137,12 @@ public class GenericTypeResolverTests { assertThat(x, equalTo((Type) Long.class)); } + @Test + public void getGenericsCannotBeResovled() throws Exception { + // SPR-11030 + Class[] resolved = GenericTypeResolver.resolveTypeArguments(List.class, Iterable.class); + assertThat(resolved, equalTo(new Class[] { Object.class })); + } public interface MyInterfaceType { }