GH-261 Added support for function composition InMemoryFunctionCatalog
- Refactored InMemoryFunctionCatalog and BeanFactoryFunctionCatalog into common catalog implementation - Added initial test Resolves #261
This commit is contained in:
@@ -19,6 +19,7 @@ package org.springframework.cloud.function.context.catalog;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.cloud.function.context.FunctionRegistration;
|
||||
import org.springframework.cloud.function.context.FunctionType;
|
||||
@@ -59,6 +60,40 @@ public class InMemoryFunctionCatalogTests {
|
||||
assertThat(lookedUpFunction instanceof FluxFunction).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionComposition() {
|
||||
FunctionRegistration<UpperCase> upperCaseRegistration = new FunctionRegistration<>(
|
||||
new UpperCase(), "uppercase").type(FunctionType.of(UpperCase.class).getType());
|
||||
FunctionRegistration<Reverse> reverseRegistration = new FunctionRegistration<>(
|
||||
new Reverse(), "reverse").type(FunctionType.of(Reverse.class).getType());
|
||||
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
||||
catalog.register(upperCaseRegistration);
|
||||
catalog.register(reverseRegistration);
|
||||
|
||||
Function<Flux<String>, Flux<String>> lookedUpFunction = catalog.lookup("uppercase|reverse");
|
||||
|
||||
assertThat(lookedUpFunction).isNotNull();
|
||||
assertThat(lookedUpFunction.apply(Flux.just("star")).blockFirst()).isEqualTo("RATS");
|
||||
}
|
||||
|
||||
private static class UpperCase implements Function<String, String> {
|
||||
|
||||
@Override
|
||||
public String apply(String t) {
|
||||
return t.toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Reverse implements Function<String, String> {
|
||||
|
||||
@Override
|
||||
public String apply(String t) {
|
||||
return new StringBuilder(t).reverse().toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestFunction implements Function<Integer, String> {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,18 +32,15 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.cloud.function.context.FunctionRegistration;
|
||||
import org.springframework.cloud.function.context.FunctionType;
|
||||
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration.BeanFactoryFunctionCatalog;
|
||||
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration.ContextFunctionRegistry;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class BeanFactoryFunctionCatalogTests {
|
||||
|
||||
private BeanFactoryFunctionCatalog processor = new BeanFactoryFunctionCatalog(
|
||||
new ContextFunctionRegistry());
|
||||
private BeanFactoryFunctionCatalog processor = new BeanFactoryFunctionCatalog();
|
||||
|
||||
@Test
|
||||
public void basicRegistrationFeatures() {
|
||||
|
||||
@@ -35,7 +35,7 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.cloud.function.context.FunctionRegistration;
|
||||
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration.ContextFunctionRegistry;
|
||||
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration.BeanFactoryFunctionCatalog;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -49,7 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
// for functions with the same name, uncomposable combinations)
|
||||
public class ContextFunctionPostProcessorTests {
|
||||
|
||||
private ContextFunctionRegistry processor = new ContextFunctionRegistry();
|
||||
private BeanFactoryFunctionCatalog processor = new BeanFactoryFunctionCatalog();
|
||||
|
||||
private URLClassLoader classLoader;
|
||||
|
||||
@@ -70,10 +70,11 @@ public class ContextFunctionPostProcessorTests {
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos");
|
||||
.lookup(null, "foos"); //lookupFunction("foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void registrationThroughMerge() {
|
||||
FunctionRegistration<Foos> registration = new FunctionRegistration<>(new Foos(),
|
||||
@@ -82,17 +83,18 @@ public class ContextFunctionPostProcessorTests {
|
||||
Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap());
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos");
|
||||
.lookup(null, "foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void registrationThroughMergeFromNamedFunction() {
|
||||
this.processor.merge(Collections.emptyMap(), Collections.emptyMap(),
|
||||
Collections.emptyMap(), Collections.singletonMap("foos", new Foos()));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos");
|
||||
.lookup(null, "foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@@ -102,7 +104,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
this.processor.register(new FunctionRegistration<>(new Bars(), "bars"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos,bars");
|
||||
.lookup(null, "foos,bars");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("Hello 4");
|
||||
assertThat(this.processor.getRegistration(foos).getNames())
|
||||
.containsExactly("foos|bars");
|
||||
@@ -116,7 +118,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
(x) -> x.toUpperCase(), "function"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<Flux<String>> supplier = (Supplier<Flux<String>>) this.processor
|
||||
.lookupSupplier("supplier|function");
|
||||
.lookup(Supplier.class, "supplier|function");
|
||||
assertThat(supplier.get().blockFirst()).isEqualTo("FOO");
|
||||
assertThat(this.processor.getRegistration(supplier).getNames())
|
||||
.containsExactly("supplier|function");
|
||||
@@ -130,7 +132,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
this.processor.register(new FunctionRegistration<Consumer<String>>(
|
||||
System.out::println, "consumer"));
|
||||
Supplier<Mono<Void>> supplier = (Supplier<Mono<Void>>) this.processor
|
||||
.lookupSupplier("supplier|consumer");
|
||||
.lookup(Supplier.class, "supplier|consumer");
|
||||
assertThat(supplier.get().block()).isNull();
|
||||
}
|
||||
|
||||
@@ -140,7 +142,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
this.processor.register(new FunctionRegistration<>(new Bars(), "bars"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos|bars");
|
||||
.lookup(null, "foos|bars");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("Hello 4");
|
||||
assertThat(this.processor.getRegistration(foos).getNames())
|
||||
.containsExactly("foos|bars");
|
||||
@@ -152,7 +154,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<Flux<String>> foos = (Supplier<Flux<String>>) this.processor
|
||||
.lookupSupplier("ints|foos");
|
||||
.lookup(Supplier.class, "ints|foos");
|
||||
assertThat(foos.get().blockFirst()).isEqualTo("8");
|
||||
assertThat(this.processor.getRegistration(foos).getNames())
|
||||
.containsExactly("ints|foos");
|
||||
@@ -167,7 +169,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
this.processor.register(new FunctionRegistration<>(create(Foos.class), "foos"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos");
|
||||
.lookup(null, "foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@@ -179,7 +181,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
.register(new FunctionRegistration<>(create(Source.class), "source"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<Flux<Integer>> source = (Supplier<Flux<Integer>>) this.processor
|
||||
.lookupSupplier("source");
|
||||
.lookup(Supplier.class, "source");
|
||||
assertThat(source.get().blockFirst()).isEqualTo(4);
|
||||
}
|
||||
|
||||
@@ -191,7 +193,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
this.processor.register(new FunctionRegistration<>(target, "sink"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<String>, Mono<Void>> sink = (Function<Flux<String>, Mono<Void>>) this.processor
|
||||
.lookupFunction("sink");
|
||||
.lookup(null, "sink");
|
||||
sink.apply(Flux.just("Hello")).subscribe();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> values = (List<String>) ReflectionTestUtils.getField(target,
|
||||
|
||||
Reference in New Issue
Block a user