GH-816 Fix support for function that returns Iterable with target-protocol set

Resolves #816
This commit is contained in:
Oleg Zhurakousky
2022-02-21 14:50:29 +01:00
parent 78ee2fc437
commit 3f36528341
3 changed files with 22 additions and 2 deletions

View File

@@ -82,7 +82,7 @@ public final class FunctionTypeUtils {
}
type = getGenericType(type);
Class<?> rawType = type instanceof ParameterizedType ? getRawType(type) : (Class<?>) type;
return Collection.class.isAssignableFrom(rawType);
return Iterable.class.isAssignableFrom(rawType);
}
public static boolean isTypeArray(Type type) {

View File

@@ -53,6 +53,7 @@ import org.springframework.cloud.function.context.FunctionProperties.FunctionCon
import org.springframework.cloud.function.context.FunctionRegistration;
import org.springframework.cloud.function.context.FunctionRegistry;
import org.springframework.cloud.function.context.config.RoutingFunction;
import org.springframework.cloud.function.context.message.MessageUtils;
import org.springframework.cloud.function.core.FunctionInvocationHelper;
import org.springframework.cloud.function.json.JsonMapper;
import org.springframework.context.expression.BeanFactoryResolver;
@@ -1149,7 +1150,13 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect
convertedOutput = this.convertOutputPublisherIfNecessary((Publisher) output, type, contentType);
}
else if (output instanceof Message) {
convertedOutput = this.convertOutputMessageIfNecessary(output, ObjectUtils.isEmpty(contentType) ? null : contentType[0]);
Message m = (Message) output;
if (m.getHeaders().containsKey(MessageUtils.TARGET_PROTOCOL) && FunctionTypeUtils.isTypeCollection(this.outputType)) {
convertedOutput = this.convertMultipleOutputValuesIfNecessary(m.getPayload(), ObjectUtils.isEmpty(contentType) ? null : contentType);
}
else {
convertedOutput = this.convertOutputMessageIfNecessary(output, ObjectUtils.isEmpty(contentType) ? null : contentType[0]);
}
}
else if (output instanceof Collection && this.isOutputTypeMessage()) {
convertedOutput = this.convertMultipleOutputValuesIfNecessary(output, ObjectUtils.isEmpty(contentType) ? null : contentType);

View File

@@ -56,6 +56,7 @@ import org.springframework.cloud.function.context.FunctionRegistration;
import org.springframework.cloud.function.context.FunctionRegistry;
import org.springframework.cloud.function.context.FunctionType;
import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper;
import org.springframework.cloud.function.context.message.MessageUtils;
import org.springframework.cloud.function.json.JsonMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -432,6 +433,18 @@ public class BeanFactoryAwareFunctionRegistryTests {
assertThat(result instanceof Message).isFalse();
}
@Test
public void testMultipleValuesInOutputHandlingWithTargetProtocol() throws Exception {
FunctionCatalog catalog = this.configureCatalog(CollectionOutConfiguration.class);
FunctionInvocationWrapper function = catalog.lookup("parseToList", "application/json");
assertThat(function).isNotNull();
Object result = function.apply(MessageBuilder.withPayload("1, 2, 3".getBytes())
.setHeader(MessageHeaders.CONTENT_TYPE, "text/plain")
.setHeader(MessageUtils.TARGET_PROTOCOL, "integration")
.build());
assertThat(result instanceof List).isTrue();
}
/**
* The following two tests test the fallback mechanism when an accept header has several values.
* The function produces Integer, which cannot be serialized by the default converter supporting text/plain