Skip to content

Commit 051d987

Browse files
committed
GH-1296: Fixed consumer with generics regression
1 parent cdd8bc6 commit 051d987

File tree

2 files changed

+69
-23
lines changed

2 files changed

+69
-23
lines changed

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -385,31 +385,33 @@ public static Type getInputType(Type functionType) {
385385

386386
ResolvableType resolvableFunctionType = ResolvableType.forType(functionType);
387387

388-
ResolvableType resolvableInputType = resolvableFunctionType.as(resolvableFunctionType.getRawClass());
389-
390-
if (resolvableInputType.getType() instanceof ParameterizedType) {
391-
return resolvableInputType.getGeneric(0).getType();
388+
if (FunctionTypeUtils.isFunction(functionType)) {
389+
return extractInputType(resolvableFunctionType.as(Function.class).getGeneric(0));
392390
}
393-
else {
394-
// will try another way. See GH-1251
395-
if (FunctionTypeUtils.isFunction(functionType)) {
396-
resolvableInputType = resolvableFunctionType.as(Function.class);
397-
}
398-
else {
399-
if (KotlinDetector.isKotlinPresent() && Function1.class.isAssignableFrom(getRawType(functionType))) { // Kotlin
400-
return ResolvableType.forType(getImmediateGenericType(functionType, 1)).getType();
401-
}
402-
else {
403-
resolvableInputType = resolvableFunctionType.as(Consumer.class);
404-
}
405-
}
406-
if (resolvableInputType.getType() instanceof ParameterizedType) {
407-
return resolvableInputType.getGeneric(0).getType();
408-
}
409-
else {
410-
return Object.class;
411-
}
391+
if (FunctionTypeUtils.isConsumer(functionType)) {
392+
return extractInputType(resolvableFunctionType.as(Consumer.class).getGeneric(0));
393+
}
394+
if (KotlinDetector.isKotlinPresent() && Function1.class.isAssignableFrom(getRawType(functionType))) { // Kotlin
395+
return ResolvableType.forType(getImmediateGenericType(functionType, 1)).getType();
412396
}
397+
398+
// no consumer or function
399+
// might be one of the other supported types (as asserted in first line of method)
400+
// for example FunctionRegistration or IntConsumer
401+
402+
// unclear what the contract is in such a case
403+
// maybe returning null here might be "more" correct
404+
return Object.class;
405+
}
406+
407+
private static Type extractInputType(ResolvableType resolvableInputType) {
408+
if (resolvableInputType.getType() instanceof TypeVariable) {
409+
// In case the input type is a type variable (e.g. as in GH-1251) we need to resolve the type
410+
// For the case that the type is unbound Object.class is used
411+
return resolvableInputType.resolve(Object.class);
412+
}
413+
414+
return resolvableInputType.getType();
413415
}
414416

415417
@SuppressWarnings("rawtypes")

spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtilsTests.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646

4747
import org.springframework.core.ParameterizedTypeReference;
4848
import org.springframework.messaging.Message;
49+
import org.springframework.util.ReflectionUtils;
4950

5051
import static org.assertj.core.api.Assertions.assertThat;
5152

@@ -63,6 +64,24 @@ public void testDiscoverFunctionalMethod() throws Exception {
6364
assertThat(method.getName()).isEqualTo("accept");
6465
}
6566

67+
private Type getBeanType(Class<?> configurationClass, String beanMethodName) {
68+
return ReflectionUtils.findMethod(configurationClass, beanMethodName).getGenericReturnType();
69+
}
70+
71+
@Test
72+
public void testInputType() {
73+
Type type;
74+
Type inputType;
75+
76+
type = getBeanType(Gh1251Configuration.class, "consumer2");
77+
inputType = FunctionTypeUtils.getInputType(type);
78+
assertThat(inputType).isEqualTo(String.class);
79+
80+
type = getBeanType(Gh1251Configuration.class, "consumer3");
81+
inputType = FunctionTypeUtils.getInputType(type);
82+
assertThat(inputType).isEqualTo(String.class);
83+
}
84+
6685
@Test
6786
public void testFunctionTypeFrom() throws Exception {
6887
Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(SimpleConsumer.class);
@@ -288,6 +307,31 @@ public void accept(Flux<Message<String>> messageFlux) {
288307
}
289308
}
290309

310+
static class Gh1251Configuration {
311+
312+
Gh1251Consumer2<Integer> consumer2() {
313+
return new Gh1251Consumer2<Integer>();
314+
}
315+
316+
Gh1251Consumer3<String> consumer3() {
317+
return new Gh1251Consumer3<>();
318+
}
319+
}
320+
321+
static class Gh1251Consumer2<E> implements Consumer<String> {
322+
323+
@Override
324+
public void accept(String message) {
325+
}
326+
}
327+
328+
static class Gh1251Consumer3<E> implements Consumer<E> {
329+
330+
@Override
331+
public void accept(E message) {
332+
}
333+
}
334+
291335
public interface ReactiveFunction<S, T> extends Function<Flux<S>, Flux<T>> {
292336

293337
}

0 commit comments

Comments
 (0)