Skip to content

Commit 9f3b8a2

Browse files
committed
GenericTypeResolver's resolveTypeArguments needs to return null for raw types (for backwards compatibility with 3.2)
Issue: SPR-11052
1 parent 84bc474 commit 9f3b8a2

File tree

4 files changed

+48
-51
lines changed

4 files changed

+48
-51
lines changed

spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,12 @@ private static Class<?> getSingleGeneric(ResolvableType resolvableType) {
240240
* @return the resolved type of each argument, with the array size matching the
241241
* number of actual type arguments, or {@code null} if not resolvable
242242
*/
243-
public static Class[] resolveTypeArguments(Class<?> clazz, Class<?> genericIfc) {
243+
public static Class<?>[] resolveTypeArguments(Class<?> clazz, Class<?> genericIfc) {
244244
ResolvableType type = ResolvableType.forClass(clazz).as(genericIfc);
245-
if (!type.hasGenerics()) {
245+
if (!type.hasGenerics() || type.hasUnresolvableGenerics()) {
246246
return null;
247247
}
248-
return type.resolveGenerics(Object.class);
248+
return type.resolveGenerics();
249249
}
250250

251251
/**

spring-core/src/main/java/org/springframework/core/ResolvableType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ public Class<?> resolve(Class<?> fallback) {
567567
this.resolved = resolveClass();
568568
this.isResolved = true;
569569
}
570-
return (this.resolved == null ? fallback : this.resolved);
570+
return (this.resolved != null ? this.resolved : fallback);
571571
}
572572

573573
private Class<?> resolveClass() {
@@ -576,7 +576,7 @@ private Class<?> resolveClass() {
576576
}
577577
if (this.type instanceof GenericArrayType) {
578578
Class<?> resolvedComponent = getComponentType().resolve();
579-
return (resolvedComponent == null ? null : Array.newInstance(resolvedComponent, 0).getClass());
579+
return (resolvedComponent != null ? Array.newInstance(resolvedComponent, 0).getClass() : null);
580580
}
581581
return resolveType().resolve();
582582
}

spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,17 @@ public void testGetTypeVariableMap() throws Exception {
138138
}
139139

140140
@Test
141-
public void getGenericsCannotBeResovled() throws Exception {
141+
public void getGenericsCannotBeResolved() throws Exception {
142142
// SPR-11030
143-
Class[] resolved = GenericTypeResolver.resolveTypeArguments(List.class, Iterable.class);
144-
assertThat(resolved, equalTo(new Class[] { Object.class }));
143+
Class<?>[] resolved = GenericTypeResolver.resolveTypeArguments(List.class, Iterable.class);
144+
assertNull(resolved);
145+
}
146+
147+
@Test
148+
public void getRawMapTypeCannotBeResolved() throws Exception {
149+
// SPR-11052
150+
Class<?>[] resolved = GenericTypeResolver.resolveTypeArguments(Map.class, Map.class);
151+
assertNull(resolved);
145152
}
146153

147154
@Test
@@ -300,11 +307,9 @@ class TypedNested extends Nested<Long> {
300307
static abstract class WithArrayBase<T> {
301308

302309
public abstract T[] array(T... args);
303-
304310
}
305311

306312
static abstract class WithArray<T> extends WithArrayBase<T> {
307-
308313
}
309314

310315
}

spring-websocket/src/main/java/org/springframework/web/socket/adapter/ConvertingEncoderDecoderSupport.java

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.springframework.web.socket.adapter;
1818

1919
import java.nio.ByteBuffer;
20-
2120
import javax.websocket.DecodeException;
2221
import javax.websocket.Decoder;
2322
import javax.websocket.EncodeException;
@@ -65,10 +64,8 @@
6564
*
6665
* @author Phillip Webb
6766
* @since 4.0
68-
*
69-
* @param <T> The type being converted to (for Encoder) or from (for Decoder)
70-
* @param <M> The WebSocket message type ({@link String} or {@link ByteBuffer})
71-
*
67+
* @param <T> the type being converted to (for Encoder) or from (for Decoder)
68+
* @param <M> the WebSocket message type ({@link String} or {@link ByteBuffer})
7269
* @see ConvertingEncoderDecoderSupport.BinaryEncoder
7370
* @see ConvertingEncoderDecoderSupport.BinaryDecoder
7471
* @see ConvertingEncoderDecoderSupport.TextEncoder
@@ -107,15 +104,13 @@ public void destroy() {
107104
*/
108105
protected ConversionService getConversionService() {
109106
ApplicationContext applicationContext = getApplicationContext();
110-
Assert.state(applicationContext != null,
111-
"Unable to locate the Spring ApplicationContext");
107+
Assert.state(applicationContext != null, "Unable to locate the Spring ApplicationContext");
112108
try {
113109
return applicationContext.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class);
114110
}
115111
catch (BeansException ex) {
116-
throw new IllegalStateException(
117-
"Unable to find ConversionService, please configure a '"
118-
+ CONVERSION_SERVICE_BEAN_NAME + "' or override getConversionService()", ex);
112+
throw new IllegalStateException("Unable to find ConversionService: please configure a '" +
113+
CONVERSION_SERVICE_BEAN_NAME + "' or override the getConversionService() method", ex);
119114
}
120115
}
121116

@@ -148,8 +143,12 @@ protected TypeDescriptor getMessageType() {
148143
}
149144

150145
private Class<?>[] resolveTypeArguments() {
151-
return GenericTypeResolver.resolveTypeArguments(getClass(),
152-
ConvertingEncoderDecoderSupport.class);
146+
Class<?>[] resolved = GenericTypeResolver.resolveTypeArguments(getClass(), ConvertingEncoderDecoderSupport.class);
147+
if (resolved == null) {
148+
throw new IllegalStateException("ConvertingEncoderDecoderSupport's generic types T and M " +
149+
"need to be substituted in subclass: " + getClass());
150+
}
151+
return resolved;
153152
}
154153

155154
/**
@@ -185,63 +184,56 @@ public T decode(M message) throws DecodeException {
185184
}
186185
catch (ConversionException ex) {
187186
if (message instanceof String) {
188-
throw new DecodeException((String) message, "Unable to decode " +
189-
"websocket message using ConversionService", ex);
187+
throw new DecodeException((String) message,
188+
"Unable to decode websocket message using ConversionService", ex);
190189
}
191190
if (message instanceof ByteBuffer) {
192-
throw new DecodeException((ByteBuffer) message, "Unable to decode " +
193-
"websocket message using ConversionService", ex);
191+
throw new DecodeException((ByteBuffer) message,
192+
"Unable to decode websocket message using ConversionService", ex);
194193
}
195194
throw ex;
196195
}
197196
}
198197

199198

200199
/**
201-
* A Binary {@link javax.websocket.Encoder.Binary javax.websocket.Encoder} that
202-
* delegates to Spring's conversion service. See
203-
* {@link ConvertingEncoderDecoderSupport} for details.
204-
*
205-
* @param <T> The type that this Encoder can convert to.
200+
* A binary {@link javax.websocket.Encoder.Binary javax.websocket.Encoder} that delegates
201+
* to Spring's conversion service. See {@link ConvertingEncoderDecoderSupport} for details.
202+
* @param <T> the type that this Encoder can convert to
206203
*/
207-
public static abstract class BinaryEncoder<T> extends
208-
ConvertingEncoderDecoderSupport<T, ByteBuffer> implements Encoder.Binary<T> {
204+
public static abstract class BinaryEncoder<T> extends ConvertingEncoderDecoderSupport<T, ByteBuffer>
205+
implements Encoder.Binary<T> {
209206
}
210207

211208

212209
/**
213-
* A Binary {@link javax.websocket.Encoder.Binary javax.websocket.Encoder} that delegates
214-
* to Spring's conversion service. See {@link ConvertingEncoderDecoderSupport} for
215-
* details.
216-
*
217-
* @param <T> The type that this Decoder can convert from.
210+
* A binary {@link javax.websocket.Encoder.Binary javax.websocket.Encoder} that delegates
211+
* to Spring's conversion service. See {@link ConvertingEncoderDecoderSupport} for details.
212+
* @param <T> the type that this Decoder can convert from
218213
*/
219-
public static abstract class BinaryDecoder<T> extends
220-
ConvertingEncoderDecoderSupport<T, ByteBuffer> implements Decoder.Binary<T> {
214+
public static abstract class BinaryDecoder<T> extends ConvertingEncoderDecoderSupport<T, ByteBuffer>
215+
implements Decoder.Binary<T> {
221216
}
222217

223218

224219
/**
225-
* A Text {@link javax.websocket.Encoder.Text javax.websocket.Encoder} that delegates
220+
* A text {@link javax.websocket.Encoder.Text javax.websocket.Encoder} that delegates
226221
* to Spring's conversion service. See {@link ConvertingEncoderDecoderSupport} for
227222
* details.
228-
*
229-
* @param <T> The type that this Encoder can convert to.
223+
* @param <T> the type that this Encoder can convert to
230224
*/
231-
public static abstract class TextEncoder<T> extends
232-
ConvertingEncoderDecoderSupport<T, String> implements Encoder.Text<T> {
225+
public static abstract class TextEncoder<T> extends ConvertingEncoderDecoderSupport<T, String>
226+
implements Encoder.Text<T> {
233227
}
234228

235229

236230
/**
237231
* A Text {@link javax.websocket.Encoder.Text javax.websocket.Encoder} that delegates
238-
* to Spring's conversion service. See {@link ConvertingEncoderDecoderSupport} for
239-
* details.
240-
*
241-
* @param <T> The type that this Decoder can convert from.
232+
* to Spring's conversion service. See {@link ConvertingEncoderDecoderSupport} for details.
233+
* @param <T> the type that this Decoder can convert from
242234
*/
243-
public static abstract class TextDecoder<T> extends
244-
ConvertingEncoderDecoderSupport<T, String> implements Decoder.Text<T> {
235+
public static abstract class TextDecoder<T> extends ConvertingEncoderDecoderSupport<T, String>
236+
implements Decoder.Text<T> {
245237
}
246238

247239
}

0 commit comments

Comments
 (0)