Fix regression for implicit composition

Also, added message check in AWS destination resolver
This commit is contained in:
Oleg Zhurakousky
2020-04-16 21:05:20 +02:00
parent 8f7672399f
commit fd93beefdb
6 changed files with 48 additions and 10 deletions

View File

@@ -154,7 +154,7 @@ public class BeanFactoryAwareFunctionRegistry extends SimpleFunctionRegistry imp
@Override
String discoverDefaultDefinitionIfNecessary(String definition) {
if (StringUtils.isEmpty(definition)) {
if (StringUtils.isEmpty(definition) || definition.endsWith("|")) {
// the underscores are for Kotlin function registrations (see KotlinLambdaToFunctionAutoConfiguration)
String[] functionNames = Stream.of(this.applicationContext.getBeanNamesForType(Function.class))
.filter(n -> !n.endsWith(FunctionRegistration.REGISTRATION_NAME_SUFFIX) && !n
@@ -184,6 +184,10 @@ public class BeanFactoryAwareFunctionRegistry extends SimpleFunctionRegistry imp
}
definition = names.get(0);
}
else if (definition.endsWith("|")) {
Set<String> fNames = this.getNames(null);
definition = this.determinImpliedDefinition(fNames, definition);
}
else {
definition = this.discoverDefaultDefinitionFromRegistration();
}

View File

@@ -27,7 +27,10 @@ import org.springframework.util.Assert;
* @author Dave Syer
* @author Mark Fisher
* @author Oleg Zhurakousky
*
* @deprecated since 3.1. End-of-life. Not used by the framework anymore in favor of SimpleFunctionRegistry
*/
@Deprecated
public class InMemoryFunctionCatalog extends AbstractComposableFunctionRegistry {
public InMemoryFunctionCatalog() {

View File

@@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -48,6 +49,7 @@ import reactor.util.function.Tuples;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cloud.function.context.FunctionProperties;
import org.springframework.cloud.function.context.FunctionRegistration;
import org.springframework.cloud.function.context.FunctionRegistry;
@@ -72,6 +74,11 @@ import org.springframework.util.StringUtils;
/**
*
* Basic implementation of FunctionRegistry which maintains the cache of registered functions while
* decorating them with additional features such as transparent type conversion, composition, routing etc.
*
* Unlike {@link BeanFactoryAwareFunctionRegistry}, this implementation does not depend on {@link BeanFactory}.
*
* @author Oleg Zhurakousky
*
@@ -217,8 +224,31 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect
else if (!this.registrationsByName.containsKey(definition) && this.registrationsByName.size() == 1) {
definition = this.registrationsByName.keySet().iterator().next();
}
else if (definition.endsWith("|")) {
if (this.registrationsByName.size() == 2) {
Set<String> fNames = this.getNames(null);
definition = this.determinImpliedDefinition(fNames, definition);
}
}
return definition;
}
String determinImpliedDefinition(Set<String> fNames, String originalDefinition) {
if (fNames.size() == 2) {
Iterator<String> iter = fNames.iterator();
String n1 = iter.next();
String n2 = iter.next();
String[] definitionName = StringUtils.delimitedListToStringArray(originalDefinition, "|");
if (definitionName[0].equals(n1)) {
definitionName[1] = n2;
originalDefinition = definitionName[0] + "|" + definitionName[1];
}
else {
definitionName[1] = n1;
originalDefinition = definitionName[0] + "|" + definitionName[1];
}
}
return originalDefinition;
}
Type discovereFunctionTypeByName(String name) {

View File

@@ -169,7 +169,6 @@ public class ContextFunctionCatalogInitializer implements ApplicationContextInit
}
if (this.context.getBeanFactory().getBeanNamesForType(FunctionCatalog.class, false, false).length == 0) {
this.context.registerBean(SimpleFunctionRegistry.class, () -> {
List<MessageConverter> messageConverters = new ArrayList<>();
JsonMapper jsonMapper = this.context.getBean(JsonMapper.class);

View File

@@ -28,6 +28,7 @@ import org.junit.Test;
import reactor.core.publisher.Flux;
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.config.JsonMessageConverter;
@@ -103,21 +104,20 @@ public class SimpleFunctionRegistryTests {
}
@Test
@Ignore
public void testFunctionCompositionImplicit() {
FunctionRegistration<Words> wordsRegistration = new FunctionRegistration<>(
new Words(), "words").type(FunctionType.of(Words.class));
FunctionRegistration<Reverse> reverseRegistration = new FunctionRegistration<>(
new Reverse(), "reverse").type(FunctionType.of(Reverse.class));
SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter);
FunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter);
catalog.register(wordsRegistration);
catalog.register(reverseRegistration);
// There's only one function, we should be able to leave that blank
Supplier<Flux<String>> lookedUpFunction = catalog.lookup("words|");
Supplier<String> lookedUpFunction = catalog.lookup("words|");
assertThat(lookedUpFunction).isNotNull();
assertThat(lookedUpFunction.get().blockFirst()).isEqualTo("olleh");
assertThat(lookedUpFunction.get()).isEqualTo("olleh");
}
@Test