diff --git a/spring-cloud-function-deployer/pom.xml b/spring-cloud-function-deployer/pom.xml index f7853a206..044618b53 100644 --- a/spring-cloud-function-deployer/pom.xml +++ b/spring-cloud-function-deployer/pom.xml @@ -26,8 +26,9 @@ ${project.version} - org.springframework.boot.experimental - spring-boot-starter-web-reactive + org.springframework.cloud + spring-cloud-function-web + ${project.version} org.springframework.boot diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/ApplicationRunner.java b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/ApplicationRunner.java index b120a3e7c..4180c6e31 100644 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/ApplicationRunner.java +++ b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/ApplicationRunner.java @@ -58,7 +58,7 @@ import reactor.core.publisher.Flux; // NOT a @Component (to prevent it from being scanned by the "main" application). public class ApplicationRunner implements CommandLineRunner { - private static final String DEFAULT_REACTOR_VERSION = "3.0.3.RELEASE"; + private static final String DEFAULT_REACTOR_VERSION = "3.0.4.RELEASE"; private static Log logger = LogFactory.getLog(ApplicationRunner.class); diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployedFunctionApplication.java b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployedFunctionApplication.java index e31b19aa2..9906f8377 100644 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployedFunctionApplication.java +++ b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployedFunctionApplication.java @@ -23,4 +23,5 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; */ @SpringBootApplication public class DeployedFunctionApplication { + } diff --git a/spring-cloud-function-deployer/thin-slim.properties b/spring-cloud-function-deployer/thin-slim.properties index 734ae153e..afd1ad87e 100644 --- a/spring-cloud-function-deployer/thin-slim.properties +++ b/spring-cloud-function-deployer/thin-slim.properties @@ -1,4 +1,5 @@ exclusions.spring-web-reactive: org.springframework:spring-web-reactive +exclusions.spring-cloud-function-web: org.springframework.cloud:spring-cloud-function-web exclusions.spring-web: org.springframework:spring-web exclusions.reator-netty: io.projectreactor.ipc:reactor-netty exclusions.spring-cloud-stream: org.springframework.cloud:spring-cloud-stream diff --git a/spring-cloud-function-web/pom.xml b/spring-cloud-function-web/pom.xml index 8c99b110b..a31e42065 100644 --- a/spring-cloud-function-web/pom.xml +++ b/spring-cloud-function-web/pom.xml @@ -20,39 +20,35 @@ - org.springframework - spring-web-reactive - 5.0.0.BUILD-SNAPSHOT - - - org.springframework - spring-web - 5.0.0.BUILD-SNAPSHOT - - - io.projectreactor.ipc - reactor-netty - 0.6.0.BUILD-SNAPSHOT + org.springframework.boot.experimental + spring-boot-starter-web-reactive org.springframework.cloud spring-cloud-function-core ${project.version} - - io.projectreactor - reactor-core - - - org.springframework.boot - spring-boot-starter-logging - - - org.springframework.boot - spring-boot-starter - + + + + org.springframework.boot + spring-boot-dependencies + 2.0.0.BUILD-SNAPSHOT + pom + import + + + org.springframework.boot.experimental + spring-boot-dependencies-web-reactive + 0.1.0.BUILD-SNAPSHOT + pom + import + + + + diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionConfigurationProperties.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionConfigurationProperties.java deleted file mode 100644 index 15398b84e..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionConfigurationProperties.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2016 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.web; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * @author Mark Fisher - */ -@ConfigurationProperties(prefix = "function") -public class FunctionConfigurationProperties { - - private String name; - - private String code; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getCode() { - return code; - } - - public void setCode(String code) { - this.code = code; - } -} diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployedFunctionController.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionController.java similarity index 70% rename from spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployedFunctionController.java rename to spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionController.java index dc2cf1c42..2545b7955 100644 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployedFunctionController.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionController.java @@ -13,11 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.function.deployer; +package org.springframework.cloud.function.web; import java.util.function.Function; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.context.embedded.ReactiveServerProperties; +import org.springframework.cloud.function.registry.FunctionCatalog; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -32,13 +35,14 @@ import reactor.core.publisher.Flux; * */ @RestController -public class DeployedFunctionController { +@ConditionalOnClass({ RestController.class, ReactiveServerProperties.class }) +public class FunctionController { - private final FunctionExtractingAppDeployer deployer; + private final FunctionCatalog functions; @Autowired - public DeployedFunctionController(FunctionExtractingAppDeployer deployer) { - this.deployer = deployer; + public FunctionController(FunctionCatalog catalog) { + this.functions = catalog; } @PostMapping(path = "/{name}", consumes = MediaType.TEXT_PLAIN_VALUE) @@ -46,10 +50,10 @@ public class DeployedFunctionController { @RequestBody Flux body) { Function function; if (name.contains(",")) { - function = deployer.composeFunction(name.split(",")); + function = functions.composeFunction(name.split(",")); } else { - function = deployer.lookupFunction(name); + function = functions.lookupFunction(name); } @SuppressWarnings("unchecked") Flux result = (Flux) function.apply(body); @@ -59,7 +63,7 @@ public class DeployedFunctionController { @GetMapping("/{name}") public Flux supplier(@PathVariable String name) { @SuppressWarnings("unchecked") - Flux result = (Flux) deployer.lookupSupplier(name).get(); + Flux result = (Flux) functions.lookupSupplier(name).get(); return result; } diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RestConfiguration.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RestConfiguration.java deleted file mode 100644 index 6e7f6d9b7..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RestConfiguration.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2016 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.web; - -import java.util.function.Function; -import java.util.function.Supplier; - -import org.reactivestreams.Publisher; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.function.registry.FunctionCatalog; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.MediaType; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; -import org.springframework.util.StringUtils; -import org.springframework.web.reactive.function.server.RequestPredicates; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.reactive.function.server.ServerResponse; - -import static org.springframework.web.reactive.function.BodyExtractors.toFlux; -import static org.springframework.web.reactive.function.BodyInserters.fromPublisher; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.ipc.netty.NettyContext; -import reactor.ipc.netty.http.server.HttpServer; - -/** - * @author Mark Fisher - */ -@Configuration -@EnableConfigurationProperties({ WebConfigurationProperties.class }) -@ConditionalOnClass({ HttpHandler.class, NettyContext.class }) -public class RestConfiguration { - - @Autowired - private WebConfigurationProperties webProperties; - - @Bean - public HttpHandler httpHandler(FunctionCatalog registry) { - FunctionInvokingHandler handler = new FunctionInvokingHandler(registry); - RouterFunction route = RouterFunctions - .route(RequestPredicates.POST(webProperties.getPath() + "/{name}") - .and(RequestPredicates.contentType(MediaType.TEXT_PLAIN)), - handler::handlePost) - .andRoute(RequestPredicates.GET(webProperties.getPath() + "/{name}"), - handler::handleGet); - return RouterFunctions.toHttpHandler(route); - } - - @Bean - public LifecycleAwareHttpServer httpServer(HttpHandler handler) { - return new LifecycleAwareHttpServer(handler, webProperties.getPort()); - } - - private static class FunctionInvokingHandler { - - private final FunctionCatalog registry; - - private FunctionInvokingHandler(FunctionCatalog registry) { - this.registry = registry; - } - - private Mono handlePost(ServerRequest request) { - Flux input = request.body(toFlux(String.class)); - String name = request.pathVariable("name"); - Function, Flux> function = (name.indexOf(',') == -1) - ? registry.lookupFunction(name) - : registry.composeFunction( - StringUtils.commaDelimitedListToStringArray(name)); - Publisher output = function.apply(input); - return ServerResponse.ok().body(fromPublisher(output, String.class)); - } - - private Mono handleGet(ServerRequest request) { - String name = request.pathVariable("name"); - Supplier> function = registry.lookupSupplier(name); - Publisher output = function.get(); - return ServerResponse.ok().body(fromPublisher(output, String.class)); - } - } - - private static class LifecycleAwareHttpServer - implements InitializingBean, DisposableBean { - - private final HttpHandler handler; - - private final int port; - - private volatile NettyContext server; - - private LifecycleAwareHttpServer(HttpHandler handler, int port) { - this.handler = handler; - this.port = port; - } - - @Override - public void afterPropertiesSet() { - ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter( - this.handler); - final HttpServer server = HttpServer.create("localhost", port); - Thread thread = new Thread(new Runnable() { - - @Override - public void run() { - LifecycleAwareHttpServer.this.server = server.newHandler(adapter) - .block(); - while (LifecycleAwareHttpServer.this.server != null) { - try { - Thread.sleep(100L); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - }); - thread.setDaemon(false); - thread.start(); - } - - @Override - public void destroy() { - if (this.server != null) { - this.server.dispose(); - this.server = null; - } - } - } -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/WebConfigurationProperties.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/WebConfigurationProperties.java deleted file mode 100644 index 26df4392d..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/WebConfigurationProperties.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.web; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties("server") -public class WebConfigurationProperties { - - private int port = 8080; - - private String path = ""; - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - while (path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } - this.path = path; - } -} diff --git a/spring-cloud-function-web/src/main/resources/META-INF/spring.factories b/spring-cloud-function-web/src/main/resources/META-INF/spring.factories index cfc3c41bf..14109c4d6 100644 --- a/spring-cloud-function-web/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-function-web/src/main/resources/META-INF/spring.factories @@ -1,2 +1,2 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.function.web.RestConfiguration \ No newline at end of file +org.springframework.cloud.function.web.FunctionController \ No newline at end of file