From 7bc6d7dfee57462e86436134ec0a511ca3fe5453 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 26 Feb 2018 16:24:55 +0000 Subject: [PATCH] Re-order type discovery and function wrapping Otherwise the explicit types from the function registration are not used. --- .../context/FunctionRegistration.java | 6 +-- .../cloud/function/context/FunctionType.java | 8 ++++ ...ntextFunctionCatalogAutoConfiguration.java | 11 +++-- .../context/FunctionRegistrationTests.java | 45 +++++++++++++++++++ .../BeanFactoryFunctionCatalogTests.java | 21 +++++++++ 5 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionRegistrationTests.java diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java index f8a570309..6832ebcfe 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java @@ -39,7 +39,7 @@ public class FunctionRegistration { private final Map properties = new LinkedHashMap<>(); - private Type type; + private FunctionType type; public FunctionRegistration(T target) { this.target = target; @@ -53,7 +53,7 @@ public class FunctionRegistration { return names; } - public Type getType() { + public FunctionType getType() { return type; } @@ -79,7 +79,7 @@ public class FunctionRegistration { } public FunctionRegistration type(Type type) { - this.type = type; + this.type = FunctionType.of(type); return this; } diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionType.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionType.java index cfc9b9384..208063216 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionType.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionType.java @@ -45,6 +45,10 @@ public class FunctionType { this.type = type; } + public Type getType() { + return type; + } + public Class getInputWrapper() { return findType(ParamType.INPUT_WRAPPER); } @@ -79,6 +83,10 @@ public class FunctionType { || Mono.class.equals(type) || Optional.class.equals(type); } + public static FunctionType of(Type function) { + return new FunctionType(function); + } + public static FunctionType from(Class input) { return new FunctionType(ResolvableType .forClassWithGenerics(Function.class, input, Object.class).getType()); diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java index 3f1400b4b..6bd70f2d2 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java @@ -439,10 +439,15 @@ public class ContextFunctionCatalogAutoConfiguration { private void wrap(FunctionRegistration registration, String key) { Object target = registration.getTarget(); this.registrations.put(target, key); + if (registration.getType() != null) { + this.types.put(key, registration.getType()); + } + else { + findType(target); + } Class type; if (target instanceof Supplier) { type = Supplier.class; - findType(target); registration.target(target((Supplier) target, key)); for (String name : registration.getNames()) { this.suppliers.put(name, registration.getTarget()); @@ -450,7 +455,6 @@ public class ContextFunctionCatalogAutoConfiguration { } else if (target instanceof Consumer) { type = Consumer.class; - findType(target); registration.target(target((Consumer) target, key)); for (String name : registration.getNames()) { this.consumers.put(name, registration.getTarget()); @@ -458,7 +462,6 @@ public class ContextFunctionCatalogAutoConfiguration { } else if (target instanceof Function) { type = Function.class; - findType(target); registration.target(target((Function) target, key)); for (String name : registration.getNames()) { this.functions.put(name, registration.getTarget()); @@ -467,7 +470,7 @@ public class ContextFunctionCatalogAutoConfiguration { else { return; } - registrations.remove(target); + this.registrations.remove(target); this.registrations.put(registration.getTarget(), key); if (publisher != null) { publisher.publishEvent(new FunctionRegistrationEvent( diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionRegistrationTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionRegistrationTests.java new file mode 100644 index 000000000..29832732f --- /dev/null +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionRegistrationTests.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cloud.function.context; + +import java.util.function.Function; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Dave Syer + * + */ +public class FunctionRegistrationTests { + + @Test + public void noTypeByDefault() { + FunctionRegistration registration = new FunctionRegistration<>(new Foos()) + .names("foos"); + assertThat(registration.getType()).isNull(); + assertThat(registration.getNames()).contains("foos"); + } + + private static class Foos implements Function { + @Override + public String apply(Integer t) { + return "i=" + t; + } + } + +} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/BeanFactoryFunctionCatalogTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/BeanFactoryFunctionCatalogTests.java index 290b6c569..675135cb6 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/BeanFactoryFunctionCatalogTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/BeanFactoryFunctionCatalogTests.java @@ -25,6 +25,7 @@ import java.util.function.Supplier; import org.junit.Test; 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; @@ -55,6 +56,26 @@ public class BeanFactoryFunctionCatalogTests { assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4"); } + @Test + public void registerFunctionWithType() { + processor.register(new FunctionRegistration>( + (Integer i) -> "i=" + i).names("foos").type( + FunctionType.from(Integer.class).to(String.class).getType())); + Function, Flux> foos = processor.lookupFunction(""); + assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("i=2"); + } + + @Test + public void registerFunctionWithFluxType() { + processor + .register(new FunctionRegistration, Flux>>( + ints -> ints.map(i -> "i=" + i)).names("foos") + .type(FunctionType.from(Integer.class).to(String.class) + .wrap(Flux.class).getType())); + Function, Flux> foos = processor.lookupFunction(""); + assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("i=2"); + } + @Test public void lookupNonExistentConsumerWithEmptyName() { processor.register(new FunctionRegistration<>(new Foos()).names("foos"));