From 949f5fb02302db30c216a86c69a0a6dc88dd8704 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 31 Mar 2020 16:40:31 +0200 Subject: [PATCH] GH-466 Fix SupplierExporter to avoid starting if Supplier is not present Added condition to the start method of the SupplierExporter to prevent it from starting for cases where there are no Suppliers in catalog Resolves #466 --- .../function/FunctionEndpointInitializer.java | 29 +++++------ .../function/web/source/SupplierExporter.java | 48 ++++++++++--------- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializer.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializer.java index 52780ac53..0556944ed 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializer.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializer.java @@ -243,23 +243,20 @@ class FunctionEndpointFactory { }) .andRoute(GET("/**"), request -> { Object functionComponent = extract(request); - if (functionComponent instanceof Supplier || functionComponent instanceof Function) { - Class outputType = (Class) this.inspector.getOutputType(functionComponent); - if (functionComponent instanceof Supplier) { - Supplier> supplier = (Supplier>) functionComponent; - FunctionWrapper wrapper = RequestProcessor.wrapper(null, null, supplier); - return ServerResponse.ok().body(wrapper.supplier().get(), outputType); - } - else if (functionComponent instanceof Function) { - Function, Flux> function = (Function, Flux>) functionComponent; - FunctionWrapper wrapper = RequestProcessor.wrapper(function, null, null); - wrapper.headers(request.headers().asHttpHeaders()); - String argument = (String) request.attribute(WebRequestConstants.ARGUMENT).get(); - wrapper.argument(Flux.just(argument)); - return ServerResponse.ok().body(wrapper.function().apply(wrapper.argument()), outputType); - } + Class outputType = (Class) this.inspector.getOutputType(functionComponent); + if (functionComponent instanceof Supplier) { + Supplier> supplier = (Supplier>) functionComponent; + FunctionWrapper wrapper = RequestProcessor.wrapper(null, null, supplier); + return ServerResponse.ok().body(wrapper.supplier().get(), outputType); + } + else { + Function, Flux> function = (Function, Flux>) functionComponent; + FunctionWrapper wrapper = RequestProcessor.wrapper(function, null, null); + wrapper.headers(request.headers().asHttpHeaders()); + String argument = (String) request.attribute(WebRequestConstants.ARGUMENT).get(); + wrapper.argument(Flux.just(argument)); + return ServerResponse.ok().body(wrapper.function().apply(wrapper.argument()), outputType); } - throw new UnsupportedOperationException("Consumer is not supported for GET"); }); } } diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SupplierExporter.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SupplierExporter.java index 99f82e8c3..c219f02be 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SupplierExporter.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SupplierExporter.java @@ -90,6 +90,8 @@ public class SupplierExporter implements SmartLifecycle { Flux streams = Flux.empty(); Set names = this.supplier == null ? this.catalog.getNames(Supplier.class) : Collections.singleton(this.supplier); + + boolean suppliersPresent = false; for (String name : names) { Supplier> supplier = this.catalog.lookup(Supplier.class, name); if (supplier == null) { @@ -97,32 +99,34 @@ public class SupplierExporter implements SmartLifecycle { continue; } streams = streams.mergeWith(forward(supplier, name)); + suppliersPresent = true; } - - this.subscription = streams - .retry(error -> { - /* - * The ConnectException may happen if a server is not yet available/reachable - * The ClassCast is to handle delayed Mono issued by HttpSupplier.transform for non-2xx responses - */ - boolean retry = error instanceof ConnectException || error instanceof ClassCastException - && this.running; - if (!retry) { - this.ok = false; - if (!this.debug) { - logger.info(error); + if (suppliersPresent) { + this.subscription = streams + .retry(error -> { + /* + * The ConnectException may happen if a server is not yet available/reachable + * The ClassCast is to handle delayed Mono issued by HttpSupplier.transform for non-2xx responses + */ + boolean retry = error instanceof ConnectException || error instanceof ClassCastException + && this.running; + if (!retry) { + this.ok = false; + if (!this.debug) { + logger.info(error); + } + stop(); } + return retry; + }) + .doOnComplete(() -> { stop(); - } - return retry; - }) - .doOnComplete(() -> { - stop(); - }) - .subscribe(); + }) + .subscribe(); - this.ok = true; - this.running = true; + this.ok = true; + this.running = true; + } } public boolean isOk() {