diff --git a/docs/pom.xml b/docs/pom.xml index 8ebe1c228..60527ff37 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT pom Spring Cloud Function Docs diff --git a/pom.xml b/pom.xml index ce54fa4ca..ba2b87556 100644 --- a/pom.xml +++ b/pom.xml @@ -6,18 +6,18 @@ spring-cloud-function-parent Spring Cloud Function Parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT pom org.springframework.cloud spring-cloud-build - 3.1.1-SNAPSHOT + 4.0.0-SNAPSHOT - 1.8 + 17 ${java.version} ${java.version} 1.0.27.RELEASE @@ -48,8 +48,16 @@ org.apache.maven.plugins maven-checkstyle-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + --add-opens java.base/java.util=ALL-UNNAMED + + + org.codehaus.mojo @@ -129,18 +137,18 @@ - - java11+ - - [11,) - - - - javax.annotation - javax.annotation-api - - - + + + + + + + + + + + + core diff --git a/spring-cloud-function-adapters/pom.xml b/spring-cloud-function-adapters/pom.xml index 092a20be6..e78de8ad4 100644 --- a/spring-cloud-function-adapters/pom.xml +++ b/spring-cloud-function-adapters/pom.xml @@ -10,7 +10,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT spring-cloud-function-adapter-parent diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/pom.xml index df68a3f43..7c47ab30a 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/pom.xml +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/pom.xml @@ -13,13 +13,12 @@ org.springframework.cloud spring-cloud-function-adapter-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT UTF-8 UTF-8 - 1.8 3.9.0 1.12.29 1.0.3 diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeAutoConfiguration.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeAutoConfiguration.java index c9730be45..0c2ffea2f 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeAutoConfiguration.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeAutoConfiguration.java @@ -29,6 +29,8 @@ import org.springframework.context.annotation.Configuration; /** * @author Dave Syer */ +//TODO - do we actually need it????? + @Configuration @AutoConfigureBefore(FunctionExporterAutoConfiguration.class) @ConditionalOnClass(DestinationResolver.class) diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEnvironmentPostProcessor.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEnvironmentPostProcessor.java deleted file mode 100644 index 5ed4e51fe..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEnvironmentPostProcessor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019-2021 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 - * - * https://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.adapter.aws; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.env.EnvironmentPostProcessor; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.MapPropertySource; - -/** - * Adds default properties to the environment for running a custom runtime in AWS. - * - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class CustomRuntimeEnvironmentPostProcessor implements EnvironmentPostProcessor { - - private static final String CUSTOM_RUNTIME = "spring.cloud.function.aws.custom"; - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { - if (!environment.containsProperty(CUSTOM_RUNTIME)) { - Map defaults = getDefaultProperties(environment); - defaults.put(CUSTOM_RUNTIME, true); - } - } - - private Map getDefaultProperties( - ConfigurableEnvironment environment) { - if (environment.getPropertySources().contains("defaultProperties")) { - MapPropertySource source = (MapPropertySource) environment - .getPropertySources().get("defaultProperties"); - return source.getSource(); - } - HashMap map = new HashMap(); - environment.getPropertySources() - .addLast(new MapPropertySource("defaultProperties", map)); - return map; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeInitializer.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeInitializer.java index 60e8a48f8..92ba13ca1 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeInitializer.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeInitializer.java @@ -19,7 +19,6 @@ package org.springframework.cloud.function.adapter.aws; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.function.context.AbstractSpringFunctionAdapterInitializer; import org.springframework.cloud.function.context.config.ContextFunctionCatalogInitializer; import org.springframework.cloud.function.web.source.DestinationResolver; import org.springframework.context.ApplicationContextInitializer; @@ -64,7 +63,7 @@ public class CustomRuntimeInitializer implements ApplicationContextInitializer clazz = Thread.currentThread().getContextClassLoader().loadClass(handler); - if (FunctionInvoker.class.isAssignableFrom(clazz) || AbstractSpringFunctionAdapterInitializer.class.isAssignableFrom(clazz)) { + if (FunctionInvoker.class.isAssignableFrom(clazz)) { return false; } } diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootApiGatewayRequestHandler.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootApiGatewayRequestHandler.java deleted file mode 100644 index 1968738ab..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootApiGatewayRequestHandler.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2012-2020 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 - * - * https://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.adapter.aws; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.codec.binary.Base64; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.http.HttpStatus; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.GenericMessage; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - * @author Semyon Fishman - * @author Markus Gulden - * - * @deprecated since 3.1 in favor of {@link FunctionInvoker} - */ -@Deprecated -public class SpringBootApiGatewayRequestHandler extends - SpringBootRequestHandler { - - @Autowired - private ObjectMapper mapper; - - public SpringBootApiGatewayRequestHandler(Class configurationClass) { - super(configurationClass); - } - - public SpringBootApiGatewayRequestHandler() { - super(); - } - - @Override - protected Object convertEvent(APIGatewayProxyRequestEvent event) { - Object deserializedBody = event.getBody() != null ? deserializeBody(event) : Optional.empty(); - return functionAcceptsMessage() - ? new GenericMessage<>(deserializedBody, getHeaders(event)) - : deserializedBody; - } - - private boolean functionAcceptsMessage() { - return ((FunctionInvocationWrapper) function()).isInputTypeMessage(); - } - - private Object deserializeBody(APIGatewayProxyRequestEvent event) { - try { - return this.mapper.readValue( - (event.getIsBase64Encoded() != null && event.getIsBase64Encoded()) - ? new String(Base64.decodeBase64(event.getBody())) : event.getBody(), - getInputType()); - } - catch (Exception e) { - throw new IllegalStateException("Cannot convert event", e); - } - } - - private MessageHeaders getHeaders(APIGatewayProxyRequestEvent event) { - Map headers = new HashMap<>(); - if (event.getHeaders() != null) { - headers.putAll(event.getHeaders()); - } - if (event.getQueryStringParameters() != null) { - headers.putAll(event.getQueryStringParameters()); - } - if (event.getPathParameters() != null) { - headers.putAll(event.getPathParameters()); - } - headers.put("httpMethod", event.getHttpMethod()); - headers.put("request", event); - return new MessageHeaders(headers); - } - - @Override - protected APIGatewayProxyResponseEvent convertOutput(Object output) { - if (functionReturnsMessage(output)) { - Message message = (Message) output; - return new APIGatewayProxyResponseEvent() - .withStatusCode((Integer) message.getHeaders() - .getOrDefault("statuscode", HttpStatus.OK.value())) - .withHeaders(toResponseHeaders(message.getHeaders())) - .withBody(serializeBody(message.getPayload())); - } - else { - return new APIGatewayProxyResponseEvent() - .withStatusCode(HttpStatus.OK.value()) - .withBody(serializeBody(output)); - - } - } - - private boolean functionReturnsMessage(Object output) { - return output instanceof Message; - } - - private Map toResponseHeaders(MessageHeaders messageHeaders) { - Map responseHeaders = new HashMap<>(); - messageHeaders - .forEach((key, value) -> responseHeaders.put(key, value.toString())); - return responseHeaders; - } - - private String serializeBody(Object body) { - try { - return this.mapper.writeValueAsString(body); - } - catch (JsonProcessingException e) { - throw new IllegalStateException("Cannot convert output", e); - } - } - - @Override - public Object handleRequest(APIGatewayProxyRequestEvent event, Context context) { - Object response = super.handleRequest(event, context); - if (returnsOutput()) { - return response; - } - else { - return new APIGatewayProxyResponseEvent() - .withStatusCode(HttpStatus.OK.value()); - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootKinesisEventHandler.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootKinesisEventHandler.java deleted file mode 100644 index 506d7e03b..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootKinesisEventHandler.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2012-2020 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 - * - * https://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.adapter.aws; - -import java.util.List; -import java.util.stream.Collectors; - -import com.amazonaws.kinesis.deagg.RecordDeaggregator; -import com.amazonaws.services.kinesis.clientlibrary.types.UserRecord; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.KinesisEvent; -import com.fasterxml.jackson.databind.ObjectMapper; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.GenericMessage; - -import static java.util.stream.Collectors.toList; - - -/** - * @param payload type - * @param response type - * @author Mark Fisher - * @author Halvdan Hoem Grelland - * @author Oleg Zhurakousky - * - * @deprecated since 3.1 in favor of {@link FunctionInvoker} - */ -@Deprecated -public class SpringBootKinesisEventHandler - extends SpringBootRequestHandler { - - @Autowired - private ObjectMapper mapper; - - public SpringBootKinesisEventHandler() { - super(); - } - - public SpringBootKinesisEventHandler(Class configurationClass) { - super(configurationClass); - } - - @SuppressWarnings("unchecked") - @Override - public List handleRequest(KinesisEvent event, Context context) { - return (List) super.handleRequest(event, context); - } - - @Override - protected Object convertEvent(KinesisEvent event) { - List payloads = deserializePayloads(event.getRecords()); - - if (((FunctionInvocationWrapper) function()).isInputTypeMessage()) { - return wrapInMessages(payloads); - } - else { - return payloads; - } - } - - private List> wrapInMessages(List payloads) { - return payloads.stream().map(GenericMessage::new).collect(Collectors.toList()); - } - - private List deserializePayloads(List records) { - return RecordDeaggregator.deaggregate(records).stream() - .map(this::deserializeUserRecord).collect(toList()); - } - - @SuppressWarnings("unchecked") - private E deserializeUserRecord(UserRecord userRecord) { - try { - byte[] jsonBytes = userRecord.getData().array(); - return (E) this.mapper.readValue(jsonBytes, getInputType()); - } - catch (Exception e) { - throw new IllegalStateException("Cannot convert event", e); - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootRequestHandler.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootRequestHandler.java deleted file mode 100644 index 95bb543ec..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootRequestHandler.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.adapter.aws; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.cloud.function.context.AbstractSpringFunctionAdapterInitializer; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.messaging.Message; - -/** - * @param event type - * @param result types - * @author Mark Fisher - * @author Oleg Zhurakousky - * - */ -@Deprecated -public class SpringBootRequestHandler extends AbstractSpringFunctionAdapterInitializer - implements RequestHandler { - - public SpringBootRequestHandler(Class configurationClass) { - super(configurationClass); - } - - public SpringBootRequestHandler() { - super(); - } - - @Override - public Object handleRequest(E event, Context context) { - initialize(context); - Object input = acceptsInput() ? convertEvent(event) : ""; - Publisher output = apply(extract(input)); - return result(input, output); - } - - @SuppressWarnings("unchecked") - @Override - protected T result(Object input, Publisher output) { - List result = new ArrayList<>(); - for (Object value : Flux.from(output).toIterable()) { - if (value instanceof Message && !((FunctionInvocationWrapper) this.function()).isOutputTypeMessage()) { - value = ((Message) value).getPayload(); - } - result.add(convertOutput(value)); - } - if (isSingleValue(input) && result.size() == 1) { - return (T) result.get(0); - } - return (T) result; - } - - protected boolean acceptsInput() { - Type inputType = ((FunctionInvocationWrapper) this.function()).getInputType(); - return inputType == null || inputType.equals(Void.class) ? false : true; - } - - protected boolean returnsOutput() { - Type outputType = ((FunctionInvocationWrapper) this.function()).getOutputType(); - return outputType == null || outputType.equals(Void.class) ? false : true; - } - - private boolean isSingleValue(Object input) { - return !(input instanceof Collection); - } - - private Flux extract(Object input) { - if (input instanceof Collection) { - return Flux.fromIterable((Iterable) input); - } - return Flux.just(input); - } - - protected Object convertEvent(E event) { - return event; - } - - @SuppressWarnings("unchecked") - protected O convertOutput(Object output) { - return (O) output; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootStreamHandler.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootStreamHandler.java deleted file mode 100644 index 186f629c3..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/SpringBootStreamHandler.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2017-2019 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 - * - * https://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.adapter.aws; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Collection; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.function.context.AbstractSpringFunctionAdapterInitializer; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class SpringBootStreamHandler extends AbstractSpringFunctionAdapterInitializer - implements RequestStreamHandler { - - @Autowired(required = false) - private ObjectMapper mapper; - - public SpringBootStreamHandler() { - super(); - } - - public SpringBootStreamHandler(Class configurationClass) { - super(configurationClass); - } - - @Override - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - initialize(context); - Object value = convertStream(input); - Publisher flux = apply(extract(value)); - this.mapper.writeValue(output, result(value, flux)); - } - - @Override - protected void initialize(Context context) { - super.initialize(context); - if (this.mapper == null) { - this.mapper = new ObjectMapper(); - } - } - - private Flux extract(Object input) { - if (input instanceof Collection) { - return Flux.fromIterable((Iterable) input); - } - return Flux.just(input); - } - - /* - * Will convert to POJOP or generic map unless user - * explicitly requests InputStream (e.g., Function). - */ - private Object convertStream(InputStream input) { - Object convertedResult = input; - try { - Class inputType = getInputType(); - if (!InputStream.class.isAssignableFrom(inputType)) { - convertedResult = this.mapper.readValue(input, inputType); - } - } - catch (Exception e) { - throw new IllegalStateException("Cannot convert event stream", e); - } - return convertedResult; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring.factories b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring.factories index b10fc836b..caf1d26e9 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring.factories @@ -1,4 +1,2 @@ org.springframework.context.ApplicationContextInitializer=\ -org.springframework.cloud.function.adapter.aws.CustomRuntimeInitializer -org.springframework.boot.env.EnvironmentPostProcessor=\ -org.springframework.cloud.function.adapter.aws.CustomRuntimeEnvironmentPostProcessor \ No newline at end of file +org.springframework.cloud.function.adapter.aws.CustomRuntimeInitializer \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootApiGatewayRequestHandlerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootApiGatewayRequestHandlerTests.java deleted file mode 100644 index 425e040cd..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootApiGatewayRequestHandlerTests.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.adapter.aws; - -import java.util.Base64; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.GenericMessage; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dimitry Declercq - * @author Markus Gulden - */ -public class SpringBootApiGatewayRequestHandlerTests { - - private SpringBootApiGatewayRequestHandler handler; - - @AfterEach - public void after() { - System.clearProperty("function.name"); - } - - @Test - public void supplierBean() { - System.setProperty("function.name", "supplier"); - this.handler = new SpringBootApiGatewayRequestHandler(FunctionConfig.class); - APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent(); - - Object output = this.handler.handleRequest(request, null); - assertThat(output).isInstanceOf(APIGatewayProxyResponseEvent.class); - assertThat(((APIGatewayProxyResponseEvent) output).getStatusCode()) - .isEqualTo(200); - assertThat(((APIGatewayProxyResponseEvent) output).getBody()) - .isEqualTo("\"hello!\""); - } - - @Test - public void functionBean() { - System.setProperty("function.name", "function"); - this.handler = new SpringBootApiGatewayRequestHandler(FunctionConfig.class); - APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent(); - request.setBody("{\"value\":\"foo\"}"); - - Object output = this.handler.handleRequest(request, null); - assertThat(output).isInstanceOf(APIGatewayProxyResponseEvent.class); - assertThat(((APIGatewayProxyResponseEvent) output).getStatusCode()) - .isEqualTo(200); - assertThat(((APIGatewayProxyResponseEvent) output).getBody()) - .isEqualTo("{\"value\":\"FOO\"}"); - - APIGatewayProxyRequestEvent bodyEncryptedRequest = new APIGatewayProxyRequestEvent(); - bodyEncryptedRequest.setBody( - Base64.getEncoder().encodeToString("{\"value\":\"foo\"}".getBytes())); - bodyEncryptedRequest.setIsBase64Encoded(true); - - output = this.handler.handleRequest(bodyEncryptedRequest, null); - assertThat(output).isInstanceOf(APIGatewayProxyResponseEvent.class); - assertThat(((APIGatewayProxyResponseEvent) output).getStatusCode()) - .isEqualTo(200); - assertThat(((APIGatewayProxyResponseEvent) output).getBody()) - .isEqualTo("{\"value\":\"FOO\"}"); - } - - @Test - public void consumerBean() { - System.setProperty("function.name", "consumer"); - this.handler = new SpringBootApiGatewayRequestHandler(FunctionConfig.class); - APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent(); - request.setBody("\"strVal\":\"test for consumer\""); - - Object output = this.handler.handleRequest(request, null); - assertThat(output).isInstanceOf(APIGatewayProxyResponseEvent.class); - assertThat(((APIGatewayProxyResponseEvent) output).getStatusCode()) - .isEqualTo(200); - } - - @Test - public void functionMessageBean() { - this.handler = new SpringBootApiGatewayRequestHandler( - FunctionMessageConfig.class); - APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent(); - request.setBody("{\"value\":\"foo\"}"); - - Object output = this.handler.handleRequest(request, null); - assertThat(output).isInstanceOf(APIGatewayProxyResponseEvent.class); - assertThat(((APIGatewayProxyResponseEvent) output).getStatusCode()) - .isEqualTo(200); - assertThat(((APIGatewayProxyResponseEvent) output).getHeaders().get("spring")) - .isEqualTo("cloud"); - assertThat(((APIGatewayProxyResponseEvent) output).getBody()) - .isEqualTo("{\"value\":\"FOO\"}"); - } - - - @Test - public void functionMessageBeanWithRequestParameters() { - this.handler = new SpringBootApiGatewayRequestHandler( - FunctionMessageEchoReqParametersConfig.class); - APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent(); - request.setPathParameters(Collections.singletonMap("path", "pathValue")); - request.setQueryStringParameters(Collections.singletonMap("query", "queryValue")); - request.setHeaders(Collections.singletonMap("test-header", "headerValue")); - request.setHttpMethod("GET"); - - Object output = this.handler.handleRequest(request, null); - assertThat(output).isInstanceOf(APIGatewayProxyResponseEvent.class); - assertThat(((APIGatewayProxyResponseEvent) output).getStatusCode()) - .isEqualTo(200); - assertThat(((APIGatewayProxyResponseEvent) output).getHeaders().get("path")) - .isEqualTo("pathValue"); - assertThat(((APIGatewayProxyResponseEvent) output).getHeaders().get("query")) - .isEqualTo("queryValue"); - assertThat( - ((APIGatewayProxyResponseEvent) output).getHeaders().get("test-header")) - .isEqualTo("headerValue"); - assertThat(((APIGatewayProxyResponseEvent) output).getHeaders().get("httpMethod")) - .isEqualTo("GET"); - assertThat(((APIGatewayProxyResponseEvent) output).getBody()) - .isEqualTo("{\"value\":\"body\"}"); - - } - - @Test - public void functionMessageBeanWithEmptyResponse() { - this.handler = new SpringBootApiGatewayRequestHandler( - FunctionMessageConsumerConfig.class); - APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent(); - - Object output = this.handler.handleRequest(request, null); - assertThat(output).isInstanceOf(APIGatewayProxyResponseEvent.class); - assertThat(((APIGatewayProxyResponseEvent) output).getStatusCode()) - .isEqualTo(200); - assertThat(((APIGatewayProxyResponseEvent) output).getBody()).isNull(); - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class FunctionConfig { - - @Bean - public Function function() { - return foo -> new Bar(foo.getValue().toUpperCase()); - } - - @Bean - public Consumer consumer() { - return v -> System.out.println(v); - } - - @Bean - public Supplier supplier() { - return () -> "hello!"; - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class FunctionMessageConfig { - - @Bean - public Function, Message> function() { - return (foo -> { - Map headers = Collections.singletonMap("spring", "cloud"); - return new GenericMessage<>( - new Bar(foo.getPayload().getValue().toUpperCase()), headers); - }); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class FunctionMessageEchoReqParametersConfig { - - @Bean - public Function, Message> function() { - return (message -> { - Map headers = new HashMap<>(); - headers.put("path", message.getHeaders().get("path")); - headers.put("query", message.getHeaders().get("query")); - headers.put("test-header", message.getHeaders().get("test-header")); - headers.put("httpMethod", message.getHeaders().get("httpMethod")); - return new GenericMessage<>(new Bar("body"), headers); - }); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class FunctionMessageConsumerConfig { - - @Bean - public Consumer> function() { - return (foo -> { - }); - } - - } - - protected static class Foo { - - private String value; - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - - protected static class Bar { - - private String value; - - public Bar() { - } - - public Bar(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootKinesisEventHandlerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootKinesisEventHandlerTests.java deleted file mode 100644 index 89d26f0da..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootKinesisEventHandlerTests.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.adapter.aws; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; - -import com.amazonaws.kinesis.agg.AggRecord; -import com.amazonaws.kinesis.agg.RecordAggregator; -import com.amazonaws.services.lambda.runtime.events.KinesisEvent; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.messaging.Message; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; - -/** - * @author Halvdan Hoem Grelland - */ -@Disabled -public class SpringBootKinesisEventHandlerTests { - - private static final ObjectMapper mapper = new ObjectMapper(); - - private SpringBootKinesisEventHandler handler; - - private static KinesisEvent asKinesisEvent(List payloads) { - KinesisEvent kinesisEvent = new KinesisEvent(); - - List kinesisEventRecords = new ArrayList<>(); - - for (Object payload : payloads) { - KinesisEvent.Record record = new KinesisEvent.Record(); - record.setData(asJsonByteBuffer(payload)); - - KinesisEvent.KinesisEventRecord kinesisEventRecord = new KinesisEvent.KinesisEventRecord(); - kinesisEventRecord.setKinesis(record); - - kinesisEventRecords.add(kinesisEventRecord); - } - - kinesisEvent.setRecords(kinesisEventRecords); - - return kinesisEvent; - } - - private static KinesisEvent asAggregatedKinesisEvent(List payloads) { - RecordAggregator aggregator = new RecordAggregator(); - - payloads.stream().map(SpringBootKinesisEventHandlerTests::asJsonByteBuffer) - .forEach(buffer -> { - try { - aggregator.addUserRecord("fakePartitionKey", buffer.array()); - } - catch (Exception e) { - fail("Creating aggregated record failed"); - } - }); - - AggRecord aggRecord = aggregator.clearAndGet(); - - KinesisEvent.Record record = new KinesisEvent.Record(); - record.setData(ByteBuffer.wrap(aggRecord.toRecordBytes())); - - KinesisEvent.KinesisEventRecord wrappingRecord = new KinesisEvent.KinesisEventRecord(); - wrappingRecord.setKinesis(record); - wrappingRecord.setEventVersion("1.0"); - - KinesisEvent event = new KinesisEvent(); - event.setRecords(singletonList(wrappingRecord)); - - return event; - } - - private static ByteBuffer asJsonByteBuffer(Object object) { - try { - return ByteBuffer.wrap(mapper.writeValueAsBytes(object)); - } - catch (JsonProcessingException e) { - fail("Setting up test data failed", e); - throw new RuntimeException(e); - } - } - - @Test - public void functionBeanHandlesKinesisEvent() throws Exception { - this.handler = new SpringBootKinesisEventHandler<>(FunctionConfig.class); - - KinesisEvent event = asKinesisEvent(singletonList(new Foo("foo"))); - - List output = this.handler.handleRequest(event, null); - - assertThat(output).containsExactly(new Bar("FOO")); - } - - @Test - public void functionBeanHandlesAggregatedKinesisEvent() throws Exception { - this.handler = new SpringBootKinesisEventHandler<>(FunctionConfig.class); - - List events = asList(new Foo("foo"), new Foo("bar"), new Foo("baz")); - KinesisEvent aggregatedEvent = asAggregatedKinesisEvent(events); - - List output = this.handler.handleRequest(aggregatedEvent, null); - - assertThat(output).containsExactly(new Bar("FOO"), new Bar("BAR"), - new Bar("BAZ")); - } - - @Test - public void functionMessageBean() throws Exception { - this.handler = new SpringBootKinesisEventHandler<>(FunctionMessageConfig.class); - - KinesisEvent event = asKinesisEvent(asList(new Foo("foo"), new Foo("bar"))); - - List output = this.handler.handleRequest(event, null); - - assertThat(output).containsExactly(new Bar("FOO"), new Bar("BAR")); - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class FunctionConfig { - - @Bean - public Function function() { - return foo -> new Bar(foo.getValue().toUpperCase()); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class FunctionMessageConfig { - - @Bean - public Function, Bar> function() { - return foo -> new Bar(foo.getPayload().getValue().toUpperCase()); - } - - } - - protected static class Foo { - - private String value; - - public Foo() { - } - - public Foo(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - - protected static class Bar { - - private String value; - - public Bar() { - } - - public Bar(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Bar bar = (Bar) o; - return Objects.equals(this.value, bar.value); - } - - @Override - public int hashCode() { - return Objects.hash(this.value); - } - - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootRequestHandlerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootRequestHandlerTests.java deleted file mode 100644 index 979ad0c1a..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootRequestHandlerTests.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2017-2020 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 - * - * https://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.adapter.aws; - -import java.util.function.Function; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -public class SpringBootRequestHandlerTests { - - private SpringBootRequestHandler handler; - - @BeforeEach - public void after() { - System.clearProperty("spring.cloud.function.definition"); - } - - @Test - public void functionBean() throws Exception { - this.handler = new SpringBootRequestHandler(FunctionConfig.class); - Object output = this.handler.handleRequest(new Foo("foo"), null); - assertThat(output).isInstanceOf(Bar.class); - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class FunctionConfig { - - @Bean - public Function function() { - return foo -> new Bar(foo.getValue().toUpperCase()); - } - - } - - protected static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - - protected static class Bar { - - private String value; - - public Bar() { - } - - public Bar(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootStreamHandlerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootStreamHandlerTests.java deleted file mode 100644 index c9aa2d935..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/SpringBootStreamHandlerTests.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.adapter.aws; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.util.Map; -import java.util.function.Function; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.util.Assert; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class SpringBootStreamHandlerTests { - - private SpringBootStreamHandler handler; - - @BeforeEach - public void before() { - System.clearProperty("function.name"); - } - - @Test - public void functionBeanWithJacksonConfig() throws Exception { - this.handler = new SpringBootStreamHandler(FunctionConfigWithJackson.class); - this.handler.initialize(null); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - this.handler.handleRequest( - new ByteArrayInputStream("{\"value\":\"foo\"}".getBytes()), output, null); - assertThat(output.toString()).isEqualTo("{\"value\":\"FOO\"}"); - } - - @Test - public void functionBeanWithoutJacksonConfig() throws Exception { - this.handler = new SpringBootStreamHandler(FunctionConfigWithoutJackson.class); - this.handler.initialize(null); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - this.handler.handleRequest( - new ByteArrayInputStream("{\"value\":\"foo\"}".getBytes()), output, null); - assertThat(output.toString()).isEqualTo("{\"value\":\"FOO\"}"); - } - - @Test - public void functionNonFluxBeanNoCatalog() throws Exception { - this.handler = new SpringBootStreamHandler(NoCatalogNonFluxFunctionConfig.class); - this.handler.initialize(null); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - this.handler.handleRequest( - new ByteArrayInputStream("{\"value\":\"foo\"}".getBytes()), output, null); - assertThat(output.toString()).isEqualTo("{\"value\":\"FOO\"}"); - } - - @Test - public void functionFluxBeanNoCatalog() throws Exception { - this.handler = new SpringBootStreamHandler(NoCatalogFluxFunctionConfig.class); - this.handler.initialize(null); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - this.handler.handleRequest( - new ByteArrayInputStream("{\"value\":\"foo\"}".getBytes()), output, null); - assertThat(output.toString()).isEqualTo("{\"value\":\"FOO\"}"); - } - - @Test - public void typelessFunctionConfig() throws Exception { - this.handler = new SpringBootStreamHandler(TypelessFunctionConfig.class); - this.handler.initialize(null); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - this.handler.handleRequest( - new ByteArrayInputStream("{\"value\":\"foo\"}".getBytes()), output, null); - assertThat(output.toString()).isEqualTo("{\"value\":\"foo\"}"); - } - - @Test - public void inputStreamFunctionConfig() throws Exception { - this.handler = new SpringBootStreamHandler(InputStreamFunctionConfig.class); - this.handler.initialize(null); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - this.handler.handleRequest( - new ByteArrayInputStream("{\"value\":\"foo\"}".getBytes()), output, null); - assertThat(output.toString()).isEqualTo("{\"value\":\"FOO\"}"); - } - - @Configuration - protected static class NoCatalogNonFluxFunctionConfig { - - @Bean - public Function function() { - return foo -> new Bar(foo.getValue().toUpperCase()); - } - - } - - @Configuration - protected static class NoCatalogFluxFunctionConfig { - - @Bean - public Function, Flux> function() { - return flux -> flux.map(foo -> new Bar(foo.getValue().toUpperCase())); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class FunctionConfigWithJackson { - - @Bean - public Function function() { - return foo -> new Bar(foo.getValue().toUpperCase()); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class FunctionConfigWithoutJackson { - - @Bean - public Function function() { - return foo -> new Bar(foo.getValue().toUpperCase()); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class TypelessFunctionConfig { - - @Bean - public Function function() { - return value -> { - Assert.isTrue(value instanceof Map, "Expected value should be Map"); - return value; - }; - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class }) - protected static class InputStreamFunctionConfig { - - @Autowired - private ObjectMapper mapper; - - @Bean - public Function function() { - return value -> { - try { - Foo foo = this.mapper.readValue((InputStream) value, Foo.class); - return new Bar(foo.getValue().toUpperCase()); - } - catch (Exception e) { - throw new IllegalStateException("Failed test", e); - } - }; - } - - } - - protected static class Foo { - - private String value; - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - - protected static class Bar { - - private String value; - - public Bar() { - } - - public Bar(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/pom.xml index 0b0ed1eab..fed34cf64 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/pom.xml +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/pom.xml @@ -13,7 +13,7 @@ org.springframework.cloud spring-cloud-function-adapter-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootHttpRequestHandler.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootHttpRequestHandler.java deleted file mode 100644 index 75ae9b568..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootHttpRequestHandler.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.adapter.azure; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.HttpResponseMessage; -import com.microsoft.azure.functions.HttpResponseMessage.Builder; - -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.GenericMessage; - -/** - * Implementation of HTTP Request Handler for Azure which supports - * HttpRequestMessage and HttpResponseMessage the types required by - * Azure Functions for HTTP-triggered functions. - * - * @param input type - * @author Markus Gulden - * - * @since 2.1 - * @deprecated since 3.2 in favor of {@link FunctionInvoker} - */ -@Deprecated -public class AzureSpringBootHttpRequestHandler extends - AzureSpringBootRequestHandler, HttpResponseMessage> { - - public AzureSpringBootHttpRequestHandler(Class configurationClass) { - super(configurationClass); - } - - public AzureSpringBootHttpRequestHandler() { - super(); - } - - @SuppressWarnings("rawtypes") - @Override - protected Object convertEvent(HttpRequestMessage event) { - - if (event.getBody() != null) { - if (functionAcceptsMessage()) { - return new GenericMessage(event.getBody(), getHeaders(event)); - } - else { - return event.getBody(); - } - } - else { - if (functionAcceptsMessage()) { - return new GenericMessage(Optional.empty(), getHeaders(event)); - } - else { - return Optional.empty(); - } - } - } - - protected boolean functionAcceptsMessage() { - - return ((FunctionInvocationWrapper) function()).isInputTypeMessage(); - } - - private MessageHeaders getHeaders(HttpRequestMessage event) { - Map headers = new HashMap(); - - if (event.getHeaders() != null) { - headers.putAll(event.getHeaders()); - } - if (event.getQueryParameters() != null) { - headers.putAll(event.getQueryParameters()); - } - if (event.getUri() != null) { - headers.put("path", event.getUri().getPath()); - } - - if (event.getHttpMethod() != null) { - headers.put("httpMethod", event.getHttpMethod().toString()); - } - - headers.put("request", event.getBody()); - return new MessageHeaders(headers); - } - - @SuppressWarnings("unchecked") - @Override - protected HttpResponseMessage convertOutput(Object input, Object output) { - HttpRequestMessage requestMessage = (HttpRequestMessage) input; - if (functionReturnsMessage(output)) { - Message message = (Message) output; - Builder builder = requestMessage - .createResponseBuilder(com.microsoft.azure.functions.HttpStatus.OK) - .body(message.getPayload()); - for (Map.Entry entry : message.getHeaders().entrySet()) { - if (entry.getValue() != null) { - builder = builder.header(entry.getKey(), entry.getValue().toString()); - } - } - return builder.build(); - } - else { - return requestMessage - .createResponseBuilder(com.microsoft.azure.functions.HttpStatus.OK) - .body(output).build(); - } - } - - @Override - public HttpResponseMessage handleRequest(HttpRequestMessage event, - ExecutionContext context) { - HttpResponseMessage result = super.handleRequest(event, context); - if (result == null) { - result = event - .createResponseBuilder(com.microsoft.azure.functions.HttpStatus.OK) - .build(); - } - return result; - } - - protected boolean functionReturnsMessage(Object output) { - return output instanceof Message; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandler.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandler.java deleted file mode 100644 index 295e7b63a..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandler.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2017-2021 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 - * - * https://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.adapter.azure; - -import java.util.Collection; -import java.util.function.Function; -import java.util.logging.Logger; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.OutputBinding; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.function.context.AbstractSpringFunctionAdapterInitializer; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -/** - * @param input type - * @param result type - * @author Soby Chacko - * @author Oleg Zhurakousky - * - * @deprecated since 3.2 in favor of {@link FunctionInvoker} - */ -@Deprecated -public class AzureSpringBootRequestHandler extends AbstractSpringFunctionAdapterInitializer { - - @SuppressWarnings("rawtypes") - private static AzureSpringBootRequestHandler thisInitializer; - - private static FunctionCatalog functionCatalog; - - private final static ExecutionContextDelegate EXECUTION_CTX_DELEGATE = new ExecutionContextDelegate(); - - public AzureSpringBootRequestHandler(Class configurationClass) { - super(configurationClass); - } - - public AzureSpringBootRequestHandler() { - super(); - } - - public O handleRequest(ExecutionContext context) { - return this.handleRequest(null, context); - } - - @Override - public void close() { - thisInitializer = null; - super.close(); - } - - @SuppressWarnings("unchecked") - public O handleRequest(I input, ExecutionContext context) { - EXECUTION_CTX_DELEGATE.targetContext = context; - String name = ""; - try { - if (context != null) { - name = context.getFunctionName(); - context.getLogger().info("Handler processing a request for: " + name); - } - - /* - * We need this "caching" logic to ensure that we don't reinitialize Spring Boot app on each invocation - * since Azure creates a new instance of this handler for each invocation, - * see https://github.com/spring-cloud/spring-cloud-function/issues/425 - */ - if (thisInitializer == null /*|| !thisInitializer.functionName.equals(name)*/) { - initialize(EXECUTION_CTX_DELEGATE); - functionCatalog = this.catalog; - thisInitializer = this; - return (O) thisInitializer.handleRequest(input, context); - } - else { - this.catalog = functionCatalog; - thisInitializer.clear(name); - Publisher events = input == null ? Mono.empty() : extract(convertEvent(input)); - if (events instanceof Flux) { - events = Flux.from(events).map(v -> this.toMessage(v, context)); - } - Publisher output = thisInitializer.apply(events); - O result = result(input, output); - if (context != null) { - context.getLogger().fine("Handler processed a request for: " + name); - } - return result; - } - } - catch (Throwable ex) { - if (context != null) { - context.getLogger().throwing(getClass().getName(), "handle", ex); - } - throw new RuntimeException(ex); - } - } - - public void handleOutput(I input, OutputBinding binding, - ExecutionContext context) { - O result = handleRequest(input, context); - binding.setValue(result); - } - - @Override - protected String doResolveName(Object targetContext) { - return ((ExecutionContext) targetContext).getFunctionName(); - } - - protected Object convertEvent(I input) { - return input; - } - - protected Flux extract(Object input) { - if (!isSingleInput(this.getFunction(), input)) { - return Flux.fromIterable((Iterable) input); - } - return Flux.just(input); - } - - protected boolean isSingleInput(Function function, Object input) { - if (!(input instanceof Collection)) { - return true; - } - if (function != null) { - return Collection.class - .isAssignableFrom(((FunctionInvocationWrapper) function).getRawInputType()); - } - return ((Collection) input).size() <= 1; - } - - protected boolean isSingleOutput(Function function, Object output) { - if (!(output instanceof Collection)) { - return true; - } - if (function != null) { - Class outputType = FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(((FunctionInvocationWrapper) function).getOutputType())); - return Collection.class.isAssignableFrom(outputType); - } - return ((Collection) output).size() <= 1; - } - - @SuppressWarnings("rawtypes") - private Message toMessage(Object value, ExecutionContext context) { - if (value instanceof Message) { - return (Message) value; - } - else { - Object payload = value; - if (value instanceof HttpRequestMessage) { - payload = ((HttpRequestMessage) value).getBody(); - if (payload == null) { - payload = ((HttpRequestMessage) value).getQueryParameters(); - } - } - return MessageBuilder.withPayload(payload) - .setHeader(AbstractSpringFunctionAdapterInitializer.TARGET_EXECUTION_CTX_NAME, context).build(); - } - } - - - private static class ExecutionContextDelegate implements ExecutionContext { - - ExecutionContext targetContext; - - @Override - public Logger getLogger() { - if (targetContext == null || targetContext.getLogger() == null) { - return Logger.getAnonymousLogger(); - } - return targetContext.getLogger(); - } - - @Override - public String getInvocationId() { - return targetContext.getInvocationId(); - } - - @Override - public String getFunctionName() { - return targetContext.getFunctionName(); - } - - @Override - public String toString() { - return "ExecutionContextDelegate over: " + this.targetContext; - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/FunctionInvoker.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/FunctionInvoker.java index 7ea1232a7..a400aa797 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/FunctionInvoker.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/FunctionInvoker.java @@ -44,7 +44,6 @@ import org.springframework.boot.WebApplicationType; import org.springframework.cloud.function.context.FunctionCatalog; 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.FunctionTypeUtils; import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry; import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; @@ -162,7 +161,7 @@ public class FunctionInvoker { Type type = FunctionContextUtils. findType(functionDefinition, APPLICATION_CONTEXT.getBeanFactory()); - functionRegistration = functionRegistration.type(new FunctionType(type)); + functionRegistration = functionRegistration.type(type); ((FunctionRegistry) FUNCTION_CATALOG).register(functionRegistration); } diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml index f348aac6a..091a93738 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml @@ -11,7 +11,7 @@ spring-cloud-function-adapter-parent org.springframework.cloud - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk/pom.xml index a7fbb0e60..149ca38b5 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk/pom.xml +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk/pom.xml @@ -13,7 +13,7 @@ org.springframework.cloud spring-cloud-function-adapter-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/pom.xml index 3e38496f9..9853012bb 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/pom.xml +++ b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-function-adapter-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT spring-cloud-function-grpc-cloudevent-ext spring-cloud-function-grpc-cloudevent-ext diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-grpc/pom.xml index 2dbdff528..bec41efae 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/pom.xml +++ b/spring-cloud-function-adapters/spring-cloud-function-grpc/pom.xml @@ -12,7 +12,7 @@ org.springframework.cloud spring-cloud-function-adapter-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-compiler/pom.xml b/spring-cloud-function-compiler/pom.xml index 602f0449d..3592c6a23 100644 --- a/spring-cloud-function-compiler/pom.xml +++ b/spring-cloud-function-compiler/pom.xml @@ -12,7 +12,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-context/pom.xml b/spring-cloud-function-context/pom.xml index 2e8642d69..61b9ab7f8 100644 --- a/spring-cloud-function-context/pom.xml +++ b/spring-cloud-function-context/pom.xml @@ -12,7 +12,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT @@ -46,6 +46,19 @@ com.fasterxml.jackson.module jackson-module-kotlin true +<<<<<<< HEAD +======= + + + javax.annotation + javax.annotation-api + 1.3.2 + + + javax.activation + javax.activation-api + 1.2.0 +>>>>>>> 4.x org.springframework.boot diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/AbstractSpringFunctionAdapterInitializer.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/AbstractSpringFunctionAdapterInitializer.java index 8aea9e37f..95b64e5d2 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/AbstractSpringFunctionAdapterInitializer.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/AbstractSpringFunctionAdapterInitializer.java @@ -141,7 +141,7 @@ public abstract class AbstractSpringFunctionAdapterInitializer implements Clo return FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(((FunctionInvocationWrapper) func).getInputType())); } if (functionRegistration != null) { - return functionRegistration.getType().getInputType(); + return FunctionTypeUtils.getRawType(FunctionTypeUtils.getInputType(functionRegistration.getType())); } return Object.class; } @@ -287,7 +287,7 @@ public abstract class AbstractSpringFunctionAdapterInitializer implements Clo Type type = FunctionContextUtils. findType(name, this.context.getBeanFactory()); - this.functionRegistration = functionRegistration.type(new FunctionType(type)); + this.functionRegistration = functionRegistration.type(type); ((FunctionRegistry) this.catalog).register(functionRegistration); return this.catalog.lookup(name); 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 536ce9ac2..8be661d2f 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 @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2021 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. @@ -27,27 +27,13 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; -import net.jodah.typetools.TypeResolver; import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - import org.springframework.beans.factory.BeanNameAware; import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.cloud.function.core.FluxConsumer; -import org.springframework.cloud.function.core.FluxFunction; -import org.springframework.cloud.function.core.FluxSupplier; -import org.springframework.cloud.function.core.FluxToMonoFunction; -import org.springframework.cloud.function.core.FluxedConsumer; -import org.springframework.cloud.function.core.FluxedFunction; -import org.springframework.cloud.function.core.MonoSupplier; -import org.springframework.cloud.function.core.MonoToFluxFunction; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; - - /** * @param target type * @author Dave Syer @@ -71,7 +57,7 @@ public class FunctionRegistration implements BeanNameAware { private T target; - private FunctionType type; + private Type type; /** * Creates instance of FunctionRegistration. @@ -105,7 +91,7 @@ public class FunctionRegistration implements BeanNameAware { this.names.addAll(names); } - public FunctionType getType() { + public Type getType() { return this.type; } @@ -119,25 +105,33 @@ public class FunctionRegistration implements BeanNameAware { } public FunctionRegistration type(Type type) { - return type(FunctionType.of(type)); - } - - public FunctionRegistration type(FunctionType type) { - - Type t = FunctionTypeUtils.discoverFunctionTypeFromClass(this.target.getClass()); - if (t == null) { // only valid for Kafka Stream KStream[] return type. + Type discoveredFunctionType = FunctionTypeUtils.discoverFunctionTypeFromClass(this.target.getClass()); + if (discoveredFunctionType == null) { // only valid for Kafka Stream KStream[] return type. return null; } - FunctionType discoveredFunctionType = FunctionType.of(t); - Class inputType = TypeResolver.resolveRawClass(discoveredFunctionType.getInputType(), null); - Class outputType = TypeResolver.resolveRawClass(discoveredFunctionType.getOutputType(), null); - - if (!(inputType.isAssignableFrom(TypeResolver.resolveRawClass(type.getInputType(), null)) - && outputType.isAssignableFrom(TypeResolver.resolveRawClass(type.getOutputType(), null)))) { - throw new IllegalStateException("Discovered function type does not match provided function type. Discovered: " - + discoveredFunctionType + "; Provided: " + type); - } this.type = type; + + Class inputType = FunctionTypeUtils.getRawType(FunctionTypeUtils.getInputType(discoveredFunctionType)); + Class outputType = FunctionTypeUtils.getRawType(FunctionTypeUtils.getOutputType(discoveredFunctionType)); + + if (inputType != null && inputType != Object.class && outputType != null && outputType != Object.class) { + Assert.isTrue((inputType.isAssignableFrom(FunctionTypeUtils.getRawType(FunctionTypeUtils.getInputType(type))) + && outputType.isAssignableFrom(FunctionTypeUtils.getRawType(FunctionTypeUtils.getOutputType(type)))), + "Discovered function type does not match provided function type. Discovered: " + + discoveredFunctionType + "; Provided: " + type); + } + else if (inputType == null && outputType != Object.class) { + Assert.isTrue(outputType.isAssignableFrom(FunctionTypeUtils.getRawType(FunctionTypeUtils.getOutputType(type))), + "Discovered function type does not match provided function type. Discovered: " + + discoveredFunctionType + "; Provided: " + type); + } + else if (outputType == null && inputType != Object.class) { + Assert.isTrue(inputType.isAssignableFrom(FunctionTypeUtils.getRawType(FunctionTypeUtils.getInputType(type))), + "Discovered function type does not match provided function type. Discovered: " + + discoveredFunctionType + "; Provided: " + type); + } + + return this; } @@ -175,52 +169,30 @@ public class FunctionRegistration implements BeanNameAware { * */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public FunctionRegistration wrap() { - this.isFunctionSignatureSupported(); - FunctionRegistration result; - if (this.type == null) { - result = (FunctionRegistration) this; - } - else if (this.target instanceof RoutingFunction) { - S target = (S) this.target; - result = new FunctionRegistration(target); - result.type(this.type.getType()); - result = result.target(target).names(this.names) - .type(result.type.wrap(Flux.class)).properties(this.properties); - } - else { - S target = (S) this.target; - result = new FunctionRegistration(target); - result.type(this.type.getType()); - - if (!this.type.isWrapper()) { - target = target instanceof Supplier - ? (S) new FluxSupplier((Supplier) target) - : target instanceof Function - ? (S) new FluxFunction((Function) target) - : (S) new FluxConsumer((Consumer) target); - } - else if (Mono.class.isAssignableFrom(this.type.getOutputWrapper())) { - target = target instanceof Supplier - ? (S) new MonoSupplier((Supplier) target) - : (S) new FluxToMonoFunction((Function) target); - } - else if (Mono.class.isAssignableFrom(this.type.getInputWrapper())) { - target = (S) new MonoToFluxFunction((Function) target); - } - else if (target instanceof Consumer) { - target = (S) new FluxedConsumer((Consumer) target); - } - else if (target instanceof Function) { - target = (S) new FluxedFunction((Function) target); - } - result = result.target(target).names(this.names) - .type(result.type.wrap(Flux.class)).properties(this.properties); - } - - return result; - } +// @SuppressWarnings({ "unchecked", "rawtypes" }) +// public FunctionRegistration wrap() { +// this.isFunctionSignatureSupported(); +// FunctionRegistration result; +// if (this.type == null) { +// result = (FunctionRegistration) this; +// } +// else if (this.target instanceof RoutingFunction) { +// S target = (S) this.target; +// result = new FunctionRegistration(target); +// result.type(this.type.getType()); +// result = result.target(target).names(this.names) +// .type(result.type.wrap(Flux.class)).properties(this.properties); +// } +// else { +// S target = (S) this.target; +// result = new FunctionRegistration(target); +// result.type(this.type.getType()); +// result = result.target(target).names(this.names) +// .type(result.type.wrap(Flux.class)).properties(this.properties); +// } +// +// return result; +// } @Override public void setBeanName(String name) { @@ -229,12 +201,12 @@ public class FunctionRegistration implements BeanNameAware { } } - private void isFunctionSignatureSupported() { - if (type != null) { - Assert.isTrue(!(Mono.class.isAssignableFrom(this.type.getOutputWrapper()) - && Mono.class.isAssignableFrom(this.type.getInputWrapper())), - "Function is not supported."); - } - } +// private void isFunctionSignatureSupported() { +// if (type != null) { +// Assert.isTrue(!(Mono.class.isAssignableFrom(this.type.getOutputWrapper()) +// && Mono.class.isAssignableFrom(this.type.getInputWrapper())), +// "Function is not supported."); +// } +// } } 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 deleted file mode 100644 index 9d9723361..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionType.java +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import reactor.core.publisher.Flux; - - -import org.springframework.core.ResolvableType; -import org.springframework.core.io.support.SpringFactoriesLoader; -import org.springframework.messaging.Message; -import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - * - */ -public class FunctionType { - - /** - * Unclassified function types. - */ - public static FunctionType UNCLASSIFIED = new FunctionType(ResolvableType - .forClassWithGenerics(Function.class, Object.class, Object.class).getType()); - - private static List transformers; - - private Type type; - - private Class inputType; - - private Class outputType; - - private Class inputWrapper; - - private Class outputWrapper; - - private boolean message; - - public FunctionType(Type type) { - this.type = functionType(type); - this.inputWrapper = findType(ParamType.INPUT_WRAPPER); - this.outputWrapper = findType(ParamType.OUTPUT_WRAPPER); - this.inputType = findType(ParamType.INPUT); - this.outputType = findType(ParamType.OUTPUT); - this.message = messageType(); - resetType(); - } - - /* - * Experimental for now. Used (reflectively) in FunctionCreatorConfiguration to effectively - * map an existing FunctionType created by one class loader to another. - */ - @SuppressWarnings("unused") // it is used - private FunctionType(Object functionType) throws Exception { - Field[] fields = functionType.getClass().getDeclaredFields(); - for (Field field : fields) { - if (!Modifier.isStatic(field.getModifiers())) { - field.setAccessible(true); - Field thisField = ReflectionUtils.findField(this.getClass(), field.getName()); - thisField.setAccessible(true); - thisField.set(this, field.get(functionType)); - } - } - } - - public static boolean isWrapper(Type type) { - if (type instanceof ParameterizedType) { - type = ((ParameterizedType) type).getRawType(); - } - if (transformers == null) { - transformers = new ArrayList<>(); - transformers.addAll( - SpringFactoriesLoader.loadFactories(WrapperDetector.class, null)); - } - for (WrapperDetector transformer : transformers) { - if (transformer.isWrapper(type)) { - return true; - } - } - return false; - } - - public static FunctionType of(Type function) { - FunctionType ft = new FunctionType(function); - if (!ft.isWrapper() && !(ft.type instanceof ParameterizedType)) { - Type[] genericInterfaces = ((Class) function).getGenericInterfaces(); - if (!ObjectUtils.isEmpty(genericInterfaces)) { - ft.type = genericInterfaces[0]; - } - } - return ft; - } - - public static FunctionType from(Class input) { - return new FunctionType(ResolvableType - .forClassWithGenerics(Function.class, input, Object.class).getType()); - } - - public static FunctionType supplier(Class input) { - return new FunctionType( - ResolvableType.forClassWithGenerics(Supplier.class, input).getType()); - } - - public static FunctionType consumer(Class input) { - return new FunctionType( - ResolvableType.forClassWithGenerics(Consumer.class, input).getType()); - } - - public static FunctionType compose(FunctionType input, FunctionType output) { - ResolvableType inputGeneric = input(input); - ResolvableType outputGeneric = output(output); - if (!isWrapper(outputGeneric.getType())) { - ResolvableType inputOutput = output(input); - if (isWrapper(inputOutput.getType())) { - outputGeneric = wrap(input, - extractClass(inputOutput.getType(), ParamType.OUTPUT_WRAPPER), - extractClass(outputGeneric.getType(), ParamType.OUTPUT)); - } - } - return new FunctionType(ResolvableType - .forClassWithGenerics(Function.class, inputGeneric, outputGeneric) - .getType()); - } - - public Type getType() { - return this.type; - } - - public Class getInputWrapper() { - return this.inputWrapper; - } - - public Class getOutputWrapper() { - return this.outputWrapper; - } - - public Class getInputType() { - return this.inputType; - } - - public Class getOutputType() { - return this.outputType; - } - - public boolean isMessage() { - return this.message; - } - - public boolean isWrapper() { - return isWrapper(getInputWrapper()) || isWrapper(getOutputWrapper()); - } - - public FunctionType to(Class output) { - ResolvableType inputGeneric = input(this); - ResolvableType outputGeneric = output(output); - return new FunctionType(ResolvableType - .forClassWithGenerics(Function.class, inputGeneric, outputGeneric) - .getType()); - } - - public FunctionType message() { - if (isMessage()) { - return this; - } - ResolvableType inputGeneric = message(getInputType()); - ResolvableType outputGeneric = message(getOutputType()); - if (isWrapper(getInputWrapper())) { - inputGeneric = ResolvableType.forClassWithGenerics(getInputWrapper(), - inputGeneric); - outputGeneric = ResolvableType.forClassWithGenerics(getInputWrapper(), - outputGeneric); - } - return new FunctionType(ResolvableType - .forClassWithGenerics(Function.class, inputGeneric, outputGeneric) - .getType()); - } - - public FunctionType wrap(Class input, Class output) { - if (!isWrapper(input) && !isWrapper(output)) { - return this; - } - else if (isWrapper(input) && isWrapper(output)) { - if (input.isAssignableFrom(getInputWrapper()) - && output.isAssignableFrom(getOutputWrapper())) { - return this; - } - return new FunctionType(ResolvableType.forClassWithGenerics(Function.class, - wrapper(input, getInputType()), wrapper(output, getOutputType())) - .getType()); - } - else { - throw new IllegalArgumentException("Both wrapper types must be wrappers in (" - + input + ", " + output + ")"); - } - } - - public FunctionType wrap(Class wrapper) { - return wrap(wrapper, wrapper); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((this.inputType == null) ? 0 : this.inputType.toString().hashCode()); - result = prime * result + ((this.inputWrapper == null) ? 0 - : this.inputWrapper.toString().hashCode()); - result = prime * result + (this.message ? 1231 : 1237); - result = prime * result - + ((this.outputType == null) ? 0 : this.outputType.toString().hashCode()); - result = prime * result + ((this.outputWrapper == null) ? 0 - : this.outputWrapper.toString().hashCode()); - return result; - } - - public String toString() { - if (this.inputType == Void.class) { - return this.type.toString() + ", which is effectively a Supplier<" - + this.outputType + ">"; - } - else if (this.outputType == Void.class) { - return this.type.toString() + ", which is effectively a Consumer<" - + this.inputType + ">"; - } - return this.type.toString(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - FunctionType other = (FunctionType) obj; - if (this.inputType == null) { - if (other.inputType != null) { - return false; - } - } - else if (!this.inputType.toString().equals(other.inputType.toString())) { - return false; - } - if (this.inputWrapper == null) { - if (other.inputWrapper != null) { - return false; - } - } - else if (!this.inputWrapper.toString().equals(other.inputWrapper.toString())) { - return false; - } - if (this.message != other.message) { - return false; - } - if (this.outputType == null) { - if (other.outputType != null) { - return false; - } - } - else if (!this.outputType.toString().equals(other.outputType.toString())) { - return false; - } - if (this.outputWrapper == null) { - if (other.outputWrapper != null) { - return false; - } - } - else if (!this.outputWrapper.toString().equals(other.outputWrapper.toString())) { - return false; - } - return true; - } - - private static ResolvableType wrap(FunctionType input, Class wrapper, - Class type) { - return input.isMessage() ? wrap(wrapper, message(type)) - : ResolvableType.forClassWithGenerics(wrapper, type); - } - - private static ResolvableType wrap(Class wrapper, ResolvableType type) { - return ResolvableType.forClassWithGenerics(wrapper, type); - } - - private static ResolvableType message(Class type) { - return ResolvableType.forClassWithGenerics(Message.class, type); - } - - private static ResolvableType input(FunctionType type) { - return type.input(type.getInputType()); - } - - private static ResolvableType output(FunctionType type) { - return type.output(type.getOutputType()); - } - - private static Class extractClass(Type param, ParamType paramType) { - if (param instanceof ParameterizedType) { - ParameterizedType concrete = (ParameterizedType) param; - param = concrete.getRawType(); - } - if (param == null) { - // Last ditch attempt to guess: Flux - if (paramType.isWrapper()) { - param = Flux.class; - } - else { - param = String.class; - } - } - Class result = param instanceof Class ? (Class) param : null; - // TODO: cache result - return result; - } - - private ResolvableType wrapper(Class wrapper, Class type) { - return wrap(this, wrapper, type); - } - - private ResolvableType output(Class type) { - ResolvableType generic; - ResolvableType raw = ResolvableType.forClass(type); - if (isMessage()) { - raw = ResolvableType.forClassWithGenerics(Message.class, raw); - } - if (FunctionType.isWrapper(getOutputWrapper())) { - generic = ResolvableType.forClassWithGenerics(getOutputWrapper(), raw); - } - else { - generic = raw; - } - return generic; - } - - private ResolvableType input(Class type) { - ResolvableType generic; - ResolvableType raw = ResolvableType.forClass(type); - if (isMessage()) { - raw = ResolvableType.forClassWithGenerics(Message.class, raw); - } - if (FunctionType.isWrapper(getInputWrapper())) { - generic = ResolvableType.forClassWithGenerics(getInputWrapper(), raw); - } - else { - generic = raw; - } - return generic; - } - - private Class findType(ParamType paramType) { - int index = paramType.isOutput() ? 1 : 0; - Type type = this.type; - if (Supplier.class.isAssignableFrom(extractClass(this.type, null))) { - if (paramType.isInput()) { - return Void.class; - } - } - boolean found = false; - while (!found && type instanceof Class && type != Object.class) { - Class clz = (Class) type; - for (Type iface : clz.getGenericInterfaces()) { - if (iface.getTypeName().startsWith("java.util.function")) { - type = iface; - found = true; - break; - } - } - if (!found) { - type = clz.getSuperclass(); - } - } - Type param = extractType(type, paramType, index); - if (param != null) { - Class result = extractClass(param, paramType); - if (result != null) { - return result; - } - } - return Object.class; - } - - private void resetType() { - if (!this.type.getTypeName().contains("EnhancerBySpringCGLIB")) { - return; - } - Type type = this.type; - - boolean found = false; - while (!found && type instanceof Class && type != Object.class) { - Class clz = (Class) type; - for (Type iface : clz.getGenericInterfaces()) { - if (iface.getTypeName().startsWith("java.util.function")) { - type = iface; - found = true; - break; - } - } - if (!found) { - type = clz.getSuperclass(); - } - } - this.type = type; - } - - private Type extractType(Type type, ParamType paramType, int index) { - Type param; - if (type instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) type; - if (parameterizedType.getActualTypeArguments().length == 1) { - if (isVoid(parameterizedType, paramType)) { - return Void.class; - } - // There's only one - index = 0; - } - Type typeArgumentAtIndex = parameterizedType.getActualTypeArguments()[index]; - if (typeArgumentAtIndex instanceof ParameterizedType - && !paramType.isWrapper()) { - if (FunctionType.isWrapper( - ((ParameterizedType) typeArgumentAtIndex).getRawType())) { - param = ((ParameterizedType) typeArgumentAtIndex) - .getActualTypeArguments()[0]; - param = extractNestedType(paramType, param); - } - else { - param = extractNestedType(paramType, typeArgumentAtIndex); - } - } - else { - param = extractNestedType(paramType, typeArgumentAtIndex); - } - } - else { - if (type != null) { - Type[] interfaces = ((Class) type).getGenericInterfaces(); - for (Type ifc : interfaces) { - Type value = extractType(ifc, paramType, index); - if (value != Object.class) { - return value; - } - } - } - param = Object.class; - } - return param; - } - - private boolean isVoid(ParameterizedType parameterizedType, ParamType paramType) { - Class rawType = extractClass(parameterizedType.getRawType(), paramType); - if (Consumer.class.isAssignableFrom(rawType) && paramType.isOutput()) { - return true; - } - if (Supplier.class.isAssignableFrom(rawType) && paramType.isInput()) { - return true; - } - return false; - } - - private Type extractNestedType(ParamType paramType, Type param) { - if (!paramType.isInnerWrapper() && param instanceof ParameterizedType) { - if (((ParameterizedType) param).getRawType().getTypeName() - .startsWith(Message.class.getName())) { - param = ((ParameterizedType) param).getActualTypeArguments()[0]; - } - } - return param; - } - - private Type functionType(Type type) { - if (Supplier.class.isAssignableFrom(extractClass(type, ParamType.OUTPUT))) { - Type product = extractType(type, ParamType.OUTPUT, 0); - Class output = extractClass(product, ParamType.OUTPUT); - if (output != null) { - if (FunctionRegistration.class.isAssignableFrom(output)) { - type = extractType(product, ParamType.OUTPUT, 0); - } - else if (Function.class.isAssignableFrom(output) - || Supplier.class.isAssignableFrom(output) - || Consumer.class.isAssignableFrom(output)) { - type = product; - } - } - } - return type; - } - - private boolean messageType() { - Class inputType = findType(ParamType.INPUT_INNER_WRAPPER); - Class outputType = findType(ParamType.OUTPUT_INNER_WRAPPER); - return inputType.getName().startsWith(Message.class.getName()) - || Message.class.isAssignableFrom(inputType) - || outputType.getName().startsWith(Message.class.getName()) - || Message.class.isAssignableFrom(outputType); - } - - enum ParamType { - - INPUT, OUTPUT, INPUT_WRAPPER, OUTPUT_WRAPPER, INPUT_INNER_WRAPPER, OUTPUT_INNER_WRAPPER; - - public boolean isOutput() { - return this == OUTPUT || this == OUTPUT_WRAPPER - || this == OUTPUT_INNER_WRAPPER; - } - - public boolean isInput() { - return this == INPUT || this == INPUT_WRAPPER || this == INPUT_INNER_WRAPPER; - } - - public boolean isWrapper() { - return this == OUTPUT_WRAPPER || this == INPUT_WRAPPER; - } - - public boolean isInnerWrapper() { - return this == OUTPUT_INNER_WRAPPER || this == INPUT_INNER_WRAPPER; - } - - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionalSpringApplication.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionalSpringApplication.java index eebf2f0d2..04365495a 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionalSpringApplication.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionalSpringApplication.java @@ -153,7 +153,7 @@ public class FunctionalSpringApplication context.registerBean("function", FunctionRegistration.class, () -> new FunctionRegistration<>( handler(context, function, functionType)) - .type(FunctionType.of(functionType))); + .type(functionType)); } private Object handler(GenericApplicationContext generic, Object handler, diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/AbstractComposableFunctionRegistry.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/AbstractComposableFunctionRegistry.java deleted file mode 100644 index f0b934c9f..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/AbstractComposableFunctionRegistry.java +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.catalog; - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -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.config.RoutingFunction; -import org.springframework.cloud.function.core.FluxToMonoFunction; -import org.springframework.cloud.function.core.IsolatedConsumer; -import org.springframework.cloud.function.core.IsolatedFunction; -import org.springframework.cloud.function.core.IsolatedSupplier; -import org.springframework.cloud.function.core.MonoToFluxFunction; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.ApplicationEventPublisherAware; -import org.springframework.context.EnvironmentAware; -import org.springframework.core.env.Environment; -import org.springframework.core.env.StandardEnvironment; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -/** - * Base implementation of {@link FunctionRegistry} which supports function composition - * during lookups. For example if this registry contains function 'a' and 'b' you can - * compose them into a single function by simply piping two names together during the - * lookup {@code this.lookup(Function.class, "a|b")}. - * - * Comma ',' is also supported as composition delimiter (e.g., {@code "a,b"}). - * - * @author Oleg Zhurakousky - * @author Dave Syer - * @since 2.1 - * - */ -public abstract class AbstractComposableFunctionRegistry implements FunctionRegistry, - ApplicationEventPublisherAware, EnvironmentAware { - - private final Map functions = new ConcurrentHashMap<>(); - - private final Map names = new ConcurrentHashMap<>(); - - private final Map types = new ConcurrentHashMap<>(); - - private Environment environment = new StandardEnvironment(); - - protected ApplicationEventPublisher applicationEventPublisher; - - @SuppressWarnings("unchecked") - @Override - public T lookup(Class type, String name) { - String functionDefinitionName = !StringUtils.hasText(name) - && this.environment.containsProperty("spring.cloud.function.definition") - ? this.environment.getProperty("spring.cloud.function.definition") - : name; - return (T) this.doLookup(type, functionDefinitionName); - } - - @SuppressWarnings("serial") - @Override - public Set getNames(Class type) { - if (type == null) { - return new HashSet(getSupplierNames()) { - { - addAll(getFunctionNames()); - } - }; - } - if (Supplier.class.isAssignableFrom(type)) { - return this.getSupplierNames(); - } - if (Function.class.isAssignableFrom(type)) { - return this.getFunctionNames(); - } - return Collections.emptySet(); - } - - /** - * Returns the names of available Suppliers. - * @return immutable {@link Set} of available {@link Supplier} names. - */ - public Set getSupplierNames() { - return this.functions.entrySet().stream() - .filter(entry -> entry.getValue() instanceof Supplier) - .map(entry -> entry.getKey()) - .collect(Collectors.toSet()); - } - - /** - * Returns the names of available Functions. - * @return immutable {@link Set} of available {@link Function} names. - */ - public Set getFunctionNames() { - return this.functions.entrySet().stream() - .filter(entry -> !(entry.getValue() instanceof Supplier)) - .map(entry -> entry.getKey()) - .collect(Collectors.toSet()); - } - - public boolean hasSuppliers() { - return !CollectionUtils.isEmpty(getSupplierNames()); - } - - public boolean hasFunctions() { - return !CollectionUtils.isEmpty(getFunctionNames()); - } - - /** - * The size of this catalog, which is the count of all Suppliers, - * Function and Consumers currently registered. - * - * @return the count of all Suppliers, Function and Consumers currently registered. - */ - @Override - public int size() { - return this.functions.size(); - } - - public FunctionType getFunctionType(String name) { - return this.types.get(name); - } - - /** - * A reverse lookup where one can determine the actual name of the function reference. - * @param function should be an instance of {@link Supplier}, {@link Function} or - * {@link Consumer}; - * @return the name of the function or null. - */ - public String lookupFunctionName(Object function) { - return this.names.containsKey(function) ? this.names.get(function) : null; - } - - @Override - public void setApplicationEventPublisher( - ApplicationEventPublisher applicationEventPublisher) { - this.applicationEventPublisher = applicationEventPublisher; - } - - @Override - public void setEnvironment(Environment environment) { - this.environment = environment; - } - - - public FunctionRegistration getRegistration(Object function) { - String functionName = function == null ? null - : this.lookupFunctionName(function); - if (StringUtils.hasText(functionName)) { - FunctionRegistration registration = new FunctionRegistration( - function, functionName); - FunctionType functionType = this.findType(registration, functionName); - return registration.type(functionType.getType()); - } - return null; - } - - @Override - public void register(FunctionRegistration functionRegistration) { - Assert.notEmpty(functionRegistration.getNames(), - "'registration' must contain at least one name before it is registered in catalog."); - register(functionRegistration, functionRegistration.getNames().iterator().next()); - } - - - - /** - * Registers function wrapped by the provided FunctionRegistration with - * this FunctionRegistry. - * - * @param registration instance of {@link FunctionRegistration} - * @param key the name of the function - */ - protected void register(FunctionRegistration registration, String key) { - Object target = registration.getTarget(); - if (registration.getType() != null) { - this.addType(key, registration.getType()); - } - else { - FunctionType functionType = findType(registration, key); - if (functionType == null) { - return; // TODO fixme - } - this.addType(key, functionType); - registration.type(functionType.getType()); - } - Class type; - registration = isolated(registration).wrap(); - target = registration.getTarget(); - if (target instanceof Supplier) { - type = Supplier.class; - for (String name : registration.getNames()) { - this.addSupplier(name, (Supplier) registration.getTarget()); - } - } - else if (target instanceof Function) { - type = Function.class; - for (String name : registration.getNames()) { - this.addFunction(name, (Function) registration.getTarget()); - } - } - else { - return; - } - this.addName(registration.getTarget(), key); - if (this.applicationEventPublisher != null) { - this.applicationEventPublisher.publishEvent(new FunctionRegistrationEvent( - registration.getTarget(), type, registration.getNames())); - } - } - - protected FunctionType findType(FunctionRegistration functionRegistration, String name) { - return functionRegistration.getType() != null - ? functionRegistration.getType() - : this.getFunctionType(name); - } - - - protected void addSupplier(String name, Supplier supplier) { - this.functions.put(name, supplier); - } - - protected void addFunction(String name, Function function) { - this.functions.put(name, function); - } - - protected void addType(String name, FunctionType functionType) { - this.types.computeIfAbsent(name, str -> functionType); - } - - protected void addName(Object function, String name) { - this.names.put(function, name); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private FunctionRegistration isolated(FunctionRegistration input) { - FunctionRegistration registration = (FunctionRegistration) input; - Object target = registration.getTarget(); - boolean isolated = getClass().getClassLoader() != target.getClass() - .getClassLoader(); - if (isolated) { - if (target instanceof Supplier && isolated) { - target = new IsolatedSupplier((Supplier) target); - } - else if (target instanceof Function) { - target = new IsolatedFunction((Function) target); - } - else if (target instanceof Consumer) { - target = new IsolatedConsumer((Consumer) target); - } - } - - registration.target(target); - return registration; - } - - private Object compose(String name, Map lookup) { - - name = name.replaceAll(",", "|").trim(); - Object composedFunction = null; - - if (lookup.containsKey(name)) { - composedFunction = lookup.get(name); - } - else if (name.equals("") && lookup.size() >= 1 && lookup.size() <= 2) { // we may have RoutingFunction function - String functionName = lookup.keySet().stream() - .filter(fName -> !fName.equals(RoutingFunction.FUNCTION_NAME)) - .findFirst().orElseGet(() -> null); - composedFunction = lookup.get(functionName); - } - else { - String[] stages = StringUtils.delimitedListToStringArray(name, "|"); - - AtomicBoolean supplierPresent = new AtomicBoolean(); - List> composableFunctions = Stream.of(stages) - .map(funcName -> find(funcName, supplierPresent.get())) - .filter(x -> x != null) - .peek(f -> supplierPresent.set(f.getTarget() instanceof Supplier)) - .collect(Collectors.toList()); - FunctionRegistration composedRegistration = composableFunctions - .stream().reduce((a, z) -> composeFunctions(a, z)) - .orElseGet(() -> null); - - if (composedRegistration != null - && composedRegistration.getTarget() != null - && !this.types.containsKey(name)) { - - composedFunction = composedRegistration.getTarget(); - this.addType(name, composedRegistration.getType()); - this.addName(composedFunction, name); - if (composedFunction instanceof Function || composedFunction instanceof Consumer) { - this.addFunction(name, (Function) composedFunction); - } - else if (composedFunction instanceof Supplier) { - this.addSupplier(name, (Supplier) composedFunction); - } - } - - } - - return composedFunction; - } - - private FunctionRegistration find(String name, boolean supplierFound) { - Object result = this.functions.get(name); - if (result == null && !StringUtils.hasText(name)) { - if (supplierFound && this.getFunctionNames().size() == 1) { - result = this.functions.get(this.getFunctionNames().iterator().next()); - } - else if (!supplierFound && this.getSupplierNames().size() == 1) { - result = this.functions.get(this.getSupplierNames().iterator().next()); - } - } - - return getRegistration(result); - } - - @SuppressWarnings("unchecked") - private FunctionRegistration composeFunctions(FunctionRegistration aReg, - FunctionRegistration bReg) { - FunctionType aType = aReg.getType(); - FunctionType bType = bReg.getType(); - Object a = aReg.getTarget(); - Object b = bReg.getTarget(); - if (aType != null && bType != null) { - if (aType.isMessage() && !bType.isMessage()) { - bType = bType.message(); - b = message(b); - } - } - Object composedFunction = null; -// if (a instanceof Supplier && b instanceof Function) { -// Supplier> supplier = (Supplier>) a; -// if (b instanceof FluxConsumer) { -// if (supplier instanceof FluxSupplier) { -// FluxConsumer fConsumer = ((FluxConsumer) b); -// composedFunction = (Supplier>) () -> Mono.from( -// supplier.get().compose(v -> fConsumer.apply(supplier.get()))); -// } -// else { -// throw new IllegalStateException( -// "The provided supplier is finite (i.e., already composed with Consumer) " -// + "therefore it can not be composed with another consumer"); -// } -// } -// else { -// Function function = (Function) b; -// composedFunction = (Supplier) () -> function -// .apply(supplier.get()); -// } -// } -// else - if (a instanceof Function && b instanceof Function) { - Function function1 = (Function) a; - Function function2 = (Function) b; - if (function1 instanceof FluxToMonoFunction) { - if (function2 instanceof MonoToFluxFunction) { - composedFunction = function1.andThen(function2); - } - else { - throw new IllegalStateException( - "The provided function is finite (i.e., returns Mono) " - + "therefore it can *only* be composed with compatible function (i.e., Function"); - } - } - else if (function2 instanceof FluxToMonoFunction) { - composedFunction = new FluxToMonoFunction( - ((Function, Flux>) a).andThen( - ((FluxToMonoFunction) b).getTarget())); - } - else { - composedFunction = function1.andThen(function2); - } - } - else if (a instanceof Function && b instanceof Consumer) { - Function function = (Function) a; - Consumer consumer = (Consumer) b; - composedFunction = (Consumer) v -> consumer.accept(function.apply(v)); - } - else { - throw new IllegalArgumentException(String - .format("Could not compose %s and %s", a.getClass(), b.getClass())); - } - String name = aReg.getNames().iterator().next() + "|" - + bReg.getNames().iterator().next(); - return new FunctionRegistration<>(composedFunction, name) - .type(FunctionType.compose(aType, bType)); - } - - private Object message(Object input) { - if (input instanceof Supplier) { - return new MessageSupplier((Supplier) input); - } - if (input instanceof Consumer) { - return new MessageConsumer((Consumer) input); - } - if (input instanceof Function) { - return new MessageFunction((Function) input); - } - return input; - } - - private Object doLookup(Class type, String name) { - Object function = this.compose(name, this.functions); - if (function != null && type != null && !type.isAssignableFrom(function.getClass())) { - function = null; - } - return function; - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionInspector.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionInspector.java deleted file mode 100644 index 0b23146b0..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionInspector.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2012-2020 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 - * - * https://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.catalog; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; - -import net.jodah.typetools.TypeResolver; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public interface FunctionInspector { - - FunctionRegistration getRegistration(Object function); - - /** - * - * @deprecated since 3.1 no longer used by the framework - */ - @Deprecated - default boolean isMessage(Object function) { - if (function == null) { - return false; - } - - return ((FunctionInvocationWrapper) function).isInputTypeMessage(); - } - - /** - * - * @deprecated since 3.1 no longer used by the framework - */ - @Deprecated - default Class getInputType(Object function) { - if (function == null) { - return Object.class; - } - Type type = ((FunctionInvocationWrapper) function).getInputType(); - Class inputType; - if (type instanceof ParameterizedType) { - if (function != null && (((FunctionInvocationWrapper) function).isInputTypePublisher() || ((FunctionInvocationWrapper) function).isInputTypeMessage())) { - inputType = TypeResolver.resolveRawClass(FunctionTypeUtils.getImmediateGenericType(type, 0), null); - } - else { - inputType = ((FunctionInvocationWrapper) function).getRawInputType(); - } - } - else { - inputType = type instanceof TypeVariable || type instanceof WildcardType ? Object.class : (Class) type; - } - return inputType; - } - - /** - * - * @deprecated since 3.1 no longer used by the framework - */ - @Deprecated - default Class getOutputType(Object function) { - if (function == null) { - return Object.class; - } - Type type = ((FunctionInvocationWrapper) function).getOutputType(); - Class outputType; - if (type instanceof ParameterizedType) { - if (function != null && ((FunctionInvocationWrapper) function).isOutputTypePublisher() || ((FunctionInvocationWrapper) function).isOutputTypeMessage()) { - outputType = TypeResolver.resolveRawClass(FunctionTypeUtils.getImmediateGenericType(type, 0), null); - } - else { - outputType = ((FunctionInvocationWrapper) function).getRawOutputType(); - } - } - else { - outputType = type instanceof TypeVariable || type instanceof WildcardType ? Object.class : (Class) type; - } - return outputType; - } - - /** - * - * @deprecated since 3.1 no longer used by the framework - */ - @Deprecated - default Class getInputWrapper(Object function) { - Class c = function == null ? Object.class : TypeResolver.resolveRawClass(((FunctionInvocationWrapper) function).getInputType(), null); - if (Flux.class.isAssignableFrom(c)) { - return c; - } - else if (Mono.class.isAssignableFrom(c)) { - return c; - } - else { - return this.getInputType(function); - } - } - - /** - * - * @deprecated since 3.1 no longer used by the framework - */ - @Deprecated - default Class getOutputWrapper(Object function) { - Class c = function == null ? Object.class : TypeResolver.resolveRawClass(((FunctionInvocationWrapper) function).getOutputType(), null); - if (Flux.class.isAssignableFrom(c)) { - return c; - } - else if (Mono.class.isAssignableFrom(c)) { - return c; - } - else { - return this.getOutputType(function); - } - } - - /** - * - * @deprecated since 3.1 no longer used by the framework - */ - @Deprecated - default String getName(Object function) { - if (function == null) { - return null; - } - return ((FunctionInvocationWrapper) function).getFunctionDefinition(); - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeConversionHelper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeConversionHelper.java index 67e871b8e..f5b0a4840 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeConversionHelper.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeConversionHelper.java @@ -71,12 +71,12 @@ class FunctionTypeConversionHelper { this.conversionService = conversionService; this.messageConverter = messageConverter; this.functionRegistration = functionRegistration; - if ((this.functionRegistration.getType().getType()) instanceof ParameterizedType) { - this.functionArgumentTypes = ((ParameterizedType) this.functionRegistration.getType().getType()) + if ((this.functionRegistration.getType()) instanceof ParameterizedType) { + this.functionArgumentTypes = ((ParameterizedType) this.functionRegistration.getType()) .getActualTypeArguments(); } else { - this.functionArgumentTypes = new Type[] { this.functionRegistration.getType().getInputType() }; + this.functionArgumentTypes = new Type[] { FunctionTypeUtils.getInputType(this.functionRegistration.getType()) }; } } @@ -227,7 +227,7 @@ class FunctionTypeConversionHelper { } } else { - Assert.isTrue(!Publisher.class.isAssignableFrom(this.functionRegistration.getType().getInputWrapper()), + Assert.isTrue(!FunctionTypeUtils.isPublisher(FunctionTypeUtils.getInputType(this.functionRegistration.getType())), "Invoking reactive function as imperative is not allowed. Function name(s): " + this.functionRegistration.getNames()); incoming = this.doConvertArgument(incoming, targetType, actualType); @@ -244,7 +244,7 @@ class FunctionTypeConversionHelper { : Flux.from((Publisher) incoming).map(value -> this.messageConverter.toMessage(value, headers)); } else { - Assert.isTrue(!Publisher.class.isAssignableFrom(this.functionRegistration.getType().getInputWrapper()), + Assert.isTrue(!FunctionTypeUtils.isPublisher(FunctionTypeUtils.getInputType(this.functionRegistration.getType())), "Invoking reactive function as imperative is not allowed. Function name(s): " + this.functionRegistration.getNames()); incoming = this.messageConverter.toMessage(incoming, headers); @@ -296,7 +296,7 @@ class FunctionTypeConversionHelper { incomingValue = incomingMessage; } else { - incomingValue = this.messageConverter.fromMessage((Message) incomingMessage, targetType); + incomingValue = this.messageConverter.fromMessage(incomingMessage, targetType); } } return incomingValue; diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java index be0b9264e..0574ae627 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java @@ -41,7 +41,6 @@ import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils; import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionType; import org.springframework.cloud.function.context.config.FunctionContextUtils; import org.springframework.cloud.function.context.config.RoutingFunction; import org.springframework.context.support.GenericApplicationContext; @@ -68,6 +67,21 @@ public final class FunctionTypeUtils { } + public static Type functionType(Type input, Type output) { + return ResolvableType.forClassWithGenerics(Function.class, + ResolvableType.forType(input), ResolvableType.forType(output)).getType(); + } + + public static Type consumerType(Type input) { + return ResolvableType.forClassWithGenerics(Consumer.class, + ResolvableType.forType(input)).getType(); + } + + public static Type supplierType(Type output) { + return ResolvableType.forClassWithGenerics(Supplier.class, + ResolvableType.forType(output)).getType(); + } + /** * Will return 'true' if the provided type is a {@link Collection} type. * This also includes collections wrapped in {@link Message}. For example, @@ -176,6 +190,37 @@ public final class FunctionTypeUtils { return null; } + /** + * Discovers the function {@link Type} based on the signature of a factory method. + * For example, given the following method {@code Function, Message> uppercase()} of + * class Foo - {@code Type type = discoverFunctionTypeFromFunctionFactoryMethod(Foo.class, "uppercase");} + * + * @param clazz instance of Class containing the factory method + * @param methodName factory method name + * @return type of the function + */ + public static Type discoverFunctionTypeFromFunctionFactoryMethod(Class clazz, String methodName) { + return discoverFunctionTypeFromFunctionFactoryMethod(ReflectionUtils.findMethod(clazz, methodName)); + } + + /** + * Discovers the function {@link Type} based on the signature of a factory method. + * For example, given the following method {@code Function, Message> uppercase()} of + * class Foo - {@code Type type = discoverFunctionTypeFromFunctionFactoryMethod(Foo.class, "uppercase");} + * + * @param method factory method + * @return type of the function + */ + public static Type discoverFunctionTypeFromFunctionFactoryMethod(Method method) { + return method.getGenericReturnType(); + } + + /** + * Unlike {@link #discoverFunctionTypeFromFunctionFactoryMethod(Class, String)}, this method discovers function + * type from the well known method of Function(apply), Supplier(get) or Consumer(accept). + * @param functionMethod functional method + * @return type of the function + */ public static Type discoverFunctionTypeFromFunctionMethod(Method functionMethod) { Assert.isTrue( functionMethod.getName().equals("apply") || @@ -223,6 +268,26 @@ public final class FunctionTypeUtils { return outputCount; } + /** + * In the event the input type is {@link ParameterizedType} this method returns its generic type. + * @param functionType instance of function type + * @return generic type or input type + */ + public static Type getComponentTypeOfInputType(Type functionType) { + Type inputType = getInputType(functionType); + return getImmediateGenericType(inputType, 0); + } + + /** + * In the event the output type is {@link ParameterizedType} this method returns its generic type. + * @param functionType instance of function type + * @return generic type or output type + */ + public static Type getComponentTypeOfOutputType(Type functionType) { + Type inputType = getOutputType(functionType); + return getImmediateGenericType(inputType, 0); + } + /** * Returns input type of function type that represents Function or Consumer. * @param functionType the Type of Function or Consumer @@ -253,15 +318,15 @@ public final class FunctionTypeUtils { @SuppressWarnings("rawtypes") public static Type discoverFunctionType(Object function, String functionName, GenericApplicationContext applicationContext) { if (function instanceof RoutingFunction) { - return FunctionType.of(FunctionContextUtils.findType(applicationContext.getBeanFactory(), functionName)).getType(); + return FunctionContextUtils.findType(applicationContext.getBeanFactory(), functionName); } else if (function instanceof FunctionRegistration) { - return ((FunctionRegistration) function).getType().getType(); + return ((FunctionRegistration) function).getType(); } if (applicationContext.containsBean(functionName + FunctionRegistration.REGISTRATION_NAME_SUFFIX)) { // for Kotlin primarily FunctionRegistration fr = applicationContext .getBean(functionName + FunctionRegistration.REGISTRATION_NAME_SUFFIX, FunctionRegistration.class); - return fr.getType().getType(); + return fr.getType(); } boolean beanDefinitionExists = false; @@ -277,13 +342,13 @@ public final class FunctionTypeUtils { if (beanDefinitionExists) { Type t = FunctionTypeUtils.getImmediateGenericType(type, 0); if (t == null || t == Object.class) { - type = FunctionType.of(FunctionContextUtils.findType(applicationContext.getBeanFactory(), functionBeanDefinitionName)).getType(); + type = FunctionContextUtils.findType(applicationContext.getBeanFactory(), functionBeanDefinitionName); } } else if (!(type instanceof ParameterizedType)) { String beanDefinitionName = discoverBeanDefinitionNameByQualifier(applicationContext.getBeanFactory(), functionName); if (StringUtils.hasText(beanDefinitionName)) { - type = FunctionType.of(FunctionContextUtils.findType(applicationContext.getBeanFactory(), beanDefinitionName)).getType(); + type = FunctionContextUtils.findType(applicationContext.getBeanFactory(), beanDefinitionName); } } return type; diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/MessageFunction.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/MessageFunction.java deleted file mode 100644 index 6650e07d0..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/MessageFunction.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.catalog; - -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.function.core.FluxConsumer; -import org.springframework.cloud.function.core.FluxFunction; -import org.springframework.cloud.function.core.FluxToMonoFunction; -import org.springframework.cloud.function.core.FluxedFunction; -import org.springframework.cloud.function.core.MonoToFluxFunction; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; - -/** - * @author Dave Syer - * @since 2.1 - */ -public class MessageFunction - implements Function, Publisher>> { - - private final Function delegate; - - public MessageFunction(Function delegate) { - this.delegate = delegate; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - public Publisher> apply(Publisher input) { - Flux incomingFlux = Flux.from(input); - Flux> flux = incomingFlux.map(value -> { - if (!(value instanceof Message)) { - return MessageBuilder.withPayload(value).build(); - } - return (Message) value; - }); - - if (this.delegate instanceof FluxFunction) { - Function target = (Function) ((FluxFunction) this.delegate) - .getTarget(); - return flux.map( - value -> MessageBuilder.withPayload(target.apply(value.getPayload())) - .copyHeaders(value.getHeaders()).build()); - } - if (this.delegate instanceof MonoToFluxFunction) { - Function, Flux> target = ((MonoToFluxFunction) this.delegate) - .getTarget(); - return flux.next() - .flatMapMany(value -> target.apply(Mono.just(value.getPayload())) - .map(object -> MessageBuilder.withPayload(object) - .copyHeaders(value.getHeaders()).build())); - } - if (this.delegate instanceof FluxToMonoFunction) { - Function, Mono> target = ((FluxToMonoFunction) this.delegate) - .getTarget(); - AtomicReference headers = new AtomicReference<>(); - return target.apply(flux.map(messsage -> { - headers.set(messsage.getHeaders()); - return messsage.getPayload(); - })).map(payload -> MessageBuilder.withPayload(payload) - .copyHeaders(headers.get()).build()); - } - if (this.delegate instanceof FluxConsumer) { - FluxConsumer target = ((FluxConsumer) this.delegate); - AtomicReference headers = new AtomicReference<>(); - Mono mapped = target.apply(flux.map(messsage -> { - headers.set(messsage.getHeaders()); - return messsage.getPayload(); - })); - return mapped.map(value -> MessageBuilder.createMessage(null, headers.get())); - } - - // TODO: cover the case that delegate is actually Function - if (this.delegate instanceof FluxedFunction) { - Function, Flux> target = ((FluxedFunction) this.delegate); - return (Flux) flux.map(value -> ((Message) value).getPayload()).transform(target); - } - Function function = this.delegate; - return flux.map( - value -> { - return MessageBuilder.withPayload(function.apply(value.getPayload())) - .copyHeaders(value.getHeaders()).build(); - }); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/MessageSupplier.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/MessageSupplier.java deleted file mode 100644 index 999a3271b..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/MessageSupplier.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.catalog; - -import java.util.function.Supplier; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.function.core.FluxSupplier; -import org.springframework.cloud.function.core.MonoSupplier; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -/** - * @author Dave Syer - */ -public class MessageSupplier implements Supplier>> { - - private Supplier delegate; - - public MessageSupplier(Supplier delegate) { - this.delegate = delegate; - } - - @Override - public Publisher> get() { - if (this.delegate instanceof FluxSupplier) { - return ((Flux) this.delegate.get()) - .map(value -> MessageBuilder.withPayload(value).build()); - } - if (this.delegate instanceof MonoSupplier) { - return ((Mono) this.delegate.get()) - .map(value -> MessageBuilder.withPayload(value).build()); - } - Object product = this.delegate.get(); - if (product instanceof Publisher) { - return Flux.from((Publisher) product) - .map(value -> MessageBuilder.withPayload(value).build()); - } - if (product instanceof Iterable) { - return Flux.fromIterable((Iterable) product) - .map(value -> MessageBuilder.withPayload(value).build()); - } - return Mono.just(MessageBuilder.withPayload(product).build()); - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java index dbfe13e49..d9cb73ddd 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java @@ -82,7 +82,7 @@ import org.springframework.util.StringUtils; * @author Oleg Zhurakousky * */ -public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspector { +public class SimpleFunctionRegistry implements FunctionRegistry { protected Log logger = LogFactory.getLog(this.getClass()); /* * - do we care about FunctionRegistration after it's been registered? What additional value does it bring? @@ -133,13 +133,6 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect } } - @Override - public FunctionRegistration getRegistration(Object function) { - throw new UnsupportedOperationException("FunctionInspector is deprecated. There is no need " - + "to access FunctionRegistration directly since you can interogate the actual " - + "looked-up function (see FunctionInvocationWrapper."); - } - public SimpleFunctionRegistry(ConversionService conversionService, CompositeMessageConverter messageConverter, JsonMapper jsonMapper) { this(conversionService, messageConverter, jsonMapper, null, null); } @@ -269,7 +262,7 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect .findFirst() .orElseGet(() -> null); FunctionInvocationWrapper function = functionRegistration != null - ? this.invocationWrapperInstance(functionName, functionRegistration.getTarget(), functionRegistration.getType().getType()) + ? this.invocationWrapperInstance(functionName, functionRegistration.getTarget(), functionRegistration.getType()) : null; if (functionRegistration != null && functionRegistration.getProperties().containsKey("singleton")) { try { diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java index 0f8bb5ecb..c06ac28ab 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java @@ -29,7 +29,6 @@ import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.core.FunctionFactoryMetadata; import org.springframework.context.annotation.ScannedGenericBeanDefinition; import org.springframework.core.ResolvableType; import org.springframework.core.io.Resource; @@ -88,20 +87,6 @@ public abstract class FunctionContextUtils { if (type != null) { param = type.getType(); } - else { - Class beanClass = definition.hasBeanClass() ? definition.getBeanClass() : null; - if (beanClass != null - && !FunctionFactoryMetadata.class.isAssignableFrom(beanClass)) { - param = beanClass; - } - else { - Object bean = registry.getBean(actualName); - // could be FunctionFactoryMetadata. . . TODO investigate and fix - if (bean instanceof FunctionFactoryMetadata) { - param = ((FunctionFactoryMetadata) bean).getFactoryMethod().getGenericReturnType(); - } - } - } } return param; } diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/converter/avro/AvroSchemaServiceManager.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/converter/avro/AvroSchemaServiceManager.java index 9152df071..ed208dc93 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/converter/avro/AvroSchemaServiceManager.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/converter/avro/AvroSchemaServiceManager.java @@ -63,7 +63,6 @@ public interface AvroSchemaServiceManager { * @param writerSchema {@link Schema} writerSchema provided at run time * @return datum reader which can be used to read Avro payload */ - @SuppressWarnings({ "unchecked", "rawtypes" }) DatumReader getDatumReader(Class type, Schema schema, Schema writerSchema); /** diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/converter/avro/AvroSchemaServiceManagerImpl.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/converter/avro/AvroSchemaServiceManagerImpl.java index 77faaabd9..eee848412 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/converter/avro/AvroSchemaServiceManagerImpl.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/converter/avro/AvroSchemaServiceManagerImpl.java @@ -71,6 +71,7 @@ public class AvroSchemaServiceManagerImpl implements AvroSchemaServiceManager { * @param schema {@link Schema} of object which needs to be serialized * @return datum writer which can be used to write Avro payload */ + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public DatumWriter getDatumWriter(Class type, Schema schema) { DatumWriter writer; diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/message/MessageUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/message/MessageUtils.java index 2c6b3c7bd..585793feb 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/message/MessageUtils.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/message/MessageUtils.java @@ -16,18 +16,6 @@ package org.springframework.cloud.function.context.message; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.springframework.cloud.function.core.FluxWrapper; -import org.springframework.cloud.function.core.Isolated; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; - /** * @author Dave Syer * @author Oleg Zhurakousky @@ -48,80 +36,4 @@ public abstract class MessageUtils { * Value for 'target-protocol' typically use as header key. */ public static String SOURCE_TYPE = "source-type"; - - /** - * Create a message for the handler. If the handler is a wrapper for a function in an - * isolated class loader, then the message will be created with the target class - * loader (therefore the {@link Message} class must be on the classpath of the target - * class loader). - * @param handler the function that will be applied to the message - * @param payload the payload of the message - * @param headers the headers for the message - * @return a message with the correct class loader - */ - public static Object create(Object handler, Object payload, - Map headers) { - if (handler instanceof FluxWrapper) { - handler = ((FluxWrapper) handler).getTarget(); - } - if (payload instanceof Message) { - headers = new HashMap<>(headers); - headers.putAll(((Message) payload).getHeaders()); - payload = ((Message) payload).getPayload(); - } - if (!(handler instanceof Isolated)) { - return MessageBuilder.withPayload(payload).copyHeaders(headers).build(); - } - ClassLoader classLoader = ((Isolated) handler).getClassLoader(); - Class builder = ClassUtils.resolveClassName(MessageBuilder.class.getName(), - classLoader); - Method withPayload = ClassUtils.getMethod(builder, "withPayload", Object.class); - Method copyHeaders = ClassUtils.getMethod(builder, "copyHeaders", Map.class); - Method build = ClassUtils.getMethod(builder, "build"); - Object instance = ReflectionUtils.invokeMethod(withPayload, null, payload); - ReflectionUtils.invokeMethod(copyHeaders, instance, headers); - return ReflectionUtils.invokeMethod(build, instance); - } - - /** - * Convert a message from the handler into one that is safe to consume in the caller's - * class loader. If the handler is a wrapper for a function in an isolated class - * loader, then the message will be created with the target class loader (therefore - * the {@link Message} class must be on the classpath of the target class loader). - * @param handler the function that generated the message - * @param message the message to convert - * @return a message with the correct class loader - */ - public static Message unpack(Object handler, Object message) { - if (handler instanceof FluxWrapper) { - handler = ((FluxWrapper) handler).getTarget(); - } - if (!(handler instanceof Isolated)) { - if (message instanceof Message) { - return (Message) message; - } - return MessageBuilder.withPayload(message).build(); - } - ClassLoader classLoader = ((Isolated) handler).getClassLoader(); - Class type = ClassUtils.isPresent(Message.class.getName(), classLoader) - ? ClassUtils.resolveClassName(Message.class.getName(), classLoader) - : null; - Object payload; - Map headers; - if (type != null && type.isAssignableFrom(message.getClass())) { - Method getPayload = ClassUtils.getMethod(type, "getPayload"); - Method getHeaders = ClassUtils.getMethod(type, "getHeaders"); - payload = ReflectionUtils.invokeMethod(getPayload, message); - @SuppressWarnings("unchecked") - Map map = (Map) ReflectionUtils - .invokeMethod(getHeaders, message); - headers = map; - } - else { - payload = message; - headers = Collections.emptyMap(); - } - return MessageBuilder.withPayload(payload).copyHeaders(headers).build(); - } - } 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 deleted file mode 100644 index 10f755f55..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionRegistrationTests.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jupiter.api.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(), - "foos"); - assertThat(registration.getType()).isNull(); - assertThat(registration.getNames()).contains("foos"); - } - - @Test - public void wrap() { - FunctionRegistration registration = new FunctionRegistration<>(new Foos(), - "foos").type(FunctionType.of(Foos.class).getType()); - FunctionRegistration other = registration.wrap(); - assertThat(registration.getType().isWrapper()).isFalse(); - assertThat(other.getType().isWrapper()).isTrue(); - assertThat(other.getTarget()).isNotEqualTo(registration.getTarget()); - } - - 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/FunctionTypeTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionTypeTests.java deleted file mode 100644 index 94b0abb81..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/FunctionTypeTests.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Collections; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuple3; - -import org.springframework.core.ResolvableType; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -public class FunctionTypeTests { - - @Test - public void functionWithTuples() { - FunctionType functionType = FunctionType.of(MyFunction.class); - assertThat(functionType.getType()).isInstanceOf(ParameterizedType.class); - } - - @Test - public void plainFunction() { - FunctionType function = new FunctionType(IntegerToString.class); - assertThat(function.getInputType()).isEqualTo(Integer.class); - assertThat(function.getOutputType()).isEqualTo(String.class); - assertThat(function.getInputWrapper()).isEqualTo(Integer.class); - assertThat(function.getOutputWrapper()).isEqualTo(String.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void supplierOfRegistration() { - FunctionType function = new FunctionType( - SupplierOfRegistrationOfIntegerToString.class); - assertThat(function.getInputType()).isEqualTo(Integer.class); - assertThat(function.getOutputType()).isEqualTo(String.class); - assertThat(function.getInputWrapper()).isEqualTo(Integer.class); - assertThat(function.getOutputWrapper()).isEqualTo(String.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void supplier() { - FunctionType function = new FunctionType(SupplierOfIntegerToString.class); - assertThat(function.getInputType()).isEqualTo(Integer.class); - assertThat(function.getOutputType()).isEqualTo(String.class); - assertThat(function.getInputWrapper()).isEqualTo(Integer.class); - assertThat(function.getOutputWrapper()).isEqualTo(String.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void genericFunction() { - FunctionType function = new FunctionType(StringToMap.class); - assertThat(function.getInputType()).isEqualTo(String.class); - assertThat(function.getOutputType()).isEqualTo(Map.class); - assertThat(function.getInputWrapper()).isEqualTo(String.class); - assertThat(function.getOutputWrapper()).isEqualTo(Map.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void pojoFunction() { - FunctionType function = new FunctionType(FooToFoo.class); - assertThat(function.getInputType()).isEqualTo(Foo.class); - assertThat(function.getOutputType()).isEqualTo(Bar.class); - assertThat(function.getInputWrapper()).isEqualTo(Foo.class); - assertThat(function.getOutputWrapper()).isEqualTo(Bar.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void fluxFunction() { - FunctionType function = new FunctionType(FluxToFlux.class); - assertThat(function.getInputType()).isEqualTo(Foo.class); - assertThat(function.getOutputType()).isEqualTo(Bar.class); - assertThat(function.getInputWrapper()).isEqualTo(Flux.class); - assertThat(function.getOutputWrapper()).isEqualTo(Flux.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void fluxMessageFunction() { - FunctionType function = new FunctionType(FluxMessageToFluxMessage.class); - assertThat(function.getInputType()).isEqualTo(Foo.class); - assertThat(function.getOutputType()).isEqualTo(Bar.class); - assertThat(function.getInputWrapper()).isEqualTo(Flux.class); - assertThat(function.getOutputWrapper()).isEqualTo(Flux.class); - assertThat(function.isMessage()).isEqualTo(true); - } - - @Test - public void plainFunctionFromType() { - Type type = ResolvableType - .forClassWithGenerics(Function.class, Integer.class, String.class) - .getType(); - FunctionType function = new FunctionType(type); - assertThat(function.getInputType()).isEqualTo(Integer.class); - assertThat(function.getOutputType()).isEqualTo(String.class); - assertThat(function.getInputWrapper()).isEqualTo(Integer.class); - assertThat(function.getOutputWrapper()).isEqualTo(String.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void pojoConsumerFromType() { - Type type = ResolvableType.forClassWithGenerics(Consumer.class, Foo.class) - .getType(); - FunctionType function = new FunctionType(type); - assertThat(function.getInputType()).isEqualTo(Foo.class); - assertThat(function.getOutputType()).isEqualTo(Void.class); - assertThat(function.getInputWrapper()).isEqualTo(Foo.class); - assertThat(function.getOutputWrapper()).isEqualTo(Void.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void pojoSupplierFromType() { - Type type = ResolvableType.forClassWithGenerics(Supplier.class, Foo.class) - .getType(); - FunctionType function = new FunctionType(type); - assertThat(function.getInputType()).isEqualTo(Void.class); - assertThat(function.getOutputType()).isEqualTo(Foo.class); - assertThat(function.getInputWrapper()).isEqualTo(Void.class); - assertThat(function.getOutputWrapper()).isEqualTo(Foo.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void pojoSupplierFrom() { - FunctionType function = new FunctionType(Supplier.class).to(Foo.class); - assertThat(function.getInputType()).isEqualTo(Void.class); - assertThat(function.getOutputType()).isEqualTo(Foo.class); - assertThat(function.getInputWrapper()).isEqualTo(Void.class); - assertThat(function.getOutputWrapper()).isEqualTo(Foo.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void pojoSupplier() { - FunctionType function = FunctionType.supplier(Foo.class); - assertThat(function.getInputType()).isEqualTo(Void.class); - assertThat(function.getOutputType()).isEqualTo(Foo.class); - assertThat(function.getInputWrapper()).isEqualTo(Void.class); - assertThat(function.getOutputWrapper()).isEqualTo(Foo.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void pojoConsumer() { - FunctionType function = FunctionType.consumer(Foo.class); - assertThat(function.getOutputType()).isEqualTo(Void.class); - assertThat(function.getInputType()).isEqualTo(Foo.class); - assertThat(function.getOutputWrapper()).isEqualTo(Void.class); - assertThat(function.getInputWrapper()).isEqualTo(Foo.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void plainFunctionFromApi() { - FunctionType function = FunctionType.from(Integer.class).to(String.class); - assertThat(function.getInputType()).isEqualTo(Integer.class); - assertThat(function.getOutputType()).isEqualTo(String.class); - assertThat(function.getInputWrapper()).isEqualTo(Integer.class); - assertThat(function.getOutputWrapper()).isEqualTo(String.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void fluxMessageFunctionFromType() { - Type type = ResolvableType - .forClassWithGenerics(Function.class, - ResolvableType.forClassWithGenerics( - Flux.class, - ResolvableType.forClassWithGenerics(Message.class, - Foo.class)), - ResolvableType.forClassWithGenerics(Flux.class, ResolvableType - .forClassWithGenerics(Message.class, Bar.class))) - .getType(); - FunctionType function = new FunctionType(type); - assertThat(function.getInputType()).isEqualTo(Foo.class); - assertThat(function.getOutputType()).isEqualTo(Bar.class); - assertThat(function.getInputWrapper()).isEqualTo(Flux.class); - assertThat(function.getOutputWrapper()).isEqualTo(Flux.class); - assertThat(function.isMessage()).isEqualTo(true); - } - - @Test - public void fluxMessageFunctionFromApi() { - FunctionType function = FunctionType.from(Foo.class).to(Bar.class).message() - .wrap(Flux.class); - assertThat(function.getInputType()).isEqualTo(Foo.class); - assertThat(function.getOutputType()).isEqualTo(Bar.class); - assertThat(function.getInputWrapper()).isEqualTo(Flux.class); - assertThat(function.getOutputWrapper()).isEqualTo(Flux.class); - assertThat(function.isMessage()).isEqualTo(true); - } - - @Test - public void compose() { - FunctionType input = FunctionType.from(Foo.class).to(Bar.class).wrap(Flux.class); - FunctionType output = FunctionType.from(Bar.class).to(String.class); - FunctionType function = FunctionType.compose(input, output); - assertThat(function.getInputType()).isEqualTo(Foo.class); - assertThat(function.getOutputType()).isEqualTo(String.class); - assertThat(function.getInputWrapper()).isEqualTo(Flux.class); - assertThat(function.getOutputWrapper()).isEqualTo(Flux.class); - assertThat(function.isMessage()).isEqualTo(false); - } - - @Test - public void idempotentMessage() { - FunctionType function = FunctionType.from(Foo.class).to(Bar.class).message() - .wrap(Flux.class); - assertThat(function).isSameAs(function.message()); - } - - @Test - public void idempotentWrapper() { - FunctionType function = FunctionType.from(Foo.class).to(Bar.class).message() - .wrap(Flux.class); - assertThat(function).isSameAs(function.wrap(Flux.class)); - } - - @Test - public void nonWrapper() { - FunctionType function = FunctionType.from(Foo.class).to(Bar.class); - assertThat(function).isSameAs(function.wrap(Object.class)); - } - - private static class SupplierOfRegistrationOfIntegerToString - implements Supplier>> { - - @Override - public FunctionRegistration> get() { - return new FunctionRegistration>( - new IntegerToString(), "ints"); - } - - } - - private static class SupplierOfIntegerToString - implements Supplier> { - - @Override - public Function get() { - return new IntegerToString(); - } - - } - - private static class IntegerToString implements Function { - - @Override - public String apply(Integer t) { - return "" + t; - } - - } - - private static class StringToMap implements Function> { - - @Override - public Map apply(String t) { - return Collections.emptyMap(); - } - - } - - private static class FooToFoo implements Function { - - @Override - public Bar apply(Foo t) { - return new Bar(); - } - - } - - private static class FluxToFlux implements Function, Flux> { - - @Override - public Flux apply(Flux t) { - return t.map(f -> new Bar()); - } - - } - - private static class FluxMessageToFluxMessage - implements Function>, Flux>> { - - @Override - public Flux> apply(Flux> t) { - return t.map(f -> MessageBuilder.withPayload(new Bar()) - .copyHeadersIfAbsent(f.getHeaders()).build()); - } - - } - - private static class Foo { - - } - - private static class Bar { - - } - - private static class MyFunction - implements Function, Flux>, Tuple3, Flux, Flux>> { - - @Override - public Tuple3, Flux, Flux> apply(Tuple2, Flux> t) { - return null; - } - -} - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/SpringFunctionAdapterInitializerTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/SpringFunctionAdapterInitializerTests.java deleted file mode 100644 index 66e257ec9..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/SpringFunctionAdapterInitializerTests.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.context.support.GenericApplicationContext; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class SpringFunctionAdapterInitializerTests { - - private AbstractSpringFunctionAdapterInitializer initializer; - - @AfterEach - public void after() { - System.clearProperty("function.name"); - if (this.initializer != null) { - this.initializer.close(); - } - } - - @Test - public void nullSource() { - Assertions.assertThrows(IllegalArgumentException.class, () -> - this.initializer = new AbstractSpringFunctionAdapterInitializer(null) { - - }); - } - - @Test - public void sourceAsMainClassProperty() { - try { - System.setProperty("MAIN_CLASS", FluxFunctionConfig.class.getName()); - this.initializer = new AbstractSpringFunctionAdapterInitializer() { - - }; - } - finally { - System.clearProperty("MAIN_CLASS"); - } - } - - @Test - public void functionBean() { - this.initializer = new AbstractSpringFunctionAdapterInitializer(FluxFunctionConfig.class) { - - }; - this.initializer.initialize(null); - Flux result = Flux.from(this.initializer.apply(Flux.just(new Foo()))); - assertThat(result.blockFirst()).isInstanceOf(Bar.class); - } - - @Test - public void functionApp() { - this.initializer = new AbstractSpringFunctionAdapterInitializer(FluxFunctionApp.class) { - - }; - this.initializer.initialize(null); - Flux result = Flux.from(this.initializer.apply(Flux.just(new Foo()))); - Object o = result.blockFirst(); - assertThat(result.blockFirst()).isInstanceOf(Bar.class); - } - - @Test - public void functionCatalog() { - this.initializer = new AbstractSpringFunctionAdapterInitializer(FunctionConfig.class) { - - }; - this.initializer.initialize(null); - Flux result = Flux.from(this.initializer.apply(Flux.just(new Foo()))); - assertThat(result.blockFirst()).isInstanceOf(Bar.class); - } - - @Test - @Disabled // related to boot 2.1 no bean override change - public void functionRegistrar() { - this.initializer = new AbstractSpringFunctionAdapterInitializer(FunctionRegistrar.class) { - - }; - this.initializer.initialize(null); - Flux result = Flux.from(this.initializer.apply(Flux.just(new Foo()))); - assertThat(result.blockFirst()).isInstanceOf(Bar.class); - } - - @Test - public void namedFunctionCatalog() { - this.initializer = new AbstractSpringFunctionAdapterInitializer(NamedFunctionConfig.class) { - - }; - System.setProperty("function.name", "other"); - this.initializer.initialize(null); - Flux result = Flux.from(this.initializer.apply(Flux.just(new Foo()))); - assertThat(result.blockFirst()).isInstanceOf(Bar.class); - } - - @Test - public void consumerCatalog() { - this.initializer = new AbstractSpringFunctionAdapterInitializer(ConsumerConfig.class) { - - }; - this.initializer.initialize(null); - Flux result = Flux.from(this.initializer.apply(Flux.just(new Foo()))); - assertThat(result.toStream().collect(Collectors.toList())).isEmpty(); - } - - @Test - public void supplierCatalog() { - initializer = new AbstractSpringFunctionAdapterInitializer(SupplierConfig.class) { - - }; - initializer.initialize(null); - Flux result = Flux.from(initializer.apply(null)); - assertThat(result.blockFirst()).isInstanceOf(Bar.class); - } - - @Configuration - protected static class FluxFunctionConfig { - - @Bean - public Function, Flux> function() { - return flux -> flux.map(foo -> new Bar()); - } - - } - - protected static class FluxFunctionApp implements Function, Flux> { - - @Override - public Flux apply(Flux flux) { - return flux.map(foo -> new Bar()); - } - - } - - protected static class FunctionRegistrar - implements ApplicationContextInitializer { - - public Function, Flux> function() { - return flux -> flux.map(foo -> new Bar()); - } - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration, Flux>>( - function()).name("function") - .type(FunctionType.from(Foo.class).to(Bar.class) - .wrap(Flux.class).getType())); - } - - } - - @Configuration - @Import(ContextFunctionCatalogAutoConfiguration.class) - protected static class FunctionConfig { - - @Bean - public Function function() { - return foo -> new Bar(); - } - - } - - @Configuration - @Import(ContextFunctionCatalogAutoConfiguration.class) - protected static class NamedFunctionConfig { - - @Bean - public Function other() { - return foo -> new Bar(); - } - - } - - @Configuration - @Import(ContextFunctionCatalogAutoConfiguration.class) - protected static class SupplierConfig { - @Bean - public Supplier supplier() { - return () -> { - return new Bar(); - }; - } - } - - @Configuration - @Import(ContextFunctionCatalogAutoConfiguration.class) - protected static class ConsumerConfig { - - @Bean - public Consumer consumer() { - return foo -> { - }; - } - - } - - protected static class Foo { - - } - - protected static class Bar { - - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java index 47318beb8..6758351f3 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java @@ -53,7 +53,6 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.function.context.FunctionCatalog; 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.json.JsonMapper; import org.springframework.context.ApplicationContext; @@ -499,30 +498,35 @@ public class BeanFactoryAwareFunctionRegistryTests { assertThat(func).isNull(); FunctionRegistry registry = (FunctionRegistry) catalog; try { - FunctionRegistration registration = new FunctionRegistration(new MyFunction(), "a").type(FunctionType.from(Integer.class).to(String.class)); + FunctionRegistration registration = new FunctionRegistration(new MyFunction(), "a") + .type(FunctionTypeUtils.functionType(Integer.class, String.class)); registry.register(registration); fail(); } - catch (IllegalStateException e) { + catch (IllegalArgumentException e) { // good as we expect it to fail } // try { - FunctionRegistration registration = new FunctionRegistration(new MyFunction(), "b").type(FunctionType.from(String.class).to(Integer.class)); + FunctionRegistration registration = new FunctionRegistration(new MyFunction(), "b") + .type(FunctionTypeUtils.functionType(String.class, Integer.class)); registry.register(registration); fail(); } - catch (IllegalStateException e) { + catch (IllegalArgumentException e) { // good as we expect it to fail } // - FunctionRegistration c = new FunctionRegistration(new MyFunction(), "c").type(FunctionType.from(String.class).to(String.class)); + FunctionRegistration c = new FunctionRegistration(new MyFunction(), "c") + .type(FunctionTypeUtils.functionType(String.class, String.class)); registry.register(c); // - FunctionRegistration d = new FunctionRegistration(new RawFunction(), "d").type(FunctionType.from(Person.class).to(String.class)); + FunctionRegistration d = new FunctionRegistration(new RawFunction(), "d") + .type(FunctionTypeUtils.functionType(Person.class, String.class)); registry.register(d); // - FunctionRegistration e = new FunctionRegistration(new RawFunction(), "e").type(FunctionType.from(Object.class).to(Object.class)); + FunctionRegistration e = new FunctionRegistration(new RawFunction(), "e") + .type(FunctionTypeUtils.functionType(Object.class, Object.class)); registry.register(e); } diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwarePojoFunctionRegistryTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwarePojoFunctionRegistryTests.java index 3f0910bb2..accc4c5ba 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwarePojoFunctionRegistryTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwarePojoFunctionRegistryTests.java @@ -133,7 +133,7 @@ public class BeanFactoryAwarePojoFunctionRegistryTests { } // POJO Function - private static class MyFunctionLike { + public static class MyFunctionLike { public String uppercase(String value) { return value.toUpperCase(); } diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtilsTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtilsTests.java index 6f0285422..1f96e0ab1 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtilsTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtilsTests.java @@ -31,7 +31,6 @@ import reactor.core.publisher.Mono; import reactor.util.function.Tuple2; import reactor.util.function.Tuple3; -import org.springframework.cloud.function.context.FunctionType; import org.springframework.core.ParameterizedTypeReference; import org.springframework.messaging.Message; @@ -114,29 +113,29 @@ public class FunctionTypeUtilsTests { @Test public void testFunctionTypeByClassDiscovery() { - FunctionType type = FunctionType.of(FunctionTypeUtils.discoverFunctionTypeFromClass(Function.class)); - assertThat(type.getInputType()).isAssignableFrom(Object.class); + Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(Function.class); + assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getInputType(type))).isAssignableFrom(Object.class); - type = FunctionType.of(FunctionTypeUtils.discoverFunctionTypeFromClass(MessageFunction.class)); - assertThat(type.getInputType()).isAssignableFrom(String.class); - assertThat(type.getOutputType()).isAssignableFrom(String.class); + type = FunctionTypeUtils.discoverFunctionTypeFromClass(MessageFunction.class); + assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfInputType(type))).isAssignableFrom(String.class); + assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfOutputType(type))).isAssignableFrom(String.class); - type = FunctionType.of(FunctionTypeUtils.discoverFunctionTypeFromClass(MyMessageFunction.class)); - assertThat(type.getInputType()).isAssignableFrom(String.class); - assertThat(type.getOutputType()).isAssignableFrom(String.class); + type = FunctionTypeUtils.discoverFunctionTypeFromClass(MyMessageFunction.class); + assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfInputType(type))).isAssignableFrom(String.class); + assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfOutputType(type))).isAssignableFrom(String.class); - type = FunctionType.of(FunctionTypeUtils.discoverFunctionTypeFromClass(MessageConsumer.class)); - assertThat(type.getInputType()).isAssignableFrom(String.class); + type = FunctionTypeUtils.discoverFunctionTypeFromClass(MessageConsumer.class); + assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfInputType(type))).isAssignableFrom(String.class); - type = FunctionType.of(FunctionTypeUtils.discoverFunctionTypeFromClass(MyMessageConsumer.class)); - assertThat(type.getInputType()).isAssignableFrom(String.class); + type = FunctionTypeUtils.discoverFunctionTypeFromClass(MyMessageConsumer.class); + assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfInputType(type))).isAssignableFrom(String.class); } @Test public void testWithComplexHierarchy() { - FunctionType type = FunctionType.of(FunctionTypeUtils.discoverFunctionTypeFromClass(ReactiveFunctionImpl.class)); - assertThat(String.class).isAssignableFrom(type.getInputType()); - assertThat(Integer.class).isAssignableFrom(type.getOutputType()); + Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(ReactiveFunctionImpl.class); + assertThat(String.class).isAssignableFrom(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfInputType(type))); + assertThat(Integer.class).isAssignableFrom(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfOutputType(type))); } @Test diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/MessageConsumerTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/MessageConsumerTests.java deleted file mode 100644 index 08221e709..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/MessageConsumerTests.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.catalog; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - */ -public class MessageConsumerTests { - - private List items = new ArrayList<>(); - - @Test - public void plainConsumer() { - MessageConsumer consumer = new MessageConsumer(input()); - consumer.accept(Flux - .just(MessageBuilder.withPayload("foo").setHeader("foo", "bar").build())); - assertThat(this.items).hasSize(1); - } - - private Consumer input() { - return value -> this.items.add(value); - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/MessageFunctionTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/MessageFunctionTests.java deleted file mode 100644 index 54094ac64..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/MessageFunctionTests.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.catalog; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.test.StepVerifier; - -import org.springframework.cloud.function.core.FluxConsumer; -import org.springframework.cloud.function.core.FluxFunction; -import org.springframework.cloud.function.core.FluxToMonoFunction; -import org.springframework.cloud.function.core.MonoToFluxFunction; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - */ -public class MessageFunctionTests { - - private List items = new ArrayList<>(); - - @Test - public void plainFunction() { - MessageFunction function = new MessageFunction(uppercase()); - Publisher> result = function.apply(Flux - .just(MessageBuilder.withPayload("foo").setHeader("foo", "bar").build())); - StepVerifier.create(result).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo("FOO"); - assertThat(message.getHeaders()).containsEntry("foo", "bar"); - }); - } - - @Test - public void fluxFunction() { - MessageFunction function = new MessageFunction(new FluxFunction<>(uppercase())); - Publisher> result = function.apply(Flux - .just(MessageBuilder.withPayload("foo").setHeader("foo", "bar").build())); - StepVerifier.create(result).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo("FOO"); - assertThat(message.getHeaders()).containsEntry("foo", "bar"); - }); - } - - @Test - public void fluxToMonoFunction() { - MessageFunction function = new MessageFunction( - new FluxToMonoFunction( - flux -> flux.next().map(uppercase()))); - Publisher> result = function.apply(Flux - .just(MessageBuilder.withPayload("foo").setHeader("foo", "bar").build())); - StepVerifier.create(result).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo("FOO"); - assertThat(message.getHeaders()).containsEntry("foo", "bar"); - }); - } - - @Test - public void monoToFunction() { - MessageFunction function = new MessageFunction( - new MonoToFluxFunction( - mono -> Flux.from(mono.map(uppercase())))); - Publisher> result = function.apply(Flux - .just(MessageBuilder.withPayload("foo").setHeader("foo", "bar").build())); - StepVerifier.create(result).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo("FOO"); - assertThat(message.getHeaders()).containsEntry("foo", "bar"); - }); - } - - @Test - public void fluxConsumer() { - MessageFunction function = new MessageFunction(new FluxConsumer<>(stash())); - Publisher> result = function.apply(Flux - .just(MessageBuilder.withPayload("foo").setHeader("foo", "bar").build())); - StepVerifier.create(result).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo(null); - assertThat(message.getHeaders()).containsEntry("foo", "bar"); - assertThat(this.items).hasSize(1); - }); - } - - private Consumer stash() { - return value -> this.items.add(value); - } - - private Function uppercase() { - return value -> value.toUpperCase(); - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/MessageSupplierTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/MessageSupplierTests.java deleted file mode 100644 index 8ff2bd6be..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/MessageSupplierTests.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.catalog; - -import java.util.Arrays; -import java.util.Collection; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.test.StepVerifier; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - */ -public class MessageSupplierTests { - - @Test - public void plainSupplier() { - MessageSupplier supplier = new MessageSupplier(input()); - StepVerifier.create(supplier.get()).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo("foo"); - assertThat(message.getHeaders()).isEmpty(); - }); - } - - @Test - public void collectionSupplier() { - MessageSupplier supplier = new MessageSupplier(inputs()); - StepVerifier.create(supplier.get()).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo("foo"); - assertThat(message.getHeaders()).isEmpty(); - }).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo("bar"); - assertThat(message.getHeaders()).isEmpty(); - }); - } - - @Test - public void fluxSupplier() { - MessageSupplier supplier = new MessageSupplier(flux()); - StepVerifier.create(supplier.get()).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo("foo"); - assertThat(message.getHeaders()).isEmpty(); - }).assertNext(message -> { - assertThat(message.getPayload()).isEqualTo("bar"); - assertThat(message.getHeaders()).isEmpty(); - }); - } - - private Supplier input() { - return () -> "foo"; - } - - private Supplier> inputs() { - return () -> Arrays.asList("foo", "bar"); - } - - private Supplier> flux() { - return () -> Flux.just("foo", "bar"); - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistryTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistryTests.java index 062b2d7fa..c570c33e8 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistryTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistryTests.java @@ -43,7 +43,6 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.function.context.FunctionCatalog; 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.HybridFunctionalRegistrationTests.UppercaseFunction; import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; import org.springframework.cloud.function.context.config.JsonMessageConverter; @@ -94,7 +93,7 @@ public class SimpleFunctionRegistryTests { public void testCachingOfFunction() { Echo function = new Echo(); FunctionRegistration registration = new FunctionRegistration<>( - function, "echo").type(FunctionType.of(Echo.class)); + function, "echo").type(Echo.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(registration); @@ -110,7 +109,7 @@ public class SimpleFunctionRegistryTests { public void testNoCachingOfFunction() { Echo function = new Echo(); FunctionRegistration registration = new FunctionRegistration<>( - function, "echo").type(FunctionType.of(Echo.class)); + function, "echo").type(Echo.class); registration.getProperties().put("singleton", "false"); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); @@ -136,7 +135,7 @@ public class SimpleFunctionRegistryTests { }; FunctionRegistration, String>> registration = new FunctionRegistration<>( - function, "echo").type(FunctionType.of(functionType)); + function, "echo").type(functionType); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(registration); @@ -150,7 +149,7 @@ public class SimpleFunctionRegistryTests { public void testSCF640() { Echo function = new Echo(); FunctionRegistration registration = new FunctionRegistration<>( - function, "echo").type(FunctionType.of(Echo.class)); + function, "echo").type(Echo.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(registration); @@ -168,27 +167,27 @@ public class SimpleFunctionRegistryTests { new JacksonMapper(new ObjectMapper())); FunctionRegistration reg1 = new FunctionRegistration<>( - new UpperCase(), "uppercase").type(FunctionType.of(UpperCase.class)); + new UpperCase(), "uppercase").type(UpperCase.class); catalog.register(reg1); // FunctionRegistration reg2 = new FunctionRegistration<>( - new UpperCaseMessage(), "uppercaseMessage").type(FunctionType.of(UpperCaseMessage.class)); + new UpperCaseMessage(), "uppercaseMessage").type(UpperCaseMessage.class); catalog.register(reg2); // FunctionRegistration reg3 = new FunctionRegistration<>( - new StringArrayFunction(), "stringArray").type(FunctionType.of(StringArrayFunction.class)); + new StringArrayFunction(), "stringArray").type(StringArrayFunction.class); catalog.register(reg3); // FunctionRegistration reg4 = new FunctionRegistration<>( - new TypelessFunction(), "typeless").type(FunctionType.of(TypelessFunction.class)); + new TypelessFunction(), "typeless").type(TypelessFunction.class); catalog.register(reg4); // FunctionRegistration reg5 = new FunctionRegistration<>( - new ByteArrayFunction(), "typeless").type(FunctionType.of(ByteArrayFunction.class)); + new ByteArrayFunction(), "typeless").type(ByteArrayFunction.class); catalog.register(reg5); // FunctionRegistration reg6 = new FunctionRegistration<>( - new StringListFunction(), "stringList").type(FunctionType.of(StringListFunction.class)); + new StringListFunction(), "stringList").type(StringListFunction.class); catalog.register(reg6); Message collectionMessage = MessageBuilder.withPayload("[\"ricky\", \"julien\", \"bubbles\"]").build(); @@ -244,7 +243,7 @@ public class SimpleFunctionRegistryTests { UpperCase function = new UpperCase(); FunctionRegistration registration = new FunctionRegistration<>( - function, "foo").type(FunctionType.of(UppercaseFunction.class)); + function, "foo").type(UppercaseFunction.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(registration); @@ -263,7 +262,7 @@ public class SimpleFunctionRegistryTests { TestFunction function = new TestFunction(); FunctionRegistration registration = new FunctionRegistration<>( - function, "foo").type(FunctionType.of(TestFunction.class)); + function, "foo").type(TestFunction.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(registration); @@ -272,7 +271,7 @@ public class SimpleFunctionRegistryTests { FunctionInvocationWrapper lookedUpFunction = catalog.lookup("hello"); assertThat(lookedUpFunction).isNotNull(); // because we only have one and can look it up with any name FunctionRegistration registration2 = new FunctionRegistration<>( - function, "foo2").type(FunctionType.of(TestFunction.class)); + function, "foo2").type(TestFunction.class); catalog.register(registration2); lookedUpFunction = catalog.lookup("hello"); assertThat(lookedUpFunction).isNull(); @@ -283,9 +282,9 @@ public class SimpleFunctionRegistryTests { @Test public void testFunctionComposition() { FunctionRegistration upperCaseRegistration = new FunctionRegistration<>( - new UpperCase(), "uppercase").type(FunctionType.of(UpperCase.class)); + new UpperCase(), "uppercase").type(UpperCase.class); FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(FunctionType.of(Reverse.class)); + new Reverse(), "reverse").type(Reverse.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(upperCaseRegistration); @@ -294,23 +293,15 @@ public class SimpleFunctionRegistryTests { Function, Flux> lookedUpFunction = catalog .lookup("uppercase|reverse"); assertThat(lookedUpFunction).isNotNull(); - - Flux flux = lookedUpFunction.apply(Flux.just("star")); - flux.subscribe(v -> { - System.out.println(v); - }); - -// assertThat(lookedUpFunction.apply(Flux.just("star")).blockFirst()) -// .isEqualTo("RATS"); } @Test @Disabled public void testFunctionCompositionImplicit() { FunctionRegistration wordsRegistration = new FunctionRegistration<>( - new Words(), "words").type(FunctionType.of(Words.class)); + new Words(), "words").type(Words.class); FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(FunctionType.of(Reverse.class)); + new Reverse(), "reverse").type(Reverse.class); FunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(wordsRegistration); @@ -327,9 +318,9 @@ public class SimpleFunctionRegistryTests { @Disabled public void testFunctionCompletelyImplicitComposition() { FunctionRegistration wordsRegistration = new FunctionRegistration<>( - new Words(), "words").type(FunctionType.of(Words.class)); + new Words(), "words").type(Words.class); FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(FunctionType.of(Reverse.class)); + new Reverse(), "reverse").type(Reverse.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(wordsRegistration); @@ -345,9 +336,9 @@ public class SimpleFunctionRegistryTests { @Test public void testFunctionCompositionExplicit() { FunctionRegistration wordsRegistration = new FunctionRegistration<>( - new Words(), "words").type(FunctionType.of(Words.class)); + new Words(), "words").type(Words.class); FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(FunctionType.of(Reverse.class)); + new Reverse(), "reverse").type(Reverse.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(wordsRegistration); @@ -363,10 +354,10 @@ public class SimpleFunctionRegistryTests { public void testFunctionCompositionWithMessages() { FunctionRegistration upperCaseRegistration = new FunctionRegistration<>( new UpperCaseMessage(), "uppercase") - .type(FunctionType.of(UpperCaseMessage.class)); + .type(UpperCaseMessage.class); FunctionRegistration reverseRegistration = new FunctionRegistration<>( new ReverseMessage(), "reverse") - .type(FunctionType.of(ReverseMessage.class)); + .type(ReverseMessage.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(upperCaseRegistration); @@ -385,9 +376,9 @@ public class SimpleFunctionRegistryTests { public void testFunctionCompositionMixedMessages() { FunctionRegistration upperCaseRegistration = new FunctionRegistration<>( new UpperCaseMessage(), "uppercase") - .type(FunctionType.of(UpperCaseMessage.class)); + .type(UpperCaseMessage.class); FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(FunctionType.of(Reverse.class)); + new Reverse(), "reverse").type(Reverse.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(upperCaseRegistration); @@ -405,7 +396,7 @@ public class SimpleFunctionRegistryTests { @Test public void testReactiveFunctionMessages() { FunctionRegistration registration = new FunctionRegistration<>(new ReactiveFunction(), "reactive") - .type(FunctionType.of(ReactiveFunction.class)); + .type(ReactiveFunction.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); @@ -433,6 +424,7 @@ public class SimpleFunctionRegistryTests { assertThat(result).isEqualTo("Jim Lahey"); } + @SuppressWarnings({ "rawtypes", "unchecked" }) @Test public void lookup() { SimpleFunctionRegistry functionRegistry = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, @@ -442,7 +434,7 @@ public class SimpleFunctionRegistryTests { Function userFunction = uppercase(); FunctionRegistration functionRegistration = new FunctionRegistration(userFunction, "uppercase") - .type(FunctionType.from(String.class).to(String.class)); + .type(FunctionTypeUtils.functionType(String.class, String.class)); functionRegistry.register(functionRegistration); function = functionRegistry.lookup("uppercase"); @@ -450,20 +442,21 @@ public class SimpleFunctionRegistryTests { } + @SuppressWarnings({ "rawtypes", "unchecked" }) @Test public void lookupDefaultName() { SimpleFunctionRegistry functionRegistry = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); Function userFunction = uppercase(); FunctionRegistration functionRegistration = new FunctionRegistration(userFunction, "uppercase") - .type(FunctionType.from(String.class).to(String.class)); + .type(FunctionTypeUtils.functionType(String.class, String.class)); functionRegistry.register(functionRegistration); FunctionInvocationWrapper function = functionRegistry.lookup(""); assertThat(function).isNotNull(); } - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void lookupWithCompositionFunctionAndConsumer() { SimpleFunctionRegistry functionRegistry = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, @@ -471,7 +464,7 @@ public class SimpleFunctionRegistryTests { Object userFunction = uppercase(); FunctionRegistration functionRegistration = new FunctionRegistration(userFunction, "uppercase") - .type(FunctionType.from(String.class).to(String.class)); + .type(FunctionTypeUtils.functionType(String.class, String.class)); functionRegistry.register(functionRegistration); userFunction = consumer(); @@ -484,6 +477,7 @@ public class SimpleFunctionRegistryTests { functionWrapper.apply("123"); } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void lookupWithReactiveConsumer() { SimpleFunctionRegistry functionRegistry = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, @@ -500,12 +494,11 @@ public class SimpleFunctionRegistryTests { functionWrapper.apply("123"); } - @SuppressWarnings({ "rawtypes", "unchecked" }) @Test public void testHeaderEnricherFunction() { FunctionRegistration registration = new FunctionRegistration<>(new HeaderEnricherFunction(), "headerEnricher") - .type(FunctionType.of(HeaderEnricherFunction.class)); + .type(HeaderEnricherFunction.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(registration); @@ -519,7 +512,7 @@ public class SimpleFunctionRegistryTests { @Test public void testReactiveMonoSupplier() { FunctionRegistration registration = new FunctionRegistration<>(new ReactiveMonoGreeter(), - "greeter").type(FunctionType.of(ReactiveMonoGreeter.class)); + "greeter").type(ReactiveMonoGreeter.class); SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); catalog.register(registration); diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializerTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializerTests.java index af23aa560..3b3075a73 100644 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializerTests.java +++ b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializerTests.java @@ -39,7 +39,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.function.context.FunctionCatalog; import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionType; +import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; import org.springframework.cloud.function.context.scan.TestFunction; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.annotation.Bean; @@ -245,17 +245,18 @@ public class ContextFunctionCatalogInitializerTests { private List list = new ArrayList<>(); + @Override public void initialize(GenericApplicationContext context) { + context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>(function()).type( - FunctionType.from(Person.class).to(Person.class).getType())); + () -> new FunctionRegistration<>(function()).type(FunctionTypeUtils.functionType(Person.class, Person.class))); context.registerBean("supplier", FunctionRegistration.class, () -> new FunctionRegistration<>(supplier()) - .type(FunctionType.supplier(String.class).getType())); + .type(FunctionTypeUtils.supplierType(String.class))); context.registerBean("consumer", FunctionRegistration.class, () -> new FunctionRegistration<>(consumer()) - .type(FunctionType.consumer(String.class).getType())); + .type(FunctionTypeUtils.consumerType(String.class))); context.registerBean(SimpleConfiguration.class, () -> this); } @@ -296,8 +297,7 @@ public class ContextFunctionCatalogInitializerTests { @Override public void initialize(GenericApplicationContext context) { context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>(function()).type( - FunctionType.from(String.class).to(String.class).getType())); + () -> new FunctionRegistration<>(function()).type(FunctionTypeUtils.functionType(String.class, String.class))); context.registerBean(PropertiesConfiguration.class, () -> this); } @@ -317,8 +317,7 @@ public class ContextFunctionCatalogInitializerTests { @Override public void initialize(GenericApplicationContext context) { context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>(function()).type( - FunctionType.from(String.class).to(String.class).getType())); + () -> new FunctionRegistration<>(function()).type(FunctionTypeUtils.functionType(String.class, String.class))); context.registerBean(ValueConfiguration.class, () -> this); } @@ -355,8 +354,7 @@ public class ContextFunctionCatalogInitializerTests { context.registerBean(String.class, () -> value()); context.registerBean("foos", FunctionRegistration.class, () -> new FunctionRegistration<>(foos(context.getBean(String.class))) - .type(FunctionType.from(String.class).to(Foo.class) - .getType())); + .type(FunctionTypeUtils.functionType(String.class, Foo.class))); } @Bean diff --git a/spring-cloud-function-core/pom.xml b/spring-cloud-function-core/pom.xml index fb4a3e1c4..14a51730a 100644 --- a/spring-cloud-function-core/pom.xml +++ b/spring-cloud-function-core/pom.xml @@ -12,7 +12,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxConsumer.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxConsumer.java deleted file mode 100644 index 78e64f2e8..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxConsumer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -import java.util.function.Consumer; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -/** - * Wrapper for a {@link Consumer} implementation that converts a non-reactive - * consumer into a reactive function ({@code Function, Mono>}). - * - * @param input type of target consumer - * @author Dave Syer - * @author Oleg Zhurakousky - * @see FluxedConsumer - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public class FluxConsumer - extends WrappedFunction, Mono, Consumer> { - - public FluxConsumer(Consumer target) { - super(target); - } - - @Override - public Mono apply(Flux input) { - return input.doOnNext(this.getTarget()).then(); - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxFunction.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxFunction.java deleted file mode 100644 index 74933963e..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxFunction.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -import java.util.function.Function; - -import reactor.core.publisher.Flux; - -/** - * {@link Function} implementation that wraps a target Function so that the target's - * simple input and output types will be wrapped as {@link Flux} instances. - * - * @param input type of target function - * @param output type of target function - * @author Mark Fisher - * @author Oleg Zhurakousky - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public class FluxFunction - extends WrappedFunction, Flux, Function> { - - public FluxFunction(Function target) { - super(target); - } - - @Override - public Flux apply(Flux input) { - return input.map(value -> this.getTarget().apply(value)); - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxSupplier.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxSupplier.java deleted file mode 100644 index 8d28038a9..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxSupplier.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -import java.time.Duration; -import java.util.function.Supplier; -import java.util.stream.Stream; - -import reactor.core.publisher.Flux; - -/** - * {@link Supplier} implementation that wraps a target Supplier so that the target's - * simple output type will be wrapped in a {@link Flux} instance. If a {@link Duration} is - * provided, the Flux will produce output periodically, invoking the target Supplier's - * {@code get} method at each interval. If no Duration is provided, the target will be - * invoked only once. - * - * @param output type of target supplier - * @author Mark Fisher - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public class FluxSupplier implements Supplier>, FluxWrapper> { - - private final Supplier supplier; - - private final Duration period; - - public FluxSupplier(Supplier supplier) { - this(supplier, null); - } - - public FluxSupplier(Supplier supplier, Duration period) { - this.supplier = supplier; - this.period = period; - } - - @Override - public Supplier getTarget() { - return this.supplier; - } - - @Override - @SuppressWarnings({ "unchecked", "rawtypes" }) - public Flux get() { - if (this.period != null) { - return Flux.interval(this.period).map(i -> this.supplier.get()); - } - Object result = this.supplier.get(); - if (result instanceof Stream) { - return Flux.fromStream((Stream) result); - } - return Flux.just((T) result); - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxToMonoFunction.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxToMonoFunction.java deleted file mode 100644 index a923d1823..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxToMonoFunction.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -import java.util.function.Function; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -/** - * Wrapper to mark function {@code Function, Mono>}. - * - * While it may look similar to {@link FluxedConsumer} the fundamental difference is that - * this class represents a function that returns {@link Mono} of type {@code }, while - * {@link FluxedConsumer} is a consumer that has been decorated as - * {@code Function, Mono>}. - * - * @param type of {@link Flux} input of the target function - * @param type of {@link Mono} output of the target function - * @author Oleg Zhurakousky - * @since 2.0 - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public class FluxToMonoFunction - extends WrappedFunction, Mono, Function, Mono>> { - - public FluxToMonoFunction(Function, Mono> target) { - super(target); - } - - @Override - public Mono apply(Flux input) { - return this.getTarget().apply(input); - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxWrapper.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxWrapper.java deleted file mode 100644 index 524e19a0c..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxWrapper.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -/** - * @param target type - * @author Dave Syer - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public interface FluxWrapper { - - T getTarget(); - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxedConsumer.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxedConsumer.java deleted file mode 100644 index 227b9e017..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxedConsumer.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.core; - -import java.util.function.Consumer; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -/** - * Wrapper for a {@link Consumer} implementation that converts a reactive consumer into a - * reactive function ({@code Function, Mono>}). This is primarily done for - * consistent representation of reactive and non-reactive consumers. - * - * @param input type of target consumer - * @author Oleg Zhurakousky - * @since 2.0.1 - * @see FluxConsumer - * - * @deprecated since 3.1 no longer used by the framework - * - */ -@Deprecated -public class FluxedConsumer - extends WrappedFunction, Mono, Consumer>> { - - public FluxedConsumer(Consumer> target) { - super(target); - } - - @Override - public Mono apply(Flux input) { - return Mono.fromRunnable(() -> this.getTarget().accept(input)); - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxedFunction.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxedFunction.java deleted file mode 100644 index 1808c5993..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FluxedFunction.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.core; - -import java.util.function.Function; - -import reactor.core.publisher.Flux; - -/** - * {@link Function} implementation that wraps a target Function so that the target's - * simple input and output types will be wrapped as {@link Flux} instances. - * - * @param input type of target function - * @param output type of target function - * @author Oleg Zhurakousky - * @since 2.0.1 - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public class FluxedFunction - extends WrappedFunction, Flux, Function, Flux>> { - - public FluxedFunction(Function, Flux> target) { - super(target); - } - - @Override - public Flux apply(Flux input) { - return input.transform(this.getTarget()); - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FunctionFactoryMetadata.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FunctionFactoryMetadata.java deleted file mode 100644 index 4f5f0b10d..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FunctionFactoryMetadata.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -import java.lang.reflect.Method; - -/** - * @param target type - * @author Dave Syer - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public interface FunctionFactoryMetadata { - - Method getFactoryMethod(); - - F getTarget(); - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/Isolated.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/Isolated.java deleted file mode 100644 index 3b7d7779a..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/Isolated.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -/** - * @author Dave Syer - * - */ -public interface Isolated { - - ClassLoader getClassLoader(); - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/IsolatedConsumer.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/IsolatedConsumer.java deleted file mode 100644 index 1eefb1bc0..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/IsolatedConsumer.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -import java.util.function.Consumer; - -import org.springframework.util.ClassUtils; - -/** - * @param type to consume - * @author Dave Syer - */ -public class IsolatedConsumer implements Consumer, Isolated { - - private final Consumer consumer; - - private final ClassLoader classLoader; - - public IsolatedConsumer(Consumer consumer) { - this.consumer = consumer; - this.classLoader = consumer.getClass().getClassLoader(); - } - - @Override - public ClassLoader getClassLoader() { - return this.classLoader; - } - - @Override - public void accept(T item) { - ClassLoader context = ClassUtils - .overrideThreadContextClassLoader(this.classLoader); - try { - this.consumer.accept(item); - } - finally { - ClassUtils.overrideThreadContextClassLoader(context); - } - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/IsolatedFunction.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/IsolatedFunction.java deleted file mode 100644 index c75122327..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/IsolatedFunction.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -import java.util.function.Function; - -import org.springframework.util.ClassUtils; - -/** - * @param input type - * @param output type - * @author Dave Syer - */ -public class IsolatedFunction implements Function, Isolated { - - private final Function function; - - private final ClassLoader classLoader; - - public IsolatedFunction(Function function) { - this.function = function; - this.classLoader = function.getClass().getClassLoader(); - } - - @Override - public ClassLoader getClassLoader() { - return this.classLoader; - } - - @Override - public T apply(S item) { - ClassLoader context = ClassUtils - .overrideThreadContextClassLoader(this.classLoader); - try { - return this.function.apply(item); - } - finally { - ClassUtils.overrideThreadContextClassLoader(context); - } - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/IsolatedSupplier.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/IsolatedSupplier.java deleted file mode 100644 index 7c9c8ba07..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/IsolatedSupplier.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -import java.util.function.Supplier; - -import org.springframework.util.ClassUtils; - -/** - * @param supplied type - * @author Dave Syer - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public class IsolatedSupplier implements Supplier, Isolated { - - private final Supplier supplier; - - private final ClassLoader classLoader; - - public IsolatedSupplier(Supplier supplier) { - this.supplier = supplier; - this.classLoader = supplier.getClass().getClassLoader(); - } - - @Override - public ClassLoader getClassLoader() { - return this.classLoader; - } - - @Override - public T get() { - ClassLoader context = ClassUtils - .overrideThreadContextClassLoader(this.classLoader); - try { - return this.supplier.get(); - } - finally { - ClassUtils.overrideThreadContextClassLoader(context); - } - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/MonoSupplier.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/MonoSupplier.java deleted file mode 100644 index d1a5d9222..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/MonoSupplier.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.core; - -import java.util.function.Supplier; - -import reactor.core.publisher.Mono; - -/** - * {@link Supplier} implementation that wraps a target Supplier so that the target's - * simple output type will be wrapped in a {@link Mono} instance. - * - * @param output type of target supplier - * @author Mark Fisher - * @since 2.1 - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public class MonoSupplier implements Supplier>, FluxWrapper> { - - private final Supplier supplier; - - public MonoSupplier(Supplier supplier) { - this.supplier = supplier; - } - - @Override - public Supplier getTarget() { - return this.supplier; - } - - @Override - @SuppressWarnings("unchecked") - public Mono get() { - Object result = this.supplier.get(); - return Mono.just((T) result); - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/MonoToFluxFunction.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/MonoToFluxFunction.java deleted file mode 100644 index e0cf7f2c4..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/MonoToFluxFunction.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.core; - -import java.util.function.Function; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -/** - * Marker wrapper for target Function<Mono, Flux>. - * - * @param type of {@link Mono} input of the target function - * @param type of {@link Flux} output of the target function - * @author Oleg Zhurakousky - * @since 2.0 - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public class MonoToFluxFunction - extends WrappedFunction, Flux, Function, Flux>> { - - public MonoToFluxFunction(Function, Flux> target) { - super(target); - } - - @Override - public Flux apply(Mono input) { - return this.getTarget().apply(input); - } - -} diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/WrappedFunction.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/WrappedFunction.java deleted file mode 100644 index 65b762b7d..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/WrappedFunction.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.core; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.reactivestreams.Publisher; - -/** - * Base class for all wrappers that represent underlying functions (user defined - * suppliers, functions and/or consumers) as reactive functions. - * - * @param input type of target consumer - * @param output type of target consumer - * @param reactive input type of target function (instance of {@link Publisher} - * @param reactive output type of target function (instance of {@link Publisher} - * @param actual target function (instance of {@link Supplier}, {@link Function} or - * {@link Consumer}) - * @author Oleg Zhurakousky - * @since 2.0.1 - * - * @deprecated since 3.1 no longer used by the framework - */ -@Deprecated -public abstract class WrappedFunction, OP extends Publisher, T> - implements Function, FluxWrapper { - - private final T target; - - WrappedFunction(T target) { - this.target = target; - } - - @Override - public T getTarget() { - return this.target; - } - -} diff --git a/spring-cloud-function-dependencies/pom.xml b/spring-cloud-function-dependencies/pom.xml index 04275c8e8..9dd103699 100644 --- a/spring-cloud-function-dependencies/pom.xml +++ b/spring-cloud-function-dependencies/pom.xml @@ -6,11 +6,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 3.1.1-SNAPSHOT + 4.0.0-SNAPSHOT spring-cloud-function-dependencies - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT pom Spring Cloud Function Dependencies Spring Cloud Function Dependencies diff --git a/spring-cloud-function-deployer/pom.xml b/spring-cloud-function-deployer/pom.xml index 1bbf34116..d3dc88e64 100644 --- a/spring-cloud-function-deployer/pom.xml +++ b/spring-cloud-function-deployer/pom.xml @@ -10,7 +10,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-deployer/src/it/bootapp-multi/pom.xml b/spring-cloud-function-deployer/src/it/bootapp-multi/pom.xml index a4178e8aa..984d3b628 100644 --- a/spring-cloud-function-deployer/src/it/bootapp-multi/pom.xml +++ b/spring-cloud-function-deployer/src/it/bootapp-multi/pom.xml @@ -18,7 +18,7 @@ 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE diff --git a/spring-cloud-function-deployer/src/it/bootapp-with-javax/pom.xml b/spring-cloud-function-deployer/src/it/bootapp-with-javax/pom.xml index 8191dd508..3d81868e9 100644 --- a/spring-cloud-function-deployer/src/it/bootapp-with-javax/pom.xml +++ b/spring-cloud-function-deployer/src/it/bootapp-with-javax/pom.xml @@ -18,7 +18,7 @@ 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE diff --git a/spring-cloud-function-deployer/src/it/bootapp-with-scf/pom.xml b/spring-cloud-function-deployer/src/it/bootapp-with-scf/pom.xml index 32125d020..72d3b0706 100644 --- a/spring-cloud-function-deployer/src/it/bootapp-with-scf/pom.xml +++ b/spring-cloud-function-deployer/src/it/bootapp-with-scf/pom.xml @@ -18,7 +18,7 @@ 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE diff --git a/spring-cloud-function-deployer/src/it/bootapp/pom.xml b/spring-cloud-function-deployer/src/it/bootapp/pom.xml index feb5311a8..9386f29a9 100644 --- a/spring-cloud-function-deployer/src/it/bootapp/pom.xml +++ b/spring-cloud-function-deployer/src/it/bootapp/pom.xml @@ -18,7 +18,7 @@ 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE diff --git a/spring-cloud-function-deployer/src/it/bootjar-multi/pom.xml b/spring-cloud-function-deployer/src/it/bootjar-multi/pom.xml index ead66cdf4..11b19e3d3 100644 --- a/spring-cloud-function-deployer/src/it/bootjar-multi/pom.xml +++ b/spring-cloud-function-deployer/src/it/bootjar-multi/pom.xml @@ -18,7 +18,7 @@ 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE diff --git a/spring-cloud-function-deployer/src/it/bootjar/pom.xml b/spring-cloud-function-deployer/src/it/bootjar/pom.xml index d20298893..ae94f01f1 100644 --- a/spring-cloud-function-deployer/src/it/bootjar/pom.xml +++ b/spring-cloud-function-deployer/src/it/bootjar/pom.xml @@ -18,7 +18,7 @@ 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE diff --git a/spring-cloud-function-deployer/src/it/bootjarnostart/pom.xml b/spring-cloud-function-deployer/src/it/bootjarnostart/pom.xml index 882b60a13..fdb2449b2 100644 --- a/spring-cloud-function-deployer/src/it/bootjarnostart/pom.xml +++ b/spring-cloud-function-deployer/src/it/bootjarnostart/pom.xml @@ -18,7 +18,7 @@ 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE diff --git a/spring-cloud-function-kotlin/pom.xml b/spring-cloud-function-kotlin/pom.xml index a197f87dc..c26714810 100644 --- a/spring-cloud-function-kotlin/pom.xml +++ b/spring-cloud-function-kotlin/pom.xml @@ -12,7 +12,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-rsocket/pom.xml b/spring-cloud-function-rsocket/pom.xml index 60cc3ea56..4ba1ae743 100644 --- a/spring-cloud-function-rsocket/pom.xml +++ b/spring-cloud-function-rsocket/pom.xml @@ -12,7 +12,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-functional-sample-aws/pom.xml b/spring-cloud-function-samples/function-functional-sample-aws/pom.xml index 858da0ed6..55f22acef 100644 --- a/spring-cloud-function-samples/function-functional-sample-aws/pom.xml +++ b/spring-cloud-function-samples/function-functional-sample-aws/pom.xml @@ -6,7 +6,7 @@ io.spring.sample function-functional-sample-aws - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-functional-sample-aws @@ -15,17 +15,20 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT UTF-8 UTF-8 - 1.8 1.0.27.RELEASE 3.9.0 +<<<<<<< HEAD 3.2.2-SNAPSHOT +======= + 4.0.0-SNAPSHOT +>>>>>>> 4.x diff --git a/spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/FunctionConfiguration.java b/spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/FunctionConfiguration.java index 34ff8b4d4..477300d38 100644 --- a/spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/FunctionConfiguration.java +++ b/spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/FunctionConfiguration.java @@ -4,7 +4,7 @@ import java.util.function.Function; import org.springframework.boot.SpringBootConfiguration; import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionType; +import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.support.GenericApplicationContext; @@ -24,7 +24,6 @@ public class FunctionConfiguration implements ApplicationContextInitializer function = (str) -> str + str.toUpperCase(); context.registerBean("uppercase", FunctionRegistration.class, - () -> new FunctionRegistration<>(function).type( - FunctionType.from(String.class).to(String.class))); + () -> new FunctionRegistration<>(function).type(FunctionTypeUtils.functionType(String.class, String.class))); } } diff --git a/spring-cloud-function-samples/function-sample-aws-custom-bean/pom.xml b/spring-cloud-function-samples/function-sample-aws-custom-bean/pom.xml index 7f15c554d..277123c90 100644 --- a/spring-cloud-function-samples/function-sample-aws-custom-bean/pom.xml +++ b/spring-cloud-function-samples/function-sample-aws-custom-bean/pom.xml @@ -5,19 +5,18 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT io.spring.sample function-sample-aws-custom-bean - 3.0.0.RELEASE + 4.0.0.RELEASE AWS Custom Runtime - @Bean sample Demo project for Spring Cloud Function with custom AWS Lambda runtime using @Bean style - 1.8 1.0.27.RELEASE - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT @@ -28,7 +27,7 @@ --> com.amazonaws aws-lambda-java-events - 2.2.6 + 3.9.0 @@ -106,34 +105,38 @@ - - - integration - - - - maven-surefire-plugin - 2.22.0 - - - integration-test - - test - - - - none - - - com/example/ContainerTests.java - - - - - - - - - - + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + + spring-releases + Spring Releases + https://repo.spring.io/release + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + + spring-releases + Spring Releases + https://repo.spring.io/libs-release-local + + diff --git a/spring-cloud-function-samples/function-sample-aws-custom/pom.xml b/spring-cloud-function-samples/function-sample-aws-custom/pom.xml index fc70937b9..98eff2eed 100644 --- a/spring-cloud-function-samples/function-sample-aws-custom/pom.xml +++ b/spring-cloud-function-samples/function-sample-aws-custom/pom.xml @@ -5,19 +5,18 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT io.spring.sample function-sample-aws-custom - 3.0.0.RELEASE + 4.0.0.RELEASE function-sample-aws-custom Demo project for Spring Cloud Function with custom AWS Lambda runtime - 1.8 1.0.27.RELEASE - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT @@ -33,6 +32,14 @@ org.springframework.boot spring-boot-starter-web +<<<<<<< HEAD +======= + + + jakarta.servlet + jakarta.servlet-api + provided +>>>>>>> 4.x @@ -43,30 +50,11 @@ spring-boot-starter - - - org.springframework.boot spring-boot-starter-test test - - - - - - - - - - - - - - - - @@ -167,28 +155,16 @@ spring-snapshots Spring Snapshots https://repo.spring.io/libs-snapshot-local - - true - - - false - spring-milestones Spring Milestones https://repo.spring.io/libs-milestone-local - - false - spring-releases Spring Releases https://repo.spring.io/release - - false - diff --git a/spring-cloud-function-samples/function-sample-aws-custom/src/main/java/com/example/LambdaApplication.java b/spring-cloud-function-samples/function-sample-aws-custom/src/main/java/com/example/LambdaApplication.java index 730053793..3d6ed1751 100644 --- a/spring-cloud-function-samples/function-sample-aws-custom/src/main/java/com/example/LambdaApplication.java +++ b/spring-cloud-function-samples/function-sample-aws-custom/src/main/java/com/example/LambdaApplication.java @@ -7,8 +7,8 @@ import org.apache.commons.logging.LogFactory; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionType; import org.springframework.cloud.function.context.FunctionalSpringApplication; +import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.support.GenericApplicationContext; @@ -32,7 +32,6 @@ public class LambdaApplication @Override public void initialize(GenericApplicationContext context) { context.registerBean("uppercase", FunctionRegistration.class, - () -> new FunctionRegistration<>(uppercase()).type( - FunctionType.from(String.class).to(String.class))); + () -> new FunctionRegistration<>(uppercase()).type(FunctionTypeUtils.functionType(String.class, String.class))); } } diff --git a/spring-cloud-function-samples/function-sample-aws-routing/pom.xml b/spring-cloud-function-samples/function-sample-aws-routing/pom.xml index 3e0304a30..aa8bb8b1e 100644 --- a/spring-cloud-function-samples/function-sample-aws-routing/pom.xml +++ b/spring-cloud-function-samples/function-sample-aws-routing/pom.xml @@ -6,7 +6,7 @@ io.spring.sample function-sample-aws-routing - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample-aws-routing @@ -15,17 +15,16 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT UTF-8 UTF-8 - 1.8 1.0.27.RELEASE 2.0.2 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-aws/pom.xml b/spring-cloud-function-samples/function-sample-aws/pom.xml index 4653b95c5..b9bd8a07b 100644 --- a/spring-cloud-function-samples/function-sample-aws/pom.xml +++ b/spring-cloud-function-samples/function-sample-aws/pom.xml @@ -6,7 +6,7 @@ io.spring.sample function-sample-aws - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample-aws @@ -15,17 +15,16 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT UTF-8 UTF-8 - 1.8 1.0.27.RELEASE 3.9.0 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-azure/pom.xml b/spring-cloud-function-samples/function-sample-azure/pom.xml index fa3844956..5d49dcc99 100644 --- a/spring-cloud-function-samples/function-sample-azure/pom.xml +++ b/spring-cloud-function-samples/function-sample-azure/pom.xml @@ -6,7 +6,7 @@ io.spring.sample function-sample-azure - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample-azure @@ -14,12 +14,11 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT - 1.8 function-sample-azure westus java-function-group @@ -54,7 +53,7 @@ org.springframework.cloud spring-cloud-function-dependencies - 3.2.1-SNAPSHOT + 4.0.0-SNAPSHOT pom import diff --git a/spring-cloud-function-samples/function-sample-azure/src/test/java/example/MapTests.java b/spring-cloud-function-samples/function-sample-azure/src/test/java/example/MapTests.java deleted file mode 100644 index c7f3e893f..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/test/java/example/MapTests.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012-2020 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 - * - * https://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 example; - -import com.microsoft.azure.functions.ExecutionContext; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import java.util.logging.Logger; -import static org.assertj.core.api.Assertions.assertThat; - -import org.springframework.cloud.function.adapter.azure.AzureSpringBootRequestHandler; - -/** - * @author Dave Syer - * - */ -public class MapTests { - - @Test - public void start() throws Exception { - AzureSpringBootRequestHandler handler = new AzureSpringBootRequestHandler<>( - Config.class); - ExecutionContext ec = new ExecutionContext() { - @Override - public Logger getLogger() { - return Logger.getAnonymousLogger(); - } - - @Override - public String getInvocationId() { - return "id1"; - } - - @Override - public String getFunctionName() { - return "uppercase"; - } - }; - - String result = handler.handleRequest("{\"greeting\": \"hello\",\"name\": \"your_name\"}", ec); - handler.close(); - assertThat(result).isEqualTo("{\"greeting\":\"HELLO\",\"name\":\"YOUR_NAME\"}"); - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/pom.xml b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/pom.xml index e81cb2cfd..67ba27e59 100644 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/pom.xml +++ b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/pom.xml @@ -12,13 +12,12 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT - 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE @@ -28,7 +27,6 @@ org.springframework.cloud spring-cloud-function-rsocket - 3.1.0-SNAPSHOT @@ -37,7 +35,7 @@ org.springframework.cloud spring-cloud-stream-binder-kafka - 3.1.0-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/pom.xml b/spring-cloud-function-samples/function-sample-cloudevent-stream/pom.xml index 3d6289177..5eb646eb9 100644 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/pom.xml +++ b/spring-cloud-function-samples/function-sample-cloudevent-stream/pom.xml @@ -4,20 +4,19 @@ 4.0.0 io.spring.sample function-sample-cloudevent-stream - 0.0.1-SNAPSHOT + 4.0.0-RELEASE function-sample-cloudevent-stream Demo project for Spring Boot org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT - 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE @@ -29,13 +28,13 @@ org.springframework.cloud spring-cloud-stream - 3.2.0-M2 + 4.0.0-SNAPSHOT org.springframework.cloud spring-cloud-stream-binder-rabbit - 3.2.0-M2 + 4.0.0-SNAPSHOT @@ -43,7 +42,7 @@ org.springframework.cloud spring-cloud-stream-binder-kafka - 3.2.0-M2 + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-cloudevent/pom.xml b/spring-cloud-function-samples/function-sample-cloudevent/pom.xml index 8e9675a83..834e4aa9e 100644 --- a/spring-cloud-function-samples/function-sample-cloudevent/pom.xml +++ b/spring-cloud-function-samples/function-sample-cloudevent/pom.xml @@ -11,13 +11,12 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT - 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE diff --git a/spring-cloud-function-samples/function-sample-compiler/pom.xml b/spring-cloud-function-samples/function-sample-compiler/pom.xml index b8958a7b2..09769fcd7 100644 --- a/spring-cloud-function-samples/function-sample-compiler/pom.xml +++ b/spring-cloud-function-samples/function-sample-compiler/pom.xml @@ -19,8 +19,7 @@ - 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 3.1.2.RELEASE 1.0.17.RELEASE diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/pom.xml b/spring-cloud-function-samples/function-sample-functional-aws-routing/pom.xml index a148ca0f0..171f4cc3b 100644 --- a/spring-cloud-function-samples/function-sample-functional-aws-routing/pom.xml +++ b/spring-cloud-function-samples/function-sample-functional-aws-routing/pom.xml @@ -6,7 +6,7 @@ io.spring.sample function-sample-functional-aws-routing - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample-functional-aws-routing @@ -15,17 +15,16 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT UTF-8 UTF-8 - 1.8 1.0.27.RELEASE 2.0.2 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-gcp-background/pom.xml b/spring-cloud-function-samples/function-sample-gcp-background/pom.xml index 29568d01b..1fa44627a 100644 --- a/spring-cloud-function-samples/function-sample-gcp-background/pom.xml +++ b/spring-cloud-function-samples/function-sample-gcp-background/pom.xml @@ -7,7 +7,7 @@ io.spring.sample function-sample-gcp-background - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample-gcp-background @@ -15,7 +15,7 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT @@ -23,7 +23,7 @@ org.springframework.cloud spring-cloud-function-adapter-gcp - 3.1.0-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-gcp-http/pom.xml b/spring-cloud-function-samples/function-sample-gcp-http/pom.xml index 01a5e6403..83aabb207 100644 --- a/spring-cloud-function-samples/function-sample-gcp-http/pom.xml +++ b/spring-cloud-function-samples/function-sample-gcp-http/pom.xml @@ -7,7 +7,7 @@ io.spring.sample function-sample-gcp-http - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample-gcp-http @@ -15,7 +15,7 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT @@ -27,7 +27,7 @@ org.springframework.cloud spring-cloud-function-adapter-gcp - ${spring-cloud-function.version} + 4.0.0-SNAPSHOT @@ -63,7 +63,6 @@ maven-deploy-plugin - 2.8.2 true diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/pom.xml b/spring-cloud-function-samples/function-sample-grpc-cloudevent/pom.xml index eade0e637..ca001c973 100644 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/pom.xml +++ b/spring-cloud-function-samples/function-sample-grpc-cloudevent/pom.xml @@ -7,17 +7,16 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT com.example.grpc function-sample-grpc-cloudevent - 0.0.1-RELEASE + 4.0.0-RELEASE function-sample-grpc-cloudevent Demo project for Spring Boot - 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/pom.xml b/spring-cloud-function-samples/function-sample-kotlin-web/pom.xml index b80bfa41f..3b081c326 100644 --- a/spring-cloud-function-samples/function-sample-kotlin-web/pom.xml +++ b/spring-cloud-function-samples/function-sample-kotlin-web/pom.xml @@ -4,22 +4,17 @@ 4.0.0 io.spring.sample function-sample-kotlin-web - 1.0 + 4.0.0 function-sample-kotlin-web Demo project for Spring Cloud Function Web Kotlin integration org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT - - 1.8 - 1.4.21 - - org.springframework.boot @@ -28,27 +23,25 @@ org.jetbrains.kotlin kotlin-reflect - 1.6.0 org.jetbrains.kotlin kotlin-stdlib-jdk8 - 1.6.0 org.springframework.cloud spring-cloud-function-kotlin - 3.2.1-SNAPSHOT + 4.0.0-SNAPSHOT org.springframework.cloud spring-cloud-function-web - 3.2.1-SNAPSHOT + 4.0.0-SNAPSHOT org.springframework.cloud spring-cloud-function-context - 3.2.1-SNAPSHOT + 4.0.0-SNAPSHOT org.springframework.boot @@ -79,7 +72,6 @@ org.jetbrains.kotlin kotlin-maven-plugin - 1.6.0 -Xjsr305=strict @@ -92,11 +84,46 @@ org.jetbrains.kotlin kotlin-maven-allopen - ${kotlin.version} + 1.4.21 + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + + spring-releases + Spring Releases + https://repo.spring.io/release + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + + spring-releases + Spring Releases + https://repo.spring.io/libs-release-local + + diff --git a/spring-cloud-function-samples/function-sample-pof/pom.xml b/spring-cloud-function-samples/function-sample-pof/pom.xml index 45b53f715..1c37adfda 100644 --- a/spring-cloud-function-samples/function-sample-pof/pom.xml +++ b/spring-cloud-function-samples/function-sample-pof/pom.xml @@ -5,7 +5,7 @@ io.spring.sample function-sample-pof - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample-pof Spring Cloud Function Web Support @@ -13,16 +13,15 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT UTF-8 UTF-8 - 1.8 3.1.2.RELEASE - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-pojo/pom.xml b/spring-cloud-function-samples/function-sample-pojo/pom.xml index fd25c5a77..af9744684 100644 --- a/spring-cloud-function-samples/function-sample-pojo/pom.xml +++ b/spring-cloud-function-samples/function-sample-pojo/pom.xml @@ -6,7 +6,7 @@ io.spring.sample function-sample-pojo - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample-pojo Spring Cloud Function Web Support @@ -14,13 +14,12 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT - 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.27.RELEASE diff --git a/spring-cloud-function-samples/function-sample-spring-integration/pom.xml b/spring-cloud-function-samples/function-sample-spring-integration/pom.xml index 6c0ea20e9..5bf55023b 100644 --- a/spring-cloud-function-samples/function-sample-spring-integration/pom.xml +++ b/spring-cloud-function-samples/function-sample-spring-integration/pom.xml @@ -20,7 +20,7 @@ UTF-8 UTF-8 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml b/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml index 38aafb06d..88053396f 100644 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml +++ b/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml @@ -6,7 +6,7 @@ io.spring.sample function-sample-aws-supplier-exporter - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample-aws-supplier-exporter Spring Cloud Function Example showing Supplier Exporter @@ -14,13 +14,12 @@ org.springframework.boot spring-boot-starter-parent - 2.6.1 + 3.0.0-SNAPSHOT - 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT @@ -119,4 +118,38 @@ + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + + spring-releases + Spring Releases + https://repo.spring.io/release + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + + spring-releases + Spring Releases + https://repo.spring.io/libs-release-local + + diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/java/com/example/demo/DemoApplication.java b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/java/com/example/demo/DemoApplication.java index d41f097c4..fd7b20ea4 100644 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/java/com/example/demo/DemoApplication.java +++ b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/java/com/example/demo/DemoApplication.java @@ -4,8 +4,8 @@ import java.util.function.Function; import org.springframework.boot.SpringBootConfiguration; import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionType; import org.springframework.cloud.function.context.FunctionalSpringApplication; +import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.support.GenericApplicationContext; @@ -21,7 +21,7 @@ public class DemoApplication public void initialize(GenericApplicationContext context) { context.registerBean("foobar", FunctionRegistration.class, () -> new FunctionRegistration<>(new Foobar()) - .type(FunctionType.from(Foo.class).to(Foo.class))); + .type(FunctionTypeUtils.functionType(Foo.class, Foo.class))); } } diff --git a/spring-cloud-function-samples/function-sample-task/pom.xml b/spring-cloud-function-samples/function-sample-task/pom.xml index bfa512c92..594b265f6 100644 --- a/spring-cloud-function-samples/function-sample-task/pom.xml +++ b/spring-cloud-function-samples/function-sample-task/pom.xml @@ -20,7 +20,7 @@ 1.8 - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT 1.0.10.RELEASE 3.1.2.RELEASE diff --git a/spring-cloud-function-samples/function-sample/pom.xml b/spring-cloud-function-samples/function-sample/pom.xml index 8a89e86c0..b254a9ca4 100644 --- a/spring-cloud-function-samples/function-sample/pom.xml +++ b/spring-cloud-function-samples/function-sample/pom.xml @@ -6,7 +6,7 @@ io.spring.sample function-sample - 2.0.0.RELEASE + 4.0.0.RELEASE jar function-sample Spring Cloud Function Web Support @@ -14,13 +14,21 @@ org.springframework.boot spring-boot-starter-parent +<<<<<<< HEAD 2.6.1 +======= + 3.0.0-SNAPSHOT +>>>>>>> 4.x +<<<<<<< HEAD 1.8 3.2.2-SNAPSHOT +======= + 4.0.0-SNAPSHOT +>>>>>>> 4.x 1.0.27.RELEASE diff --git a/spring-cloud-function-samples/pom.xml b/spring-cloud-function-samples/pom.xml index 69fdcc2c5..9185ddc07 100644 --- a/spring-cloud-function-samples/pom.xml +++ b/spring-cloud-function-samples/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-task/pom.xml b/spring-cloud-function-task/pom.xml index fef2cfda4..5731b90d5 100644 --- a/spring-cloud-function-task/pom.xml +++ b/spring-cloud-function-task/pom.xml @@ -12,7 +12,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/spring-cloud-function-web/pom.xml b/spring-cloud-function-web/pom.xml index 6ae02e9f2..d22873fde 100644 --- a/spring-cloud-function-web/pom.xml +++ b/spring-cloud-function-web/pom.xml @@ -12,10 +12,15 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT + + jakarta.servlet + jakarta.servlet-api + provided + org.springframework spring-webmvc @@ -35,11 +40,6 @@ org.springframework.cloud spring-cloud-function-context - - javax.servlet - javax.servlet-api - provided - commons-logging commons-logging diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RequestProcessor.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RequestProcessor.java deleted file mode 100644 index 138a8b617..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RequestProcessor.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2017-2020 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 - * - * https://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.lang.reflect.Type; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.Supplier; -import java.util.stream.Stream; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.message.MessageUtils; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.cloud.function.web.util.FunctionWebRequestProcessingHelper; -import org.springframework.cloud.function.web.util.HeaderUtils; -import org.springframework.core.ResolvableType; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.http.ResponseEntity.BodyBuilder; -import org.springframework.http.codec.ServerCodecConfigurer; -import org.springframework.messaging.Message; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class RequestProcessor { - - private static Log logger = LogFactory.getLog(RequestProcessor.class); - - private final JsonMapper mapper; - - public RequestProcessor(JsonMapper mapper, - ObjectProvider codecs) { - this.mapper = mapper; - } - - public static FunctionWrapper wrapper(FunctionInvocationWrapper function) { - return new FunctionWrapper(function); - } - - @SuppressWarnings("rawtypes") - public Mono> get(FunctionWrapper wrapper) { - if (wrapper.function().isFunction()) { - return response(wrapper, wrapper.function(), invokeFunction(wrapper), true, true); - } - else { - FunctionInvocationWrapper function = (wrapper.function); - Object result = FunctionWebRequestProcessingHelper.invokeFunction(function, null, false); - return response(wrapper, wrapper.function(), result instanceof Publisher ? (Publisher) result : Flux.just(result), null, - true); - } - - } - - public Mono> post(FunctionWrapper wrapper, String body, - boolean stream) { - FunctionInvocationWrapper function = (FunctionInvocationWrapper) wrapper.handler(); - Type itemType = function != null ? function.getItemType(function.getInputType()) : Object.class; - - Object input = body == null ? "" : body; - - /* - * We need this to ensure that imperative function which are sent array-like input - * can be invoked with each item and then aggregated - */ - if (input != null && JsonMapper.isJsonStringRepresentsCollection(input)) { - Type type = FunctionTypeUtils.isTypeCollection(itemType) - ? ResolvableType.forType(itemType).getType() - : ResolvableType.forClassWithGenerics(Collection.class, ResolvableType.forType(itemType)).asCollection().getType(); - input = this.mapper.fromJson((String) input, type); - } - - return response(wrapper, input, stream); - } - - public Mono> stream(FunctionWrapper functionWrapper) { - Publisher result = functionWrapper.function.isFunction() - ? invokeFunction(functionWrapper) - : (Publisher) functionWrapper.function.get(); - return stream(functionWrapper, result); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Mono> response(FunctionWrapper wrapper, Object body, boolean stream) { - - FunctionInvocationWrapper function = (wrapper.function()); - Flux flux; - Class inputType = function == null - ? Object.class - : FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(function.getInputType())); - if (MultiValueMap.class.isAssignableFrom(inputType)) { - body = null; - flux = Flux.just(wrapper.params()); - } - else if (body != null) { - if (Collection.class.isAssignableFrom(inputType)) { - flux = Flux.just(body); - } - else if (body instanceof Flux) { - flux = Flux.from((Flux) body); - } - else { - Iterable iterable = body instanceof Collection - ? (Collection) body - : Collections.singletonList(body); - flux = Flux.fromIterable(iterable); - } - } - else { - throw new IllegalStateException( - "Failed to determine input for function call with parameters: '" - + wrapper.params + "' and headers: `" + wrapper.headers - + "`"); - } - - if (function != null) { - flux = messages(wrapper, function, flux); - } - Mono> responseEntityMono = null; - - if (function == null) { - responseEntityMono = Mono.just(ResponseEntity.status(HttpStatus.NOT_FOUND) - .body("Function for provided path can not be found")); - } - else { - Publisher result = (Publisher) FunctionWebRequestProcessingHelper.invokeFunction(function, flux, function.isInputTypeMessage()); - if (function.isConsumer()) { - if (result != null) { - ((Mono) result).subscribe(); - } - logger.debug("Handled POST with consumer"); - responseEntityMono = Mono.just(ResponseEntity.status(HttpStatus.ACCEPTED).build()); - } - else { - result = Flux.from((Publisher) result); - logger.debug("Handled POST with function: " + function); - if (stream) { - responseEntityMono = stream(wrapper, result); - } - else { - responseEntityMono = response(wrapper, function, result, - body == null ? null : !(body instanceof Collection), false); - } - } - } - return responseEntityMono; - } - - private Mono> response(FunctionWrapper request, Object handler, - Publisher result, Boolean single, boolean getter) { - BodyBuilder builder = ResponseEntity.ok(); - if (result instanceof Mono) { - result = Mono.from(result) - .map(message -> MessageUtils.unpack(handler, message)) - .doOnNext(value -> { - addHeaders(builder, value); - if (!isValidCloudEvent(value.getHeaders().keySet())) { -// builder.headers(HeaderUtils.sanitize(request.headers())); - } - }) - .map(message -> message.getPayload()); - } - else { - result = Flux.from(result) - .map(message -> MessageUtils.unpack(handler, message)) - .doOnNext(value -> { - addHeaders(builder, value); - if (!isValidCloudEvent(value.getHeaders().keySet())) { -// builder.headers(HeaderUtils.sanitize(request.headers())); - } - }) - .map(message -> message.getPayload()); - } - - if (isOutputSingle(handler) - && (single != null && single || getter || isInputMultiple(handler))) { - result = Mono.from(result); - } - - if (result instanceof Flux) { - result = Flux.from(result).onErrorContinue((e, v) -> { - logger.error("Failed to process value: " + v, e); - }) - .collectList(); - } - return Mono.from(result).flatMap(body -> Mono.just(builder.body(body))); - } - - private boolean isValidCloudEvent(Set headerKeys) { - return headerKeys.contains("ce-id") - && headerKeys.contains("ce-source") - && headerKeys.contains("ce-type") - && headerKeys.contains("ce-specversion"); - } - - // this seem to be very relevant to AWS container tests - private Flux messages(FunctionWrapper request, Object function, Flux flux) { - Map headers = new HashMap<>(HeaderUtils.fromHttp(request.headers())); - if (function instanceof FunctionInvocationWrapper) { - headers.put("scf-func-name", ((FunctionInvocationWrapper) function).getFunctionDefinition()); - } - return flux.map(payload -> MessageUtils.create(function, payload, headers)); - } - - private void addHeaders(BodyBuilder builder, Message message) { - builder.headers(HeaderUtils.fromMessage(message.getHeaders())); - } - - private Mono> stream(FunctionWrapper request, Publisher result) { - BodyBuilder builder = ResponseEntity.ok(); - if (((FunctionInvocationWrapper) request.handler()).isInputTypeMessage()) { - result = Flux.from(result) - .doOnNext(value -> addHeaders(builder, (Message) value)) - .map(message -> MessageUtils.unpack(request.handler(), message) - .getPayload()); - } - else { - builder.headers(HeaderUtils.sanitize(request.headers())); - } - - Publisher output = result; - return Flux.from(output).then(Mono.fromSupplier(() -> builder.body(output))); - } - - - - private boolean isInputMultiple(Object handler) { - FunctionInvocationWrapper function = (FunctionInvocationWrapper) handler; - Class type = function == null ? Object.class : FunctionTypeUtils - .getRawType(FunctionTypeUtils.getGenericType(function.getInputType())); - return Collection.class.isAssignableFrom(type) || (function != null && FunctionTypeUtils.isFlux(function.getInputType())); - - } - - private boolean isOutputSingle(Object handler) { - FunctionInvocationWrapper function = (FunctionInvocationWrapper) handler; - Type outputType = function.getOutputType(); - Class type = FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(outputType)); - Class wrapper = function.isOutputTypePublisher() ? FunctionTypeUtils.getRawType(outputType) : type; - if (Stream.class.isAssignableFrom(type)) { - return false; - } - else { - return wrapper == type || Mono.class.equals(wrapper) - || Optional.class.equals(wrapper); - } - } - - private Publisher invokeFunction(FunctionWrapper wrapper) { - if (wrapper.argument != null) { - Flux input = Flux.from(wrapper.argument); - Object result = FunctionWebRequestProcessingHelper.invokeFunction(wrapper.function, input, wrapper.function.isInputTypeMessage()); - return Mono.from((Publisher) result); - } - else { - return Mono.empty(); - } - } - - /** - * Wrapper for functions. - */ - public static class FunctionWrapper { - - private final FunctionInvocationWrapper function; - - private final MultiValueMap params = new LinkedMultiValueMap<>(); - - private HttpHeaders headers = new HttpHeaders(); - - private Publisher argument; - - public FunctionWrapper(FunctionInvocationWrapper function) { - this.function = function; - } - - public Object handler() { - return this.function; - } - - public FunctionInvocationWrapper function() { - return this.function; - } - - @Deprecated - public Supplier supplier() { - return this.function; - } - - public MultiValueMap params() { - return this.params; - } - - public HttpHeaders headers() { - return this.headers; - } - - public FunctionWrapper headers(HttpHeaders headers) { - this.headers = headers; - return this; - } - - public FunctionWrapper params(MultiValueMap params) { - this.params.addAll(params); - return this; - } - - public FunctionWrapper argument(Publisher argument) { - this.argument = argument; - return this; - } - - public FunctionWrapper argument(String argument) { - this.argument = Mono.just(argument); - return this; - } - - public Publisher argument() { - return this.argument; - } - } -} 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 899b92c15..83e466b13 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 @@ -41,11 +41,9 @@ import org.springframework.cloud.function.context.FunctionalSpringApplication; import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; import org.springframework.cloud.function.context.config.ContextFunctionCatalogInitializer; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.cloud.function.web.RequestProcessor; -import org.springframework.cloud.function.web.RequestProcessor.FunctionWrapper; import org.springframework.cloud.function.web.constants.WebRequestConstants; import org.springframework.cloud.function.web.util.FunctionWebRequestProcessingHelper; +import org.springframework.cloud.function.web.util.FunctionWrapper; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationEvent; @@ -104,12 +102,9 @@ public class FunctionEndpointInitializer implements ApplicationContextInitialize } private void registerEndpoint(GenericApplicationContext context) { - context.registerBean(RequestProcessor.class, - () -> new RequestProcessor(context.getBeansOfType(JsonMapper.class).values().iterator().next(), - context.getBeanProvider(ServerCodecConfigurer.class))); context.registerBean(FunctionEndpointFactory.class, () -> new FunctionEndpointFactory(context.getBean(FunctionProperties.class), context.getBean(FunctionCatalog.class), - context.getBean(RequestProcessor.class), context.getEnvironment())); + context.getEnvironment())); RouterFunctionRegister.register(context); } @@ -204,16 +199,13 @@ class FunctionEndpointFactory { private final String handler; - private final RequestProcessor processor; - private final FunctionProperties functionProperties; - FunctionEndpointFactory(FunctionProperties functionProperties, FunctionCatalog functionCatalog, RequestProcessor processor, Environment environment) { + FunctionEndpointFactory(FunctionProperties functionProperties, FunctionCatalog functionCatalog, Environment environment) { String handler = environment.resolvePlaceholders("${function.handler}"); if (handler.startsWith("$")) { handler = null; } - this.processor = processor; this.functionCatalog = functionCatalog; this.handler = handler; this.functionProperties = functionProperties; @@ -241,9 +233,10 @@ class FunctionEndpointFactory { FunctionInvocationWrapper funcWrapper = extract(request); Class outputType = funcWrapper == null ? Object.class : FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(funcWrapper.getOutputType())); - FunctionWrapper wrapper = RequestProcessor.wrapper(funcWrapper); + FunctionWrapper wrapper = new FunctionWrapper(funcWrapper); Mono> stream = request.bodyToMono(String.class) - .flatMap(content -> this.processor.post(wrapper, content, false)); + .flatMap(content -> (Mono>) FunctionWebRequestProcessingHelper.processRequest(wrapper, content, false)); + return stream.flatMap(entity -> { BodyBuilder builder = status(entity.getStatusCode()).headers(headers -> headers.addAll(entity.getHeaders())); if (outputType == null) { // consumer @@ -265,11 +258,12 @@ class FunctionEndpointFactory { return ServerResponse.ok().body(result, outputType); } else { - FunctionWrapper wrapper = RequestProcessor.wrapper(funcWrapper); - wrapper.headers(request.headers().asHttpHeaders()); + FunctionWrapper wrapper = new FunctionWrapper(funcWrapper); + + wrapper.setHeaders(request.headers().asHttpHeaders()); String argument = (String) request.attribute(WebRequestConstants.ARGUMENT).get(); - wrapper.argument(Flux.just(argument)); - Object result = FunctionWebRequestProcessingHelper.invokeFunction(funcWrapper, wrapper.argument(), + wrapper.setArgument(Flux.just(argument)); + Object result = FunctionWebRequestProcessingHelper.invokeFunction(funcWrapper, wrapper.getArgument(), funcWrapper.isInputTypeMessage()); return ServerResponse.ok().body(result, outputType); } diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionHandlerMapping.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionHandlerMapping.java index f22f2e2db..0423d9710 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionHandlerMapping.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionHandlerMapping.java @@ -18,7 +18,7 @@ package org.springframework.cloud.function.web.mvc; import java.util.HashMap; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; @@ -35,6 +35,8 @@ import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + + /** * @author Dave Syer * @author Oleg Zhurakousky diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterAutoConfiguration.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterAutoConfiguration.java index 92f112953..9d65de859 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterAutoConfiguration.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterAutoConfiguration.java @@ -30,7 +30,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.function.context.FunctionCatalog; import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionType; +import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; import org.springframework.cloud.function.web.source.FunctionExporterAutoConfiguration.SourceActiveCondition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @@ -70,10 +70,11 @@ public class FunctionExporterAutoConfiguration { FunctionRegistration>> registration = new FunctionRegistration<>(supplier); Type rawType = ResolvableType.forClassWithGenerics(Supplier.class, this.props.getSource().getType()).getType(); // FunctionType functionType = FunctionType.supplier(this.props.getSource().getType()).wrap(Flux.class); - FunctionType type = FunctionType.of(rawType); - if (this.props.getSource().isIncludeHeaders()) { -// type = type.message(); - } +// FunctionType type = FunctionType.of(rawType); +// if (this.props.getSource().isIncludeHeaders()) { +//// type = type.message(); +// } + Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(HttpSupplier.class); registration = registration.type(type); return registration; } diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWebRequestProcessingHelper.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWebRequestProcessingHelper.java index b459a6954..b78037908 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWebRequestProcessingHelper.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWebRequestProcessingHelper.java @@ -87,6 +87,10 @@ public final class FunctionWebRequestProcessingHelper { public static Object processRequest(FunctionWrapper wrapper, Object argument, boolean eventStream) { FunctionInvocationWrapper function = wrapper.getFunction(); + if (function == null) { + return Mono.just(ResponseEntity.notFound().build()); + } + HttpHeaders headers = wrapper.getHeaders(); Message inputMessage = argument == null ? null : MessageBuilder.withPayload(argument).copyHeaders(headers.toSingleValueMap()).build(); diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalExporterTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalExporterTests.java index a75d0806d..de952b7f4 100644 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalExporterTests.java +++ b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalExporterTests.java @@ -16,6 +16,8 @@ package org.springframework.cloud.function.test; +import java.lang.reflect.Method; +import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; import java.util.function.Function; @@ -29,7 +31,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionType; +import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; import org.springframework.cloud.function.context.test.FunctionalSpringBootTest; import org.springframework.cloud.function.test.FunctionalExporterTests.ApplicationConfiguration; import org.springframework.cloud.function.web.source.SupplierExporter; @@ -38,6 +40,7 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.messaging.Message; import org.springframework.messaging.support.MessageBuilder; +import org.springframework.util.ReflectionUtils; import org.springframework.util.SocketUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -114,8 +117,16 @@ public class FunctionalExporterTests { @Override public void initialize(GenericApplicationContext context) { context.registerBean("uppercase", FunctionRegistration.class, - () -> new FunctionRegistration<>(uppercase()).type( - FunctionType.from(Person.class).to(String.class).message())); + () -> new FunctionRegistration<>(uppercase()) + .type(FunctionTypeUtils.discoverFunctionTypeFromFunctionFactoryMethod(this.getClass(), "uppercase"))); + } + + public static Type discoverFunctionTypeFromFunctionFactoryMethod(Class clazz, String methodName) { + return discoverFunctionTypeFromFunctionFactoryMethod(ReflectionUtils.findMethod(clazz, methodName)); + } + + public static Type discoverFunctionTypeFromFunctionFactoryMethod(Method method) { + return method.getGenericReturnType(); } } diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerTests.java index 721ae6e23..28e3a65c6 100644 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerTests.java +++ b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2019 the original author or authors. + * Copyright 2019-2021 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. @@ -28,8 +28,8 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionType; import org.springframework.cloud.function.context.FunctionalSpringApplication; +import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.support.GenericApplicationContext; import org.springframework.http.HttpStatus; @@ -169,18 +169,19 @@ public class FunctionEndpointInitializerTests { @Override public void initialize(GenericApplicationContext applicationContext) { + applicationContext.registerBean("uppercase", FunctionRegistration.class, () -> new FunctionRegistration<>(uppercase()) - .type(FunctionType.from(String.class).to(String.class))); + .type(FunctionTypeUtils.functionType(String.class, String.class))); applicationContext.registerBean("reverse", FunctionRegistration.class, () -> new FunctionRegistration<>(reverse()) - .type(FunctionType.from(String.class).to(String.class))); + .type(FunctionTypeUtils.functionType(String.class, String.class))); applicationContext.registerBean("lowercase", FunctionRegistration.class, () -> new FunctionRegistration<>(lowercase()) - .type(FunctionType.from(String.class).to(String.class))); + .type(FunctionTypeUtils.functionType(String.class, String.class))); applicationContext.registerBean("supplier", FunctionRegistration.class, () -> new FunctionRegistration<>(supplier()) - .type(FunctionType.supplier(String.class))); + .type(FunctionTypeUtils.supplierType(String.class))); } } diff --git a/spring-cloud-starter-function-web/pom.xml b/spring-cloud-starter-function-web/pom.xml index 169661b40..04fa6ce0b 100644 --- a/spring-cloud-starter-function-web/pom.xml +++ b/spring-cloud-starter-function-web/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT .. spring-cloud-starter-function-web diff --git a/spring-cloud-starter-function-webflux/pom.xml b/spring-cloud-starter-function-webflux/pom.xml index 69b8e3e57..994b8bf30 100644 --- a/spring-cloud-starter-function-webflux/pom.xml +++ b/spring-cloud-starter-function-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-function-parent - 3.2.2-SNAPSHOT + 4.0.0-SNAPSHOT spring-cloud-starter-function-webflux spring-cloud-starter-function-webflux